diff --git a/.circleci/Dockerfiles/Dockerfile.android b/.circleci/Dockerfiles/Dockerfile.android index 431f802e3566dc..5b313b53bfa679 100644 --- a/.circleci/Dockerfiles/Dockerfile.android +++ b/.circleci/Dockerfiles/Dockerfile.android @@ -14,7 +14,7 @@ # and build a Android application that can be used to run the # tests specified in the scripts/ directory. # -FROM reactnativecommunity/react-native-android:2019-10-18 +FROM reactnativecommunity/react-native-android:2.1 LABEL Description="React Native Android Test Image" LABEL maintainer="Héctor Ramos " @@ -25,11 +25,13 @@ ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" ADD .buckconfig /app/.buckconfig ADD .buckjavaargs /app/.buckjavaargs -ADD tools /app/tools +ADD Libraries /app/Libraries ADD ReactAndroid /app/ReactAndroid ADD ReactCommon /app/ReactCommon ADD React /app/React ADD keystores /app/keystores +ADD packages/react-native-codegen /app/packages/react-native-codegen +ADD tools /app/tools WORKDIR /app @@ -49,4 +51,3 @@ RUN yarn RUN ./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog RUN ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1 - diff --git a/.circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh b/.circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh index d51860f1d6f037..b6a2427324e7d2 100644 --- a/.circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh +++ b/.circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh @@ -10,7 +10,7 @@ mount -o remount,exec /dev/shm AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1) # create virtual device -echo no | android create avd -n "$AVD_UUID" -f -t android-19 --abi default/armeabi-v7a +echo no | android create avd -n "$AVD_UUID" -f -t android-21 --abi default/armeabi-v7a # emulator setup emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim & diff --git a/.circleci/Dockerfiles/scripts/run-ci-e2e-tests.sh b/.circleci/Dockerfiles/scripts/run-ci-e2e-tests.sh index 4c12de632141fd..3176638424e7e0 100755 --- a/.circleci/Dockerfiles/scripts/run-ci-e2e-tests.sh +++ b/.circleci/Dockerfiles/scripts/run-ci-e2e-tests.sh @@ -67,11 +67,6 @@ while :; do shift ;; - --tvos) - RUN_IOS=1 - shift - ;; - *) break esac @@ -114,7 +109,7 @@ function e2e_suite() { # create virtual device if ! android list avd | grep "$AVD_UUID" > /dev/null; then - echo no | android create avd -n "$AVD_UUID" -f -t android-19 --abi default/armeabi-v7a + echo no | android create avd -n "$AVD_UUID" -f -t android-21 --abi default/armeabi-v7a fi # newline at end of adb devices call and first line is headers diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f469a546236e7..49c0c6603f4051 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,11 +15,10 @@ defaults: &defaults environment: - GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1 # The public github tokens are publicly visible by design - - PUBLIC_PULLBOT_GITHUB_TOKEN_A: "a6edf8e8d40ce4e8b11a" - - PUBLIC_PULLBOT_GITHUB_TOKEN_B: "150e1341f4dd9c944d2a" - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_token_a "78a72af35445ca3f8180" - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_token_b "b1a98e0bbd56ff1ccba1" - + - PUBLIC_PULLBOT_GITHUB_TOKEN_A: &github_pullbot_token_a "a6edf8e8d40ce4e8b11a" + - PUBLIC_PULLBOT_GITHUB_TOKEN_B: &github_pullbot_token_b "150e1341f4dd9c944d2a" + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_analysisbot_token_a "312d354b5c36f082cfe9" + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_analysisbot_token_b "07973d757026bdd9f196" # ------------------------- # EXECUTORS @@ -28,15 +27,15 @@ executors: nodelts: <<: *defaults docker: - - image: circleci/node:12 + - image: circleci/node:14 nodeprevlts: <<: *defaults docker: - - image: circleci/node:10 + - image: circleci/node:12 reactnativeandroid: <<: *defaults docker: - - image: reactnativecommunity/react-native-android:2019-10-18 + - image: reactnativecommunity/react-native-android:2.1 resource_class: "large" environment: - TERM: "dumb" @@ -45,12 +44,14 @@ executors: - GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError"' - BUILD_THREADS: 2 # Repeated here, as the environment key in this executor will overwrite the one in defaults - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_token_a - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_token_b + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_analysisbot_token_a + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_analysisbot_token_b + - PUBLIC_PULLBOT_GITHUB_TOKEN_A: *github_pullbot_token_a + - PUBLIC_PULLBOT_GITHUB_TOKEN_B: *github_pullbot_token_b reactnativeios: <<: *defaults macos: - xcode: &_XCODE_VERSION "11.6.0" + xcode: &_XCODE_VERSION "12.1.0" # ------------------------- # COMMANDS @@ -76,7 +77,6 @@ commands: - restore_cache: keys: - v4-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} - - v4-yarn-cache-{{ arch }} - run: name: "Yarn: Install Dependencies" command: | @@ -95,7 +95,6 @@ commands: - restore_cache: keys: - v3-buck-v2019.01.10.01-{{ checksum "scripts/circleci/buck_fetch.sh" }}} - - v3-buck-v2019.01.10.01- - run: name: Install BUCK command: | @@ -152,20 +151,20 @@ commands: command: cp packages/rn-tester/Podfile.lock packages/rn-tester/Podfile.lock.bak - restore_cache: keys: - - v1-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }} - - v1-pods-{{ .Environment.CIRCLE_JOB }}- + # The committed lockfile is generated using USE_FRAMEWORKS=0 and USE_HERMES=0 so it could load an outdated cache if a change + # only affects the frameworks or hermes config. To help prevent this also cache based on the content of Podfile. + - v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} - steps: << parameters.steps >> - save_cache: paths: - packages/rn-tester/Pods - key: v1-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }} + key: v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} download_gradle_dependencies: steps: - restore_cache: keys: - v1-gradle-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }} - - v1-gradle- - run: name: Download Dependencies Using Gradle command: ./scripts/circleci/gradle_download_deps.sh @@ -216,12 +215,12 @@ commands: jobs: setup: parameters: - executor: - type: executor - default: nodelts - checkout_type: - type: string - default: node + executor: + type: executor + default: nodelts + checkout_type: + type: string + default: node executor: << parameters.executor >> steps: - checkout @@ -237,17 +236,17 @@ 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: - executor: nodelts + executor: reactnativeandroid steps: - restore_cache_checkout: - checkout_type: node + checkout_type: android - run_yarn - install_github_bot_deps - run: name: Install additional GitHub bot dependencies - command: sudo apt update && sudo apt install -y shellcheck jq + command: apt update && apt install -y shellcheck jq - run: name: Run linters against modified files (analysis-bot) @@ -261,15 +260,14 @@ jobs: DANGER_GITHUB_API_TOKEN="$PUBLIC_PULLBOT_GITHUB_TOKEN_A""$PUBLIC_PULLBOT_GITHUB_TOKEN_B" yarn danger ci --use-github-checks when: always - # ------------------------- # JOBS: Analyze Code # ------------------------- analyze_code: - executor: nodelts + executor: reactnativeandroid steps: - restore_cache_checkout: - checkout_type: node + checkout_type: android - setup_artifacts - run_yarn @@ -278,6 +276,11 @@ jobs: command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml when: always + - run: + name: Lint Java + command: scripts/circleci/exec_swallow_error.sh yarn lint-java --check + when: always + - run: name: Check for errors in code using Flow (iOS) command: yarn flow-check-ios @@ -351,6 +354,9 @@ jobs: use_frameworks: type: boolean default: false + use_hermes: + type: boolean + default: false run_unit_tests: description: Specifies whether unit tests should run. type: boolean @@ -381,7 +387,7 @@ jobs: - run: name: Configure Environment Variables command: | - echo 'export PATH=/usr/local/opt/node@10/bin:$PATH' >> $BASH_ENV + echo 'export PATH=/usr/local/opt/node@12/bin:$PATH' >> $BASH_ENV source $BASH_ENV - with_brew_cache_span: @@ -389,7 +395,7 @@ jobs: - brew_install: package: watchman - brew_install: - package: node@10 + package: node@12 - run: name: "Brew: Tap wix/brew" command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null @@ -407,10 +413,13 @@ jobs: name: Set USE_FRAMEWORKS=1 command: echo "export USE_FRAMEWORKS=1" >> $BASH_ENV - - run: - name: Fetch CocoaPods Specs - command: | - curl https://cocoapods-specs.circleci.com/fetch-cocoapods-repo-from-s3.sh | bash -s cf + - when: + condition: << parameters.use_hermes >> + steps: + - run: + name: Set USE_HERMES=1 + command: echo "export USE_HERMES=1" >> $BASH_ENV + - run: name: Setup the CocoaPods environment command: pod setup @@ -419,11 +428,7 @@ jobs: steps: - run: name: Generate RNTesterPods Workspace - command: cd packages/rn-tester && pod install --verbose - - - run: - name: Generate RNTesterPods Xcode Workspace - command: pushd packages/rn-tester && pod install --verbose && popd + command: cd packages/rn-tester && USE_FABRIC=1 bundle exec pod install --verbose # ------------------------- # Runs iOS unit tests @@ -543,12 +548,13 @@ jobs: name: "Run Tests: Android Unit Tests" command: buck test ReactAndroid/src/test/... --config build.threads=$BUILD_THREADS --xml ./reports/buck/all-results-raw.xml - run: - name: "Run Tests: Android Instrumentation Tests" + name: "Build Tests: Android Instrumentation Tests" + # Here, just build the instrumentation tests. There is a known issue with installing the APK to android-21+ emulator. command: | if [[ ! -e ReactAndroid/src/androidTest/assets/AndroidTestBundle.js ]]; then echo "JavaScript bundle missing, cannot run instrumentation tests. Verify Build JavaScript Bundle step completed successfully."; exit 1; fi - source scripts/android-setup.sh && NO_BUCKD=1 retry3 timeout 300 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS + source scripts/android-setup.sh && NO_BUCKD=1 retry3 timeout 300 buck build ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS # Optionally, run disabled tests - when: @@ -589,7 +595,7 @@ jobs: source ~/.bashrc nvm i node npm i -g yarn - npx envinfo@latest + echo y | npx envinfo@latest yarn run docker-setup-android yarn run docker-build-android @@ -605,11 +611,11 @@ jobs: default: false environment: - ANDROID_HOME: "C:\\Android\\android-sdk" - - ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\19.2.5345600" + - ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\20.1.5948944" - ANDROID_BUILD_VERSION: 28 - ANDROID_TOOLS_VERSION: 29.0.3 - GRADLE_OPTS: -Dorg.gradle.daemon=false - - NDK_VERSION: 19.2.5345600 + - NDK_VERSION: 20.1.5948944 steps: - checkout @@ -625,7 +631,6 @@ jobs: - restore_cache: keys: - v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} - - v1-win-yarn-cache-{{ arch }}- - run: name: "Yarn: Install Dependencies" command: yarn install --frozen-lockfile --non-interactive @@ -642,7 +647,7 @@ jobs: name: Setup Android SDKs command: | sdkmanager --licenses - sdkmanager "system-images;android-19;google_apis;armeabi-v7a" + sdkmanager "system-images;android-21;google_apis;armeabi-v7a" sdkmanager "platforms;android-%ANDROID_BUILD_VERSION%" sdkmanager "build-tools;%ANDROID_TOOLS_VERSION%" sdkmanager "add-ons;addon-google_apis-google-23" @@ -772,23 +777,38 @@ workflows: requires: - setup_android - test_ios: - name: test_ios_unit - run_disabled_tests: false + name: test_ios_unit_jsc run_unit_tests: true requires: - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper + # - test_ios: + # name: test_ios_unit_frameworks_jsc + # use_frameworks: true + # run_unit_tests: true + # requires: + # - setup_ios - test_ios: - name: test_ios_unit_frameworks - use_frameworks: true + name: test_ios_unit_hermes + use_hermes: true run_unit_tests: true requires: - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper + # - test_ios: + # name: test_ios_unit_frameworks_hermes + # use_hermes: true + # use_frameworks: true + # run_unit_tests: true + # requires: + # - setup_ios + # DISABLED: Detox tests need to be fixed # - test_ios: # name: test_ios_detox - # run_disabled_tests: false # run_detox_tests: true # requires: # - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper # - test_ios: # name: test_ios_detox_frameworks # use_frameworks: true @@ -838,11 +858,18 @@ workflows: analysis: jobs: - - setup + - setup: + name: setup_js + + - setup: + name: setup_android + checkout_type: android + executor: reactnativeandroid + # Run lints on every commit other than those to the gh-pages branch - analyze_code: requires: - - setup + - setup_android filters: branches: ignore: gh-pages @@ -850,7 +877,7 @@ workflows: # Run code checks on PRs from forks - analyze_pr: requires: - - setup + - setup_android filters: branches: only: /^pull\/.*$/ @@ -858,7 +885,7 @@ workflows: # Gather coverage - js_coverage: requires: - - setup + - setup_js nightly: triggers: - schedule: diff --git a/.eslintignore b/.eslintignore index a00ba35784f0a1..f1beb735a483c6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,3 @@ -# node_modules ignored by default - **/main.js **/staticBundle.js bots/node_modules @@ -7,7 +5,6 @@ docs/generatedComponentApiDocs.js flow/ Libraries/Renderer/* Libraries/vendor/**/* +node_modules/ packages/*/node_modules -pr-inactivity-bookmarklet.js -question-bookmarklet.js packages/react-native-codegen/lib diff --git a/.eslintrc b/.eslintrc index 47460cc9582009..2c5a51053d8221 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,15 +5,20 @@ "./packages/eslint-config-react-native-community/index.js" ], + "plugins": [ + "@react-native/eslint-plugin-codegen" + ], + "overrides": [ { "files": [ "Libraries/**/*.js", ], - rules: { - '@react-native-community/no-haste-imports': 2, - '@react-native-community/error-subclass-name': 2, - '@react-native-community/platform-colors': 2, + "rules": { + "@react-native-community/no-haste-imports": 2, + "@react-native-community/error-subclass-name": 2, + "@react-native-community/platform-colors": 2, + "@react-native/codegen/react-native-modules": 2 } }, { @@ -40,8 +45,8 @@ ], "env": { "jasmine": true, - "jest": true, - }, - }, - ], + "jest": true + } + } + ] } diff --git a/.flowconfig b/.flowconfig index 75ab9756c8e742..57b81f8dc68cea 100644 --- a/.flowconfig +++ b/.flowconfig @@ -29,9 +29,6 @@ flow/ [options] emoji=true -esproposal.optional_chaining=enable -esproposal.nullish_coalescing=enable - exact_by_default=true module.file_ext=.js @@ -50,8 +47,6 @@ suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_type=$FlowFixMeEmpty -well_formed_exports=true -types_first=true experimental.abstract_locations=true [lints] @@ -75,4 +70,4 @@ untyped-import untyped-type-import [version] -^0.133.0 +^0.143.1 diff --git a/.flowconfig.android b/.flowconfig.android index 622c4e6b937556..f537518f8504b8 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -29,9 +29,6 @@ flow/ [options] emoji=true -esproposal.optional_chaining=enable -esproposal.nullish_coalescing=enable - exact_by_default=true module.file_ext=.js @@ -50,8 +47,6 @@ suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_type=$FlowFixMeEmpty -well_formed_exports=true -types_first=true experimental.abstract_locations=true [lints] @@ -75,4 +70,4 @@ untyped-import untyped-type-import [version] -^0.133.0 +^0.143.1 diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 4e313c997e3094..e597d1e3334e5a 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -27,7 +27,7 @@ If you'd like to discuss topics related to the future of React Native, please ch If you want to participate in casual discussions about the use of React Native, consider participating in one of the following forums: -- [Reactiflux Discord Server](https://www.reactiflux) +- [Reactiflux Discord Server](https://www.reactiflux.com) - [Spectrum Chat](https://spectrum.chat/react-native) - [React Native Community Facebook Group](https://www.facebook.com/groups/react.native.community) diff --git a/.gitignore b/.gitignore index ad00da2eefa7e0..e71831ae100198 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ project.xcworkspace # Gradle /build/ +/packages/react-native-codegen/android/build/ +/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build +/packages/rn-tester/android/app/.cxx/ /packages/rn-tester/android/app/build/ /packages/rn-tester/android/app/gradle/ /packages/rn-tester/android/app/gradlew @@ -97,10 +100,9 @@ package-lock.json !/packages/rn-tester/Pods/__offline_mirrors__ # react-native-codegen +/Libraries/FBReactNativeSpec/FBReactNativeSpec /packages/react-native-codegen/lib -/ReactCommon/fabric/components/rncore/ -/schema-native-modules.json -/schema-rncore.json +/ReactCommon/react/renderer/components/rncore/ # Visual studio .vscode diff --git a/.prettierrc b/.prettierrc index 20374fd919f060..bc951b8e09ab9e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,5 +3,6 @@ "singleQuote": true, "trailingComma": "all", "bracketSpacing": false, - "jsxBracketSameLine": true + "jsxBracketSameLine": true, + "arrowParens": "avoid" } diff --git a/ECOSYSTEM.md b/ECOSYSTEM.md index 75dc1ec14d3d25..657cfb43a11366 100644 --- a/ECOSYSTEM.md +++ b/ECOSYSTEM.md @@ -17,7 +17,7 @@ React Native's current set of partners include Callstack, Expo, Facebook, Infini * **[Callstack](https://callstack.com/):** Manages releases, maintains the [React Native CLI](https://github.com/react-native-community/react-native-cli) and organizes [React Native EU](https://react-native.eu/) * **[Expo](https://expo.io/):** Builds [expo](https://github.com/expo/expo) on top of React Native to simplify app development * **[Facebook](https://opensource.facebook.com):** Oversees the React Native product and maintains the [React Native core repo](https://reactnative.dev/) -* **[Infinite Red](https://infinite.red/):** Maintains the [ignite cli/boilerplate](https://github.com/infinitered/ignite), organizes [Chain React Conf](https://infinite.red/ChainReactConf) +* **[Infinite Red](https://infinite.red/):** Maintains the [ignite cli/boilerplate](https://github.com/infinitered/ignite), organizes [Chain React Conf](https://cr.infinite.red/) * **[Microsoft](http://aka.ms/reactnative):** Develops [React Native Windows](https://github.com/Microsoft/react-native-windows) and [React Native macOS](https://github.com/microsoft/react-native-macos) for building apps that target Windows and macOS * **[Software Mansion](https://swmansion.com/):** Maintain core infrastructure including JSC, Animated, and other popular third-party plugins. diff --git a/IntegrationTests/AsyncStorageTest.js b/IntegrationTests/AsyncStorageTest.js index 12d9f3d620f331..a6039d4b6d571d 100644 --- a/IntegrationTests/AsyncStorageTest.js +++ b/IntegrationTests/AsyncStorageTest.js @@ -16,6 +16,7 @@ const {AsyncStorage, Text, View, StyleSheet} = ReactNative; const {TestModule} = ReactNative.NativeModules; const deepDiffer = require('react-native/Libraries/Utilities/differ/deepDiffer'); +const nullthrows = require('nullthrows'); const DEBUG = false; @@ -43,15 +44,32 @@ function expectTrue(condition: boolean, message: string) { } } +// Type-safe wrapper around JSON.stringify +function stringify( + value: + | void + | null + | string + | number + | boolean + | {...} + | $ReadOnlyArray, +): string { + if (typeof value === 'undefined') { + return 'undefined'; + } + return JSON.stringify(value); +} + function expectEqual(lhs, rhs, testname: string) { expectTrue( !deepDiffer(lhs, rhs), 'Error in test ' + testname + ': expected\n' + - JSON.stringify(rhs) + + stringify(rhs) + '\ngot\n' + - JSON.stringify(lhs), + stringify(lhs), ); } @@ -61,7 +79,7 @@ function expectAsyncNoError(place, err) { } expectTrue( err === null, - 'Unexpected error in ' + place + ': ' + JSON.stringify(err), + 'Unexpected error in ' + place + ': ' + stringify(err), ); } @@ -71,7 +89,7 @@ function testSetAndGet() { AsyncStorage.getItem(KEY_1, (err2, result) => { expectAsyncNoError('testSetAndGet/getItem', err2); expectEqual(result, VAL_1, 'testSetAndGet setItem'); - updateMessage('get(key_1) correctly returned ' + result); + updateMessage('get(key_1) correctly returned ' + String(result)); runTestCase('should get null for missing key', testMissingGet); }); }); @@ -81,7 +99,7 @@ function testMissingGet() { AsyncStorage.getItem(KEY_2, (err, result) => { expectAsyncNoError('testMissingGet/setItem', err); expectEqual(result, null, 'testMissingGet'); - updateMessage('missing get(key_2) correctly returned ' + result); + updateMessage('missing get(key_2) correctly returned ' + String(result)); runTestCase('check set twice results in a single key', testSetTwice); }); } @@ -105,8 +123,9 @@ function testRemoveItem() { AsyncStorage.getAllKeys((err, result) => { expectAsyncNoError('testRemoveItem/getAllKeys', err); expectTrue( - result.indexOf(KEY_1) >= 0 && result.indexOf(KEY_2) >= 0, - 'Missing KEY_1 or KEY_2 in ' + '(' + result + ')', + nullthrows(result).indexOf(KEY_1) >= 0 && + nullthrows(result).indexOf(KEY_2) >= 0, + 'Missing KEY_1 or KEY_2 in ' + '(' + nullthrows(result).join() + ')', ); updateMessage('testRemoveItem - add two items'); AsyncStorage.removeItem(KEY_1, err2 => { @@ -123,8 +142,8 @@ function testRemoveItem() { AsyncStorage.getAllKeys((err4, result3) => { expectAsyncNoError('testRemoveItem/getAllKeys', err4); expectTrue( - result3.indexOf(KEY_1) === -1, - 'Unexpected: KEY_1 present in ' + result3, + nullthrows(result3).indexOf(KEY_1) === -1, + 'Unexpected: KEY_1 present in ' + nullthrows(result3).join(), ); updateMessage('proper length returned.'); runTestCase('should merge values', testMerge); @@ -137,13 +156,17 @@ function testRemoveItem() { } function testMerge() { - AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), err1 => { + AsyncStorage.setItem(KEY_MERGE, stringify(VAL_MERGE_1), err1 => { expectAsyncNoError('testMerge/setItem', err1); - AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), err2 => { + AsyncStorage.mergeItem(KEY_MERGE, stringify(VAL_MERGE_2), err2 => { expectAsyncNoError('testMerge/mergeItem', err2); AsyncStorage.getItem(KEY_MERGE, (err3, result) => { expectAsyncNoError('testMerge/setItem', err3); - expectEqual(JSON.parse(result), VAL_MERGE_EXPECT, 'testMerge'); + expectEqual( + JSON.parse(nullthrows(result)), + VAL_MERGE_EXPECT, + 'testMerge', + ); updateMessage('objects deeply merged\nDone!'); runTestCase('multi set and get', testOptimizedMultiGet); }); @@ -165,8 +188,7 @@ function testOptimizedMultiGet() { expectAsyncNoError(`${i} testOptimizedMultiGet/multiGet`, err2); expectEqual(result, batch, `${i} testOptimizedMultiGet multiGet`); updateMessage( - 'multiGet([key_1, key_2]) correctly returned ' + - JSON.stringify(result), + 'multiGet([key_1, key_2]) correctly returned ' + stringify(result), ); done(); }); diff --git a/IntegrationTests/GlobalEvalWithSourceUrlTest.js b/IntegrationTests/GlobalEvalWithSourceUrlTest.js index a30bfeec12df1a..fca7bfbc2170c7 100644 --- a/IntegrationTests/GlobalEvalWithSourceUrlTest.js +++ b/IntegrationTests/GlobalEvalWithSourceUrlTest.js @@ -10,6 +10,8 @@ 'use strict'; +import type {ExtendedError} from 'react-native/Libraries/Core/Devtools/parseErrorStack'; + const React = require('react'); const ReactNative = require('react-native'); const parseErrorStack = require('react-native/Libraries/Core/Devtools/parseErrorStack'); @@ -31,7 +33,7 @@ class GlobalEvalWithSourceUrlTest extends React.Component<{...}> { 'Expected globalEvalWithSourceUrl(expression) to return a value', ); } - let syntaxError; + let syntaxError: ?ExtendedError; try { global.globalEvalWithSourceUrl('{'); } catch (e) { @@ -42,7 +44,12 @@ class GlobalEvalWithSourceUrlTest extends React.Component<{...}> { 'Expected globalEvalWithSourceUrl to throw on a syntax error', ); } - if (!(syntaxError instanceof SyntaxError)) { + // Hermes throws an Error instead of a SyntaxError + // https://github.com/facebook/hermes/issues/400 + if ( + syntaxError.jsEngine !== 'hermes' && + !(syntaxError instanceof SyntaxError) + ) { throw new Error( 'Expected globalEvalWithSourceUrl to throw SyntaxError on a syntax error', ); diff --git a/IntegrationTests/LayoutEventsTest.js b/IntegrationTests/LayoutEventsTest.js index c86592a600b2f1..8c24abf36622ed 100644 --- a/IntegrationTests/LayoutEventsTest.js +++ b/IntegrationTests/LayoutEventsTest.js @@ -197,4 +197,5 @@ const styles = StyleSheet.create({ }, }); +LayoutEventsTest.displayName = 'LayoutEventsTest'; module.exports = LayoutEventsTest; diff --git a/IntegrationTests/TimersTest.js b/IntegrationTests/TimersTest.js index 8550c6f00eec6b..05569c8dbfcefd 100644 --- a/IntegrationTests/TimersTest.js +++ b/IntegrationTests/TimersTest.js @@ -267,4 +267,5 @@ const styles = StyleSheet.create({ }, }); +TimersTest.displayName = 'TimersTest'; module.exports = TimersTest; diff --git a/Libraries/ActionSheetIOS/ActionSheetIOS.js b/Libraries/ActionSheetIOS/ActionSheetIOS.js index 076ab004a56eb3..1fc86a0fd8872c 100644 --- a/Libraries/ActionSheetIOS/ActionSheetIOS.js +++ b/Libraries/ActionSheetIOS/ActionSheetIOS.js @@ -33,6 +33,7 @@ const ActionSheetIOS = { * - `destructiveButtonIndex` (int or array of ints) - index or indices of destructive buttons in `options` * - `title` (string) - a title to show above the action sheet * - `message` (string) - a message to show below the title + * - `disabledButtonIndices` (array of numbers) - a list of button indices which should be disabled * * The 'callback' function takes one parameter, the zero-based index * of the selected item. @@ -49,6 +50,7 @@ const ActionSheetIOS = { +anchor?: ?number, +tintColor?: ColorValue | ProcessedColorValue, +userInterfaceStyle?: string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) { @@ -57,7 +59,7 @@ const ActionSheetIOS = { 'Options must be a valid object', ); invariant(typeof callback === 'function', 'Must provide a valid callback'); - invariant(RCTActionSheetManager, "ActionSheetManager does't exist"); + invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist"); const {tintColor, destructiveButtonIndex, ...remainingOptions} = options; let destructiveButtonIndices = null; @@ -123,7 +125,7 @@ const ActionSheetIOS = { typeof successCallback === 'function', 'Must provide a valid successCallback', ); - invariant(RCTActionSheetManager, "ActionSheetManager does't exist"); + invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist"); RCTActionSheetManager.showShareActionSheetWithOptions( {...options, tintColor: processColor(options.tintColor)}, failureCallback, diff --git a/Libraries/ActionSheetIOS/NativeActionSheetManager.js b/Libraries/ActionSheetIOS/NativeActionSheetManager.js index 063d9147e1d69b..6d86200d9accd6 100644 --- a/Libraries/ActionSheetIOS/NativeActionSheetManager.js +++ b/Libraries/ActionSheetIOS/NativeActionSheetManager.js @@ -25,6 +25,7 @@ export interface Spec extends TurboModule { +anchor?: ?number, +tintColor?: ?number, +userInterfaceStyle?: ?string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) => void; diff --git a/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec b/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec index ef883132395026..7a318174f5d539 100644 --- a/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec +++ b/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec @@ -24,10 +24,10 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/actionsheetios" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "*.{m}" - s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" + s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" s.header_dir = "RCTActionSheet" s.dependency "React-Core/RCTActionSheetHeaders", version diff --git a/Libraries/Animated/AnimatedEvent.js b/Libraries/Animated/AnimatedEvent.js index 98ff42eb197071..87a434752be9e2 100644 --- a/Libraries/Animated/AnimatedEvent.js +++ b/Libraries/Animated/AnimatedEvent.js @@ -74,6 +74,7 @@ function attachNativeEvent( NativeAnimatedHelper.API.removeAnimatedEventFromView( viewTag, eventName, + // $FlowFixMe[incompatible-call] mapping.animatedValueTag, ); }); diff --git a/Libraries/Animated/NativeAnimatedHelper.js b/Libraries/Animated/NativeAnimatedHelper.js index 653301ef5d9314..af78a8d0987591 100644 --- a/Libraries/Animated/NativeAnimatedHelper.js +++ b/Libraries/Animated/NativeAnimatedHelper.js @@ -37,7 +37,6 @@ let nativeEventEmitter; let waitingForQueuedOperations = new Set(); let queueOperations = false; -let queueConnections = false; let queue: Array<() => void> = []; /** @@ -45,9 +44,6 @@ let queue: Array<() => void> = []; * the native module methods */ const API = { - enableQueue: function(): void { - queueConnections = true; - }, getValue: function( tag: number, saveValueCallback: (value: number) => void, @@ -57,12 +53,11 @@ const API = { NativeAnimatedModule.getValue(tag, saveValueCallback); } }, - setWaitingForIdentifier: function(id: number): void { + setWaitingForIdentifier: function(id: string): void { waitingForQueuedOperations.add(id); queueOperations = true; - queueConnections = true; }, - unsetWaitingForIdentifier: function(id: number): void { + unsetWaitingForIdentifier: function(id: string): void { waitingForQueuedOperations.delete(id); if (waitingForQueuedOperations.size === 0) { @@ -72,25 +67,16 @@ const API = { }, disableQueue: function(): void { invariant(NativeAnimatedModule, 'Native animated module is not available'); - queueConnections = false; - if (!queueOperations) { - if (Platform.OS === 'android') { - NativeAnimatedModule.startOperationBatch(); - } - for (let q = 0, l = queue.length; q < l; q++) { - queue[q](); - } - queue.length = 0; - if (Platform.OS === 'android') { - NativeAnimatedModule.finishOperationBatch(); - } + + if (Platform.OS === 'android') { + NativeAnimatedModule.startOperationBatch(); } - }, - queueConnection: (fn: () => void): void => { - if (queueConnections) { - queue.push(fn); - } else { - fn(); + for (let q = 0, l = queue.length; q < l; q++) { + queue[q](); + } + queue.length = 0; + if (Platform.OS === 'android') { + NativeAnimatedModule.finishOperationBatch(); } }, queueOperation: (fn: () => void): void => { @@ -120,7 +106,7 @@ const API = { }, connectAnimatedNodes: function(parentTag: number, childTag: number): void { invariant(NativeAnimatedModule, 'Native animated module is not available'); - API.queueConnection(() => + API.queueOperation(() => NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag), ); }, diff --git a/Libraries/Animated/NativeAnimatedModule.js b/Libraries/Animated/NativeAnimatedModule.js index a42e7ba5b12bed..be8ceb140fc31c 100644 --- a/Libraries/Animated/NativeAnimatedModule.js +++ b/Libraries/Animated/NativeAnimatedModule.js @@ -30,7 +30,6 @@ export type AnimatingNodeConfig = Object; export interface Spec extends TurboModule { +startOperationBatch: () => void; +finishOperationBatch: () => void; - +createAnimatedNode: (tag: number, config: AnimatedNodeConfig) => void; +getValue: (tag: number, saveValueCallback: SaveValueCallback) => void; +startListeningToAnimatedNodeValue: (tag: number) => void; diff --git a/Libraries/Animated/NativeAnimatedTurboModule.js b/Libraries/Animated/NativeAnimatedTurboModule.js index ac6c50b45069ac..b19fbde5f9b0f3 100644 --- a/Libraries/Animated/NativeAnimatedTurboModule.js +++ b/Libraries/Animated/NativeAnimatedTurboModule.js @@ -30,7 +30,6 @@ export type AnimatingNodeConfig = Object; export interface Spec extends TurboModule { +startOperationBatch: () => void; +finishOperationBatch: () => void; - +createAnimatedNode: (tag: number, config: AnimatedNodeConfig) => void; +getValue: (tag: number, saveValueCallback: SaveValueCallback) => void; +startListeningToAnimatedNodeValue: (tag: number) => void; diff --git a/Libraries/Animated/animations/Animation.js b/Libraries/Animated/animations/Animation.js index fd0c2218858452..53967d96f9e109 100644 --- a/Libraries/Animated/animations/Animation.js +++ b/Libraries/Animated/animations/Animation.js @@ -24,6 +24,8 @@ export type AnimationConfig = { iterations?: number, }; +let startNativeAnimationNextId = 1; + // Important note: start() and stop() will only be called at most once. // Once an animation has been stopped or finished its course, it will // not be reused. @@ -57,16 +59,27 @@ class Animation { onEnd && onEnd(result); } __startNativeAnimation(animatedValue: AnimatedValue): void { - NativeAnimatedHelper.API.enableQueue(); - animatedValue.__makeNative(); - NativeAnimatedHelper.API.disableQueue(); - this.__nativeId = NativeAnimatedHelper.generateNewAnimationId(); - NativeAnimatedHelper.API.startAnimatingNode( - this.__nativeId, - animatedValue.__getNativeTag(), - this.__getNativeAnimationConfig(), - this.__debouncedOnEnd.bind(this), + const startNativeAnimationWaitId = `${startNativeAnimationNextId}:startAnimation`; + startNativeAnimationNextId += 1; + NativeAnimatedHelper.API.setWaitingForIdentifier( + startNativeAnimationWaitId, ); + try { + animatedValue.__makeNative(); + this.__nativeId = NativeAnimatedHelper.generateNewAnimationId(); + NativeAnimatedHelper.API.startAnimatingNode( + this.__nativeId, + animatedValue.__getNativeTag(), + this.__getNativeAnimationConfig(), + this.__debouncedOnEnd.bind(this), + ); + } catch (e) { + throw e; + } finally { + NativeAnimatedHelper.API.unsetWaitingForIdentifier( + startNativeAnimationWaitId, + ); + } } } diff --git a/Libraries/Animated/components/AnimatedImage.js b/Libraries/Animated/components/AnimatedImage.js index 56cdb7d18f7908..5aae7d90056442 100644 --- a/Libraries/Animated/components/AnimatedImage.js +++ b/Libraries/Animated/components/AnimatedImage.js @@ -17,9 +17,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent( - (Image: $FlowFixMe), -): AnimatedComponentType< +module.exports = (createAnimatedComponent((Image: $FlowFixMe), { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedScrollView.js b/Libraries/Animated/components/AnimatedScrollView.js index 259cbb81b0ee2f..bfa75b7167b6d3 100644 --- a/Libraries/Animated/components/AnimatedScrollView.js +++ b/Libraries/Animated/components/AnimatedScrollView.js @@ -24,9 +24,9 @@ const ScrollViewWithEventThrottle = React.forwardRef((props, ref) => ( )); -module.exports = (createAnimatedComponent( - ScrollViewWithEventThrottle, -): AnimatedComponentType< +module.exports = (createAnimatedComponent(ScrollViewWithEventThrottle, { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedText.js b/Libraries/Animated/components/AnimatedText.js index 5a184e0626fe17..7a940093aadd08 100644 --- a/Libraries/Animated/components/AnimatedText.js +++ b/Libraries/Animated/components/AnimatedText.js @@ -17,9 +17,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent( - (Text: $FlowFixMe), -): AnimatedComponentType< +module.exports = (createAnimatedComponent((Text: $FlowFixMe), { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedView.js b/Libraries/Animated/components/AnimatedView.js index 0ce54601fe9990..d2a87807b02b7f 100644 --- a/Libraries/Animated/components/AnimatedView.js +++ b/Libraries/Animated/components/AnimatedView.js @@ -17,7 +17,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent(View): AnimatedComponentType< +module.exports = (createAnimatedComponent(View, { + collapsable: true, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/createAnimatedComponent.js b/Libraries/Animated/createAnimatedComponent.js index d5dc89b7f81f8d..8e8638edb63d58 100644 --- a/Libraries/Animated/createAnimatedComponent.js +++ b/Libraries/Animated/createAnimatedComponent.js @@ -11,7 +11,6 @@ 'use strict'; const View = require('../Components/View/View'); -const Platform = require('../Utilities/Platform'); const {AnimatedEvent} = require('./AnimatedEvent'); const AnimatedProps = require('./nodes/AnimatedProps'); const React = require('react'); @@ -38,8 +37,13 @@ export type AnimatedComponentType< Instance, >; +type AnimatedComponentOptions = { + collapsable?: boolean, +}; + function createAnimatedComponent( Component: React.AbstractComponent, + options?: AnimatedComponentOptions, ): AnimatedComponentType { invariant( typeof Component !== 'function' || @@ -56,7 +60,7 @@ function createAnimatedComponent( _eventDetachers: Array = []; // Only to be used in this file, and only in Fabric. - _animatedComponentId: number = -1; + _animatedComponentId: string = `${animatedComponentNextId++}:animatedComponent`; _attachNativeEvents() { // Make sure to get the scrollable node for components that implement @@ -80,6 +84,9 @@ function createAnimatedComponent( } _isFabric = (): boolean => { + // When called during the first render, `_component` is always null. + // Therefore, even if a component is rendered in Fabric, we can't detect + // that until ref is set, which happens sometime after the first render. if (this._component == null) { return false; } @@ -113,9 +120,6 @@ function createAnimatedComponent( _waitForUpdate = (): void => { if (this._isFabric()) { - if (this._animatedComponentId === -1) { - this._animatedComponentId = animatedComponentNextId++; - } NativeAnimatedHelper.API.setWaitingForIdentifier( this._animatedComponentId, ); @@ -217,22 +221,28 @@ function createAnimatedComponent( const {style: passthruStyle = {}, ...passthruProps} = this.props.passthroughAnimatedPropExplicitValues || {}; const mergedStyle = {...style, ...passthruStyle}; + const forceNativeId = + props.collapsable ?? + (this._propsAnimated.__isNative || + this._isFabric() || + options?.collapsable === false); + // The native driver updates views directly through the UI thread so we + // have to make sure the view doesn't get optimized away because it cannot + // go through the NativeViewHierarchyManager since it operates on the shadow + // thread. TODO: T68258846 + const collapsableProps = forceNativeId + ? { + nativeID: props.nativeID ?? 'animatedComponent', + collapsable: false, + } + : {}; return ( ); } diff --git a/Libraries/Animated/nodes/AnimatedDivision.js b/Libraries/Animated/nodes/AnimatedDivision.js index 437b013b525c8f..fad47ae87d1242 100644 --- a/Libraries/Animated/nodes/AnimatedDivision.js +++ b/Libraries/Animated/nodes/AnimatedDivision.js @@ -24,7 +24,7 @@ class AnimatedDivision extends AnimatedWithChildren { constructor(a: AnimatedNode | number, b: AnimatedNode | number) { super(); - if (b === 0) { + if (b === 0 || (b instanceof AnimatedNode && b.__getValue() === 0)) { console.error('Detected potential division by zero in AnimatedDivision'); } this._a = typeof a === 'number' ? new AnimatedValue(a) : a; diff --git a/Libraries/AppState/AppState.js b/Libraries/AppState/AppState.js index cc8a62a381ff8e..5e31fe2b954121 100644 --- a/Libraries/AppState/AppState.js +++ b/Libraries/AppState/AppState.js @@ -11,20 +11,48 @@ 'use strict'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; +import type EventSubscription from '../vendor/emitter/_EventSubscription'; +import type EmitterSubscription from '../vendor/emitter/_EmitterSubscription'; import logError from '../Utilities/logError'; import EventEmitter from '../vendor/emitter/EventEmitter'; import NativeAppState from './NativeAppState'; import invariant from 'invariant'; +export type AppStateValues = 'inactive' | 'background' | 'active'; + +type AppStateEventDefinitions = { + change: [AppStateValues], + memoryWarning: [], + blur: [], + focus: [], +}; + +type NativeAppStateEventDefinitions = { + appStateDidChange: [{app_state: AppStateValues}], + appStateFocusChange: [boolean], + memoryWarning: [], +}; + /** * `AppState` can tell you if the app is in the foreground or background, * and notify you when the state changes. * * See https://reactnative.dev/docs/appstate.html */ -class AppState extends NativeEventEmitter { - _eventHandlers: Object; - _supportedEvents = ['change', 'memoryWarning', 'blur', 'focus']; +class AppState extends NativeEventEmitter { + _eventHandlers: { + [key: $Keys]: Map< + /* Handler */ $FlowFixMe, + EventSubscription, + >, + ..., + }; + _supportedEvents: $ReadOnlyArray<$Keys> = [ + 'change', + 'memoryWarning', + 'blur', + 'focus', + ]; currentState: ?string; isAvailable: boolean; @@ -57,6 +85,7 @@ class AppState extends NativeEventEmitter { // It's possible that the state will have changed here & listeners need to be notified if (!eventUpdated && this.currentState !== appStateData.app_state) { this.currentState = appStateData.app_state; + // $FlowExpectedError[incompatible-call] this.emit('appStateDidChange', appStateData); } }, logError); @@ -73,7 +102,10 @@ class AppState extends NativeEventEmitter { * * See https://reactnative.dev/docs/appstate.html#addeventlistener */ - addEventListener(type: string, handler: Function) { + addEventListener>( + type: K, + handler: (...$ElementType) => void, + ): void { invariant( this._supportedEvents.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', @@ -82,32 +114,38 @@ class AppState extends NativeEventEmitter { switch (type) { case 'change': { + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const changeHandler: AppStateValues => void = handler; this._eventHandlers[type].set( handler, this.addListener('appStateDidChange', appStateData => { - handler(appStateData.app_state); + changeHandler(appStateData.app_state); }), ); break; } case 'memoryWarning': { + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const memoryWarningHandler: () => void = handler; this._eventHandlers[type].set( handler, - this.addListener('memoryWarning', handler), + this.addListener('memoryWarning', memoryWarningHandler), ); break; } case 'blur': case 'focus': { + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const focusOrBlurHandler: () => void = handler; this._eventHandlers[type].set( handler, this.addListener('appStateFocusChange', hasFocus => { if (type === 'blur' && !hasFocus) { - handler(); + focusOrBlurHandler(); } if (type === 'focus' && hasFocus) { - handler(); + focusOrBlurHandler(); } }), ); @@ -120,52 +158,72 @@ class AppState extends NativeEventEmitter { * * See https://reactnative.dev/docs/appstate.html#removeeventlistener */ - removeEventListener(type: string, handler: Function) { + removeEventListener>( + type: K, + handler: (...$ElementType) => void, + ) { invariant( this._supportedEvents.indexOf(type) !== -1, 'Trying to remove listener for unknown event: "%s"', type, ); - if (!this._eventHandlers[type].has(handler)) { + const subscription = this._eventHandlers[type].get(handler); + if (!subscription) { return; } - this._eventHandlers[type].get(handler).remove(); + subscription.remove(); this._eventHandlers[type].delete(handler); } } -function throwMissingNativeModule() { - invariant( - false, - 'Cannot use AppState module when native RCTAppState is not included in the build.\n' + - 'Either include it, or check AppState.isAvailable before calling any methods.', - ); +class MissingNativeModuleError extends Error { + constructor() { + super( + 'Cannot use AppState module when native RCTAppState is not included in the build.\n' + + 'Either include it, or check AppState.isAvailable before calling any methods.', + ); + } } -class MissingNativeAppStateShim extends EventEmitter { +class MissingNativeAppStateShim extends EventEmitter { // AppState isAvailable: boolean = false; currentState: ?string = null; - addEventListener(type: string, handler: Function) { - throwMissingNativeModule(); + addEventListener>( + type: K, + handler: (...$ElementType) => mixed, + ): void { + throw new MissingNativeModuleError(); } - removeEventListener(type: string, handler: Function) { - throwMissingNativeModule(); + removeEventListener>( + type: K, + handler: (...$ElementType) => mixed, + ) { + throw new MissingNativeModuleError(); } - // EventEmitter - addListener() { - throwMissingNativeModule(); + // $FlowIssue[invalid-tuple-arity] + addListener>( + eventType: K, + // $FlowIssue[incompatible-extend] + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription { + throw new MissingNativeModuleError(); } - removeAllListeners() { - throwMissingNativeModule(); + removeAllListeners>( + eventType: ?K, + ): void { + throw new MissingNativeModuleError(); } - removeSubscription() { - throwMissingNativeModule(); + removeSubscription>( + subscription: EmitterSubscription, + ): void { + throw new MissingNativeModuleError(); } } diff --git a/Libraries/BUCK b/Libraries/BUCK new file mode 100644 index 00000000000000..586510279a0321 --- /dev/null +++ b/Libraries/BUCK @@ -0,0 +1,56 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load( + "//tools/build_defs/oss:rn_codegen_defs.bzl", + "rn_codegen_components", + "rn_codegen_modules", +) +load( + "//tools/build_defs/oss:rn_defs.bzl", + "react_native_root_target", +) + +fb_native.genrule( + # The schema name must have the following format: "{name}-codegen-modules-schema" + # Why: Internally, we have build scripts that find all NativeModule schemas in the + # dependencies of an app, and build TurboModuleManager delegates. Those scripts assume + # that all schema targets have the aforementioned naming scheme. + name = "FBReactNativeSpec-codegen-modules-schema", + srcs = glob( + [ + "**/*.js", + ], + exclude = [ + "**/__tests__/**/*", + ], + ), + cmd = "$(exe {}) $OUT $SRCS".format(react_native_root_target("packages/react-native-codegen:write_to_json")), + out = "schema.json", + labels = [ + "codegen_rule", + "react_native_schema_target", + ], +) + +rn_codegen_modules( + name = "FBReactNativeSpec", + android_package_name = "com.facebook.fbreact.specs", + library_labels = ["supermodule:xplat/default/public.react_native.infra"], + schema_target = ":FBReactNativeSpec-codegen-modules-schema", +) + +rn_codegen_components( + name = "FBReactNativeComponentSpec", + library_labels = ["supermodule:xplat/default/public.react_native.infra"], + # Why does FBReactNativeComponentSpec depend on -codegen-modules-schema? + # The module codegen schema also contains components. We cannot change the name + # of the schema target, because internally, we have infra that depends on how + # it's named. + # + # TODO(T83341482): Clean up how OSS NativeModule codegen is declared + schema_target = ":FBReactNativeSpec-codegen-modules-schema", +) diff --git a/Libraries/Blob/RCTBlobManager.mm b/Libraries/Blob/RCTBlobManager.mm index a75844ed6ae1ed..551c910584fad4 100755 --- a/Libraries/Blob/RCTBlobManager.mm +++ b/Libraries/Blob/RCTBlobManager.mm @@ -37,8 +37,8 @@ @implementation RCTBlobManager RCT_EXPORT_MODULE(BlobModule) @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; @synthesize methodQueue = _methodQueue; -@synthesize turboModuleRegistry = _turboModuleRegistry; - (void)setBridge:(RCTBridge *)bridge { @@ -140,9 +140,9 @@ - (void)remove:(NSString *)blobId RCT_EXPORT_METHOD(addNetworkingHandler) { - RCTNetworking *const networking = _bridge ? _bridge.networking : [_turboModuleRegistry moduleForName:"RCTNetworking"]; + RCTNetworking *const networking = [_moduleRegistry moduleForName:"Networking"]; - // TODO(T63516227): Why can methodQueue be nil here? + // TODO(T63516227): Why can methodQueue be nil here? // We don't want to do anything when methodQueue is nil. if (!networking.methodQueue) { return; @@ -156,23 +156,23 @@ - (void)remove:(NSString *)blobId RCT_EXPORT_METHOD(addWebSocketHandler:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule setContentHandler:self forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] setContentHandler:self forSocketID:[NSNumber numberWithDouble:socketID]]; }); } RCT_EXPORT_METHOD(removeWebSocketHandler:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule setContentHandler:nil forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] setContentHandler:nil forSocketID:[NSNumber numberWithDouble:socketID]]; }); } // @lint-ignore FBOBJCUNTYPEDCOLLECTION1 RCT_EXPORT_METHOD(sendOverSocket:(NSDictionary *)blob socketID:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule sendData:[self resolve:blob] forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] sendData:[self resolve:blob] forSocketID:[NSNumber numberWithDouble:socketID]]; }); } diff --git a/Libraries/Blob/RCTFileReaderModule.mm b/Libraries/Blob/RCTFileReaderModule.mm index 315605acc1174d..2525de0c201b2b 100644 --- a/Libraries/Blob/RCTFileReaderModule.mm +++ b/Libraries/Blob/RCTFileReaderModule.mm @@ -23,15 +23,14 @@ @implementation RCTFileReaderModule RCT_EXPORT_MODULE(FileReaderModule) -@synthesize bridge = _bridge; -@synthesize turboModuleRegistry = _turboModuleRegistry; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_METHOD(readAsText:(NSDictionary *)blob encoding:(NSString *)encoding resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - RCTBlobManager *blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]]; + RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"]; NSData *data = [blobManager resolve:blob]; if (data == nil) { @@ -56,12 +55,7 @@ @implementation RCTFileReaderModule resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - RCTBlobManager *blobManager = nil; - if ([self bridge]) { - blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]]; - } else { - blobManager = [[self turboModuleRegistry] moduleForName:[NSStringFromClass([RCTBlobManager class]) UTF8String]]; - } + RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"]; NSData *data = [blobManager resolve:blob]; if (data == nil) { diff --git a/Libraries/Blob/React-RCTBlob.podspec b/Libraries/Blob/React-RCTBlob.podspec index 045cf27ab9d0f8..9d691b100ab9fa 100644 --- a/Libraries/Blob/React-RCTBlob.podspec +++ b/Libraries/Blob/React-RCTBlob.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{h,m,mm}" diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js index b0909d2b072753..cfceeaaa7c719f 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js @@ -11,18 +11,24 @@ 'use strict'; import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; -import UIManager from '../../ReactNative/UIManager'; import NativeAccessibilityInfo from './NativeAccessibilityInfo'; +import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import {sendAccessibilityEvent} from '../../Renderer/shims/ReactNative'; +import legacySendAccessibilityEvent from './legacySendAccessibilityEvent'; +import {type ElementRef} from 'react'; const REDUCE_MOTION_EVENT = 'reduceMotionDidChange'; const TOUCH_EXPLORATION_EVENT = 'touchExplorationDidChange'; -type ChangeEventName = $Keys<{ - change: string, - reduceMotionChanged: string, - screenReaderChanged: string, - ... -}>; +type AccessibilityEventDefinitions = { + reduceMotionChanged: [boolean], + screenReaderChanged: [boolean], + // alias for screenReaderChanged + change: [boolean], +}; + +type AccessibilityEventTypes = 'focus'; const _subscriptions = new Map(); @@ -98,7 +104,10 @@ const AccessibilityInfo = { return this.isScreenReaderEnabled; }, - addEventListener: function(eventName: ChangeEventName, handler: T): void { + addEventListener: function>( + eventName: K, + handler: (...$ElementType) => void, + ): EventSubscription { let listener; if (eventName === 'change' || eventName === 'screenReaderChanged') { @@ -113,18 +122,28 @@ const AccessibilityInfo = { ); } + // $FlowFixMe[escaped-generic] _subscriptions.set(handler, listener); + + return { + remove: () => { + // $FlowIssue flow does not recognize handler properly + AccessibilityInfo.removeEventListener(eventName, handler); + }, + }; }, - removeEventListener: function( - eventName: ChangeEventName, - handler: T, + removeEventListener: function>( + eventName: K, + handler: (...$ElementType) => void, ): void { + // $FlowFixMe[escaped-generic] const listener = _subscriptions.get(handler); if (!listener) { return; } listener.remove(); + // $FlowFixMe[escaped-generic] _subscriptions.delete(handler); }, @@ -134,10 +153,18 @@ const AccessibilityInfo = { * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus */ setAccessibilityFocus: function(reactTag: number): void { - UIManager.sendAccessibilityEvent( - reactTag, - UIManager.getConstants().AccessibilityEventTypes.typeViewFocused, - ); + legacySendAccessibilityEvent(reactTag, 'focus'); + }, + + /** + * Send a named accessibility event to a HostComponent. + */ + sendAccessibilityEvent_unstable: function( + handle: ElementRef>, + eventType: AccessibilityEventTypes, + ) { + // route through React renderer to distinguish between Fabric and non-Fabric handles + sendAccessibilityEvent(handle, eventType); }, /** diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js index fb73ab2ee249c7..cd55ed59c0383d 100644 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js @@ -12,6 +12,11 @@ import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; import NativeAccessibilityManager from './NativeAccessibilityManager'; +import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import {sendAccessibilityEvent} from '../../Renderer/shims/ReactNative'; +import legacySendAccessibilityEvent from './legacySendAccessibilityEvent'; +import {type ElementRef} from 'react'; const CHANGE_EVENT_NAME = { announcementFinished: 'announcementFinished', @@ -23,17 +28,24 @@ const CHANGE_EVENT_NAME = { screenReaderChanged: 'screenReaderChanged', }; -type ChangeEventName = $Keys<{ - announcementFinished: string, - boldTextChanged: string, - change: string, - grayscaleChanged: string, - invertColorsChanged: string, - reduceMotionChanged: string, - reduceTransparencyChanged: string, - screenReaderChanged: string, - ... -}>; +type AccessibilityEventDefinitions = { + boldTextChanged: [boolean], + grayscaleChanged: [boolean], + invertColorsChanged: [boolean], + reduceMotionChanged: [boolean], + reduceTransparencyChanged: [boolean], + screenReaderChanged: [boolean], + // alias for screenReaderChanged + change: [boolean], + announcementFinished: [ + { + announcement: string, + success: boolean, + }, + ], +}; + +type AccessibilityEventTypes = 'focus'; const _subscriptions = new Map(); @@ -202,28 +214,30 @@ const AccessibilityInfo = { * * See https://reactnative.dev/docs/accessibilityinfo.html#addeventlistener */ - addEventListener: function( - eventName: ChangeEventName, - handler: T, - ): {remove: () => void} { - let listener; + addEventListener: function>( + eventName: K, + handler: (...$ElementType) => void, + ): EventSubscription { + let subscription: EventSubscription; if (eventName === 'change') { - listener = RCTDeviceEventEmitter.addListener( + subscription = RCTDeviceEventEmitter.addListener( CHANGE_EVENT_NAME.screenReaderChanged, + // $FlowFixMe[incompatible-call] handler, ); } else if (CHANGE_EVENT_NAME[eventName]) { - listener = RCTDeviceEventEmitter.addListener(eventName, handler); + subscription = RCTDeviceEventEmitter.addListener(eventName, handler); } - _subscriptions.set(handler, listener); + // $FlowFixMe[escaped-generic] + _subscriptions.set(handler, subscription); + return { - remove: AccessibilityInfo.removeEventListener.bind( - null, - eventName, - handler, - ), + remove: () => { + // $FlowIssue flow does not recognize handler properly + AccessibilityInfo.removeEventListener(eventName, handler); + }, }; }, @@ -233,9 +247,18 @@ const AccessibilityInfo = { * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus */ setAccessibilityFocus: function(reactTag: number): void { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.setAccessibilityFocus(reactTag); - } + legacySendAccessibilityEvent(reactTag, 'focus'); + }, + + /** + * Send a named accessibility event to a HostComponent. + */ + sendAccessibilityEvent_unstable: function( + handle: ElementRef>, + eventType: AccessibilityEventTypes, + ) { + // route through React renderer to distinguish between Fabric and non-Fabric handles + sendAccessibilityEvent(handle, eventType); }, /** @@ -254,15 +277,17 @@ const AccessibilityInfo = { * * See https://reactnative.dev/docs/accessibilityinfo.html#removeeventlistener */ - removeEventListener: function( - eventName: ChangeEventName, - handler: T, + removeEventListener: function>( + eventName: K, + handler: (...$ElementType) => void, ): void { + // $FlowFixMe[escaped-generic] const listener = _subscriptions.get(handler); if (!listener) { return; } listener.remove(); + // $FlowFixMe[escaped-generic] _subscriptions.delete(handler); }, }; diff --git a/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js new file mode 100644 index 00000000000000..a5c75a92befd7b --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js @@ -0,0 +1,31 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +'use strict'; + +import UIManager from '../../ReactNative/UIManager'; + +/** + * This is a function exposed to the React Renderer that can be used by the + * pre-Fabric renderer to emit accessibility events to pre-Fabric nodes. + */ +function legacySendAccessibilityEvent( + reactTag: number, + eventType: string, +): void { + if (eventType === 'focus') { + UIManager.sendAccessibilityEvent( + reactTag, + UIManager.getConstants().AccessibilityEventTypes.typeViewFocused, + ); + } +} + +module.exports = legacySendAccessibilityEvent; diff --git a/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js new file mode 100644 index 00000000000000..cbc1785610a2f0 --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +'use strict'; + +import NativeAccessibilityManager from './NativeAccessibilityManager'; + +/** + * This is a function exposed to the React Renderer that can be used by the + * pre-Fabric renderer to emit accessibility events to pre-Fabric nodes. + */ +function legacySendAccessibilityEvent( + reactTag: number, + eventType: string, +): void { + if (eventType === 'focus' && NativeAccessibilityManager) { + NativeAccessibilityManager.setAccessibilityFocus(reactTag); + } +} + +module.exports = legacySendAccessibilityEvent; diff --git a/Libraries/Components/ActivityIndicator/ActivityIndicator.js b/Libraries/Components/ActivityIndicator/ActivityIndicator.js index 52cbda4a7312e2..05f125d86698bf 100644 --- a/Libraries/Components/ActivityIndicator/ActivityIndicator.js +++ b/Libraries/Components/ActivityIndicator/ActivityIndicator.js @@ -62,8 +62,18 @@ type Props = $ReadOnly<{| size?: ?IndicatorSize, |}>; -const ActivityIndicator = (props: Props, forwardedRef?: any) => { - const {onLayout, style, size, ...restProps} = props; +const ActivityIndicator = ( + { + animating = true, + color = Platform.OS === 'ios' ? GRAY : null, + hidesWhenStopped = true, + onLayout, + size = 'small', + style, + ...restProps + }: Props, + forwardedRef?: any, +) => { let sizeStyle; let sizeProp; @@ -77,11 +87,14 @@ const ActivityIndicator = (props: Props, forwardedRef?: any) => { sizeProp = 'large'; break; default: - sizeStyle = {height: props.size, width: props.size}; + sizeStyle = {height: size, width: size}; break; } const nativeProps = { + animating, + color, + hidesWhenStopped, ...restProps, ref: forwardedRef, style: sizeStyle, @@ -178,16 +191,6 @@ const ActivityIndicatorWithRef: React.AbstractComponent< > = React.forwardRef(ActivityIndicator); ActivityIndicatorWithRef.displayName = 'ActivityIndicator'; -/* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.89 was deployed. To see the error, delete this comment - * and run Flow. */ -ActivityIndicatorWithRef.defaultProps = { - animating: true, - color: Platform.OS === 'ios' ? GRAY : null, - hidesWhenStopped: true, - size: 'small', -}; - const styles = StyleSheet.create({ container: { alignItems: 'center', diff --git a/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap b/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap index d8316e939d13d1..4326d7f8ae20f3 100644 --- a/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap +++ b/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap @@ -2,9 +2,7 @@ exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` `; @@ -35,18 +33,14 @@ exports[` should render as expected: should deep render whe exports[` should render as expected: should shallow render as when mocked 1`] = ` `; exports[` should render as expected: should shallow render as when not mocked 1`] = ` `; diff --git a/Libraries/Components/AppleTV/NativeTVNavigationEventEmitter.js b/Libraries/Components/AppleTV/NativeTVNavigationEventEmitter.js deleted file mode 100644 index e4e4e47d553469..00000000000000 --- a/Libraries/Components/AppleTV/NativeTVNavigationEventEmitter.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type {TurboModule} from '../../TurboModule/RCTExport'; -import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry'; - -export interface Spec extends TurboModule { - +addListener: (eventName: string) => void; - +removeListeners: (count: number) => void; -} - -let NativeModule: ?Spec = null; - -const wrapperModule = { - addListener(eventName: string) { - if (NativeModule == null) { - NativeModule = TurboModuleRegistry.get('TVNavigationEventEmitter'); - } - NativeModule && NativeModule.addListener(eventName); - }, - - removeListeners(count: number) { - if (NativeModule == null) { - NativeModule = TurboModuleRegistry.get('TVNavigationEventEmitter'); - } - NativeModule && NativeModule.removeListeners(count); - }, -}; - -export default wrapperModule; diff --git a/Libraries/Components/AppleTV/TVEventHandler.js b/Libraries/Components/AppleTV/TVEventHandler.js deleted file mode 100644 index d3f475a1fdb777..00000000000000 --- a/Libraries/Components/AppleTV/TVEventHandler.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -'use strict'; - -import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter'; -import Platform from '../../Utilities/Platform'; -import {type EventSubscription} from '../../vendor/emitter/EventEmitter'; -import NativeTVNavigationEventEmitter from './NativeTVNavigationEventEmitter'; - -class TVEventHandler { - __nativeTVNavigationEventListener: ?EventSubscription = null; - __nativeTVNavigationEventEmitter: ?NativeEventEmitter = null; - - enable(component: ?any, callback: Function): void { - if (Platform.OS === 'ios' && !NativeTVNavigationEventEmitter) { - return; - } - - this.__nativeTVNavigationEventEmitter = new NativeEventEmitter( - NativeTVNavigationEventEmitter, - ); - this.__nativeTVNavigationEventListener = this.__nativeTVNavigationEventEmitter.addListener( - 'onHWKeyEvent', - data => { - if (callback) { - callback(component, data); - } - }, - ); - } - - disable(): void { - if (this.__nativeTVNavigationEventListener) { - this.__nativeTVNavigationEventListener.remove(); - delete this.__nativeTVNavigationEventListener; - } - if (this.__nativeTVNavigationEventEmitter) { - delete this.__nativeTVNavigationEventEmitter; - } - } -} - -module.exports = TVEventHandler; diff --git a/Libraries/Components/Keyboard/Keyboard.js b/Libraries/Components/Keyboard/Keyboard.js index a9e0a29771ddfd..5b56ad03a42271 100644 --- a/Libraries/Components/Keyboard/Keyboard.js +++ b/Libraries/Components/Keyboard/Keyboard.js @@ -14,18 +14,9 @@ import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter'; import LayoutAnimation from '../../LayoutAnimation/LayoutAnimation'; import dismissKeyboard from '../../Utilities/dismissKeyboard'; import NativeKeyboardObserver from './NativeKeyboardObserver'; -import invariant from 'invariant'; -const KeyboardEventEmitter: NativeEventEmitter = new NativeEventEmitter( - NativeKeyboardObserver, -); - -export type KeyboardEventName = - | 'keyboardWillShow' - | 'keyboardDidShow' - | 'keyboardWillHide' - | 'keyboardDidHide' - | 'keyboardWillChangeFrame' - | 'keyboardDidChangeFrame'; +import type EmitterSubscription from '../../vendor/emitter/_EmitterSubscription'; + +export type KeyboardEventName = $Keys; export type KeyboardEventEasing = | 'easeIn' @@ -61,11 +52,14 @@ export type IOSKeyboardEvent = $ReadOnly<{| isEventFromThisApp: boolean, |}>; -type KeyboardEventListener = (e: KeyboardEvent) => void; - -// The following object exists for documentation purposes -// Actual work happens in -// https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/NativeEventEmitter.js +type KeyboardEventDefinitions = { + keyboardWillShow: [KeyboardEvent], + keyboardDidShow: [KeyboardEvent], + keyboardWillHide: [KeyboardEvent], + keyboardDidHide: [KeyboardEvent], + keyboardWillChangeFrame: [KeyboardEvent], + keyboardDidChangeFrame: [KeyboardEvent], +}; /** * `Keyboard` module to control keyboard events. @@ -109,7 +103,11 @@ type KeyboardEventListener = (e: KeyboardEvent) => void; *``` */ -const Keyboard = { +class Keyboard extends NativeEventEmitter { + constructor() { + super(NativeKeyboardObserver); + } + /** * The `addListener` function connects a JavaScript function to an identified native * keyboard notification event. @@ -133,9 +131,13 @@ const Keyboard = { * * @param {function} callback function to be called when the event fires. */ - addListener(eventName: KeyboardEventName, callback: KeyboardEventListener) { - invariant(false, 'Dummy method used for documentation'); - }, + addListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription { + return super.addListener(eventType, listener); + } /** * Removes a specific listener. @@ -143,51 +145,45 @@ const Keyboard = { * @param {string} eventName The `nativeEvent` is the string that identifies the event you're listening for. * @param {function} callback function to be called when the event fires. */ - removeListener( - eventName: KeyboardEventName, - callback: KeyboardEventListener, - ) { - invariant(false, 'Dummy method used for documentation'); - }, + removeListener>( + eventType: K, + listener: (...$ElementType) => mixed, + ): void { + super.removeListener(eventType, listener); + } /** * Removes all listeners for a specific event type. * * @param {string} eventType The native event string listeners are watching which will be removed. */ - removeAllListeners(eventName: KeyboardEventName) { - invariant(false, 'Dummy method used for documentation'); - }, + removeAllListeners>(eventType: ?K): void { + super.removeAllListeners(eventType); + } /** * Dismisses the active keyboard and removes focus. */ - dismiss() { - invariant(false, 'Dummy method used for documentation'); - }, + dismiss(): void { + dismissKeyboard(); + } /** * Useful for syncing TextInput (or other keyboard accessory view) size of * position changes with keyboard movements. */ - scheduleLayoutAnimation(event: KeyboardEvent) { - invariant(false, 'Dummy method used for documentation'); - }, -}; - -// Throw away the dummy object and reassign it to original module -KeyboardEventEmitter.dismiss = dismissKeyboard; -KeyboardEventEmitter.scheduleLayoutAnimation = function(event: KeyboardEvent) { - const {duration, easing} = event; - if (duration != null && duration !== 0) { - LayoutAnimation.configureNext({ - duration: duration, - update: { + scheduleLayoutAnimation(event: KeyboardEvent): void { + const {duration, easing} = event; + if (duration != null && duration !== 0) { + LayoutAnimation.configureNext({ duration: duration, - type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard', - }, - }); + update: { + duration: duration, + type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard', + }, + }); + } } -}; +} -module.exports = KeyboardEventEmitter; +module.exports = (new Keyboard(): Keyboard); diff --git a/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/Libraries/Components/Keyboard/KeyboardAvoidingView.js index 4e87a3f16c8d76..b3b33f838bec24 100644 --- a/Libraries/Components/Keyboard/KeyboardAvoidingView.js +++ b/Libraries/Components/Keyboard/KeyboardAvoidingView.js @@ -97,13 +97,16 @@ class KeyboardAvoidingView extends React.Component { }; _onLayout = (event: ViewLayoutEvent) => { + const wasFrameNull = this._frame == null; this._frame = event.nativeEvent.layout; if (!this._initialFrameHeight) { // save the initial frame height, before the keyboard is visible this._initialFrameHeight = this._frame.height; } - this._updateBottomIfNecesarry(); + if (wasFrameNull) { + this._updateBottomIfNecesarry(); + } }; _updateBottomIfNecesarry = () => { diff --git a/Libraries/Components/Keyboard/__tests__/Keyboard-test.js b/Libraries/Components/Keyboard/__tests__/Keyboard-test.js index 639cdd0db5f4f0..ab38d1ccb8b3ab 100644 --- a/Libraries/Components/Keyboard/__tests__/Keyboard-test.js +++ b/Libraries/Components/Keyboard/__tests__/Keyboard-test.js @@ -19,6 +19,7 @@ const Keyboard = require('../Keyboard'); import NativeEventEmitter from '../../../EventEmitter/NativeEventEmitter'; jest.mock('../../../LayoutAnimation/LayoutAnimation'); +jest.mock('../../../Utilities/dismissKeyboard'); describe('Keyboard', () => { beforeEach(() => { @@ -36,14 +37,14 @@ describe('Keyboard', () => { }); it('uses dismissKeyboard utility', () => { - expect(Keyboard.dismiss).toBe(dismissKeyboard); + Keyboard.dismiss(); + expect(dismissKeyboard).toHaveBeenCalled(); }); describe('scheduling layout animation', () => { - const scheduleLayoutAnimation = ( - duration: number | null, - easing: string | null, - ): void => Keyboard.scheduleLayoutAnimation({duration, easing}); + const scheduleLayoutAnimation = (duration, easing): void => + // $FlowFixMe[incompatible-call] + Keyboard.scheduleLayoutAnimation({duration, easing}); it('triggers layout animation', () => { scheduleLayoutAnimation(12, 'spring'); diff --git a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js b/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js index bac74826a1fb11..d01757865909fc 100644 --- a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js +++ b/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow */ 'use strict'; @@ -14,6 +14,8 @@ import * as React from 'react'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; import requireNativeComponent from '../../ReactNative/requireNativeComponent'; +import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; +import AndroidDialogPickerViewConfig from './AndroidDialogPickerViewConfig'; import type { DirectEventHandler, @@ -64,6 +66,17 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['setNativeSelectedPosition'], }); -export default (requireNativeComponent( - 'AndroidDialogPicker', -): NativeType); +let AndroidDialogPickerNativeComponent; +if (global.RN$Bridgeless) { + registerGeneratedViewConfig( + 'AndroidDialogPicker', + AndroidDialogPickerViewConfig, + ); + AndroidDialogPickerNativeComponent = 'AndroidDialogPicker'; +} else { + AndroidDialogPickerNativeComponent = requireNativeComponent( + 'AndroidDialogPicker', + ); +} + +export default ((AndroidDialogPickerNativeComponent: any): NativeType); diff --git a/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js b/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js new file mode 100644 index 00000000000000..440006163698c2 --- /dev/null +++ b/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {PartialViewConfig} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; + +const AndroidDialogPickerViewConfig = { + uiViewClassName: 'AndroidDialogPicker', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: { + color: {process: require('../../StyleSheet/processColor')}, + backgroundColor: {process: require('../../StyleSheet/processColor')}, + enabled: true, + items: true, + prompt: true, + selected: true, + onSelect: true, + }, +}; + +module.exports = (AndroidDialogPickerViewConfig: PartialViewConfig); diff --git a/Libraries/Components/Picker/Picker.js b/Libraries/Components/Picker/Picker.js index 76fa6d36f1b257..87c1f8133e4a5d 100644 --- a/Libraries/Components/Picker/Picker.js +++ b/Libraries/Components/Picker/Picker.js @@ -30,9 +30,9 @@ type PickerItemProps = $ReadOnly<{| /** * The value to be passed to picker's `onValueChange` callback when - * this item is selected. Can be a string or an integer. + * this item is selected. */ - value?: ?(number | string), + value?: ?string, /** * Color of this item's text. @@ -62,9 +62,9 @@ type PickerProps = $ReadOnly<{| style?: ?TextStyleProp, /** - * Value matching value of one of the items. Can be a string or an integer. + * Value matching value of one of the items. */ - selectedValue?: ?(number | string), + selectedValue?: ?string, /** * Callback for when an item is selected. This is called with the following parameters: diff --git a/Libraries/Components/Picker/PickerIOS.ios.js b/Libraries/Components/Picker/PickerIOS.ios.js index 39417c3c23b4d2..7f294019261a85 100644 --- a/Libraries/Components/Picker/PickerIOS.ios.js +++ b/Libraries/Components/Picker/PickerIOS.ios.js @@ -37,7 +37,7 @@ type PickerIOSChangeEvent = SyntheticEvent< type RCTPickerIOSItemType = $ReadOnly<{| label: ?Label, - value: ?(number | string), + value: ?string, textColor: ?ProcessedColorValue, |}>; @@ -49,7 +49,7 @@ type Props = $ReadOnly<{| itemStyle?: ?TextStyleProp, onChange?: ?(event: PickerIOSChangeEvent) => mixed, onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed, - selectedValue: ?(number | string), + selectedValue: ?string, accessibilityLabel?: ?string, |}>; @@ -60,7 +60,7 @@ type State = {| type ItemProps = $ReadOnly<{| label: ?Label, - value?: ?(number | string), + value?: ?string, color?: ?ColorValue, |}>; diff --git a/Libraries/Components/Picker/RCTPickerNativeComponent.js b/Libraries/Components/Picker/RCTPickerNativeComponent.js index ca42471b6025ce..7fdbe9c76c80fd 100644 --- a/Libraries/Components/Picker/RCTPickerNativeComponent.js +++ b/Libraries/Components/Picker/RCTPickerNativeComponent.js @@ -11,12 +11,14 @@ 'use strict'; const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); +const ReactNativeViewConfigRegistry = require('../../Renderer/shims/ReactNativeViewConfigRegistry'); import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {SyntheticEvent} from '../../Types/CoreEventTypes'; import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; import type {ProcessedColorValue} from '../../StyleSheet/processColor'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; +import RCTPickerViewConfig from './RCTPickerViewConfig'; import * as React from 'react'; type PickerIOSChangeEvent = SyntheticEvent< @@ -28,7 +30,7 @@ type PickerIOSChangeEvent = SyntheticEvent< type RCTPickerIOSItemType = $ReadOnly<{| label: ?Label, - value: ?(number | string), + value: ?string, textColor: ?ProcessedColorValue, |}>; @@ -56,8 +58,15 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['setNativeSelectedIndex'], }); -const RCTPickerNativeComponent: ComponentType = requireNativeComponent( - 'RCTPicker', -); +let RCTPickerNativeComponent; +if (global.RN$Bridgeless) { + ReactNativeViewConfigRegistry.register('RCTPicker', () => { + return RCTPickerViewConfig; + }); + RCTPickerNativeComponent = 'RCTPicker'; +} else { + RCTPickerNativeComponent = requireNativeComponent('RCTPicker'); +} -export default RCTPickerNativeComponent; +// flowlint-next-line unclear-type:off +export default ((RCTPickerNativeComponent: any): HostComponent); diff --git a/Libraries/Components/Picker/RCTPickerViewConfig.js b/Libraries/Components/Picker/RCTPickerViewConfig.js new file mode 100644 index 00000000000000..9a5ec9d612dd1b --- /dev/null +++ b/Libraries/Components/Picker/RCTPickerViewConfig.js @@ -0,0 +1,41 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import ReactNativeViewViewConfig from '../../Components/View/ReactNativeViewViewConfig'; +import {type ViewConfig} from '../../Renderer/shims/ReactNativeTypes'; + +const RCTPickerViewConfig = { + uiViewClassName: 'RCTPicker', + bubblingEventTypes: { + topChange: { + phasedRegistrationNames: { + bubbled: 'onChange', + captured: 'onChangeCapture', + }, + }, + }, + directEventTypes: {}, + validAttributes: { + ...ReactNativeViewViewConfig.validAttributes, + color: {process: require('../../StyleSheet/processColor')}, + fontFamily: true, + fontSize: true, + fontStyle: true, + fontWeight: true, + items: true, + onChange: true, + selectedIndex: true, + textAlign: true, + }, +}; + +module.exports = (RCTPickerViewConfig: ViewConfig); diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index c43fde3eecedca..a6692c92bd425f 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -130,6 +130,11 @@ type Props = $ReadOnly<{| * Used only for documentation or testing (e.g. snapshot testing). */ testOnly_pressed?: ?boolean, + + /** + * Duration to wait after press down before calling `onPressIn`. + */ + unstable_pressDelay?: ?number, |}>; /** @@ -152,6 +157,7 @@ function Pressable(props: Props, forwardedRef): React.Node { pressRetentionOffset, style, testOnly_pressed, + unstable_pressDelay, ...restProps } = props; @@ -164,6 +170,14 @@ function Pressable(props: Props, forwardedRef): React.Node { const hitSlop = normalizeRect(props.hitSlop); + const restPropsWithDefaults: React.ElementConfig = { + ...restProps, + ...android_rippleConfig?.viewProps, + accessible: accessible !== false, + focusable: focusable !== false, + hitSlop, + }; + const config = useMemo( () => ({ disabled, @@ -171,6 +185,7 @@ function Pressable(props: Props, forwardedRef): React.Node { pressRectOffset: pressRetentionOffset, android_disableSound, delayLongPress, + delayPressIn: unstable_pressDelay, onLongPress, onPress, onPressIn(event: PressEvent): void { @@ -205,18 +220,15 @@ function Pressable(props: Props, forwardedRef): React.Node { onPressOut, pressRetentionOffset, setPressed, + unstable_pressDelay, ], ); const eventHandlers = usePressability(config); return ( diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js index 61663d6ad50b30..b4d1118cf40533 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js @@ -81,23 +81,27 @@ export type ProgressBarAndroidProps = $ReadOnly<{| * ``` */ const ProgressBarAndroid = ( - props: ProgressBarAndroidProps, + { + styleAttr = 'Normal', + indeterminate = true, + animating = true, + ...restProps + }: ProgressBarAndroidProps, forwardedRef: ?React.Ref, ) => { - return ; + return ( + + ); }; const ProgressBarAndroidToExport = React.forwardRef(ProgressBarAndroid); -/* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an - * error found when Flow v0.89 was deployed. To see the error, delete this - * comment and run Flow. */ -ProgressBarAndroidToExport.defaultProps = { - styleAttr: 'Normal', - indeterminate: true, - animating: true, -}; - /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an * error found when Flow v0.89 was deployed. To see the error, delete this * comment and run Flow. */ diff --git a/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap b/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap index 87b8c16da4f277..f1985dfedb660a 100644 --- a/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap +++ b/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap @@ -18,7 +18,6 @@ exports[` should render as expected: should deep render wh exports[` should render as expected: should shallow render as when mocked 1`] = ` @@ -26,7 +25,6 @@ exports[` should render as expected: should shallow render exports[` should render as expected: should shallow render as when not mocked 1`] = ` diff --git a/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js index 9bd3600eb31571..bc2d26560c7e93 100644 --- a/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js +++ b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js @@ -41,17 +41,9 @@ type NativeProps = $ReadOnly<{| */ progressBackgroundColor?: ?ColorValue, /** - * Size of the refresh indicator, see RefreshControl.SIZE. - * - * This type isn't currently accurate. It really is specific numbers - * hard coded in the Android platform. - * - * Also, 1 isn't actually a safe default. We are able to set this here - * because native code isn't currently consuming the generated artifact. - * This will end up being - * size?: WithDefault<'default' | 'large', 'default'>, + * Size of the refresh indicator. */ - size?: WithDefault, + size?: WithDefault<'default' | 'large', 'default'>, /** * Progress view top offset */ diff --git a/Libraries/Components/RefreshControl/RefreshControl.js b/Libraries/Components/RefreshControl/RefreshControl.js index a85c820791d1e1..f9eb5381c54098 100644 --- a/Libraries/Components/RefreshControl/RefreshControl.js +++ b/Libraries/Components/RefreshControl/RefreshControl.js @@ -22,18 +22,6 @@ import PullToRefreshViewNativeComponent, { Commands as PullToRefreshCommands, } from './PullToRefreshViewNativeComponent'; -let RefreshLayoutConsts: any; -if (Platform.OS === 'android') { - const AndroidSwipeRefreshLayout = require('../../ReactNative/UIManager').getViewManagerConfig( - 'AndroidSwipeRefreshLayout', - ); - RefreshLayoutConsts = AndroidSwipeRefreshLayout - ? AndroidSwipeRefreshLayout.Constants - : {SIZE: {}}; -} else { - RefreshLayoutConsts = {SIZE: {}}; -} - type IOSProps = $ReadOnly<{| /** * The color of the refresh indicator. @@ -63,12 +51,9 @@ type AndroidProps = $ReadOnly<{| */ progressBackgroundColor?: ?ColorValue, /** - * Size of the refresh indicator, see RefreshControl.SIZE. + * Size of the refresh indicator. */ - size?: ?( - | typeof RefreshLayoutConsts.SIZE.DEFAULT - | typeof RefreshLayoutConsts.SIZE.LARGE - ), + size?: ?('default' | 'large'), /** * Progress view top offset */ @@ -137,8 +122,6 @@ export type RefreshControlProps = $ReadOnly<{| * in the `onRefresh` function otherwise the refresh indicator will stop immediately. */ class RefreshControl extends React.Component { - static SIZE: any = RefreshLayoutConsts.SIZE; - _nativeRef: ?React.ElementRef< | typeof PullToRefreshViewNativeComponent | typeof AndroidSwipeRefreshLayoutNativeComponent, diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index 7aef247b62c869..c0be65511536b3 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -186,7 +186,7 @@ const ScrollResponderMixin = { if ( this.props.keyboardShouldPersistTaps === 'handled' && - currentlyFocusedInput != null && + this.scrollResponderKeyboardIsDismissible() && e.target !== currentlyFocusedInput ) { return true; @@ -223,7 +223,6 @@ const ScrollResponderMixin = { // and a new touch starts with a non-textinput target (in which case the // first tap should be sent to the scroll view and dismiss the keyboard, // then the second tap goes to the actual interior view) - const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); const {keyboardShouldPersistTaps} = this.props; const keyboardNeverPersistTaps = !keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never'; @@ -240,7 +239,7 @@ const ScrollResponderMixin = { if ( keyboardNeverPersistTaps && - currentlyFocusedTextInput != null && + this.scrollResponderKeyboardIsDismissible() && e.target != null && !TextInputState.isTextInput(e.target) ) { @@ -250,6 +249,31 @@ const ScrollResponderMixin = { return false; }, + /** + * Do we consider there to be a dismissible soft-keyboard open? + */ + scrollResponderKeyboardIsDismissible: function(): boolean { + const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); + + // We cannot dismiss the keyboard without an input to blur, even if a soft + // keyboard is open (e.g. when keyboard is open due to a native component + // not participating in TextInputState). It's also possible that the + // currently focused input isn't a TextInput (such as by calling ref.focus + // on a non-TextInput). + const hasFocusedTextInput = + currentlyFocusedInput != null && + TextInputState.isTextInput(currentlyFocusedInput); + + // Even if an input is focused, we may not have a keyboard to dismiss. E.g + // when using a physical keyboard. Ensure we have an event for an opened + // keyboard, except on Android where setting windowSoftInputMode to + // adjustNone leads to missing keyboard events. + const softKeyboardMayBeOpen = + this.keyboardWillOpenTo != null || Platform.OS === 'android'; + + return hasFocusedTextInput && softKeyboardMayBeOpen; + }, + /** * Invoke this from an `onResponderReject` event. * @@ -306,6 +330,7 @@ const ScrollResponderMixin = { * Invoke this from an `onResponderRelease` event. */ scrollResponderHandleResponderRelease: function(e: PressEvent) { + this.state.isTouching = e.nativeEvent.touches.length !== 0; this.props.onResponderRelease && this.props.onResponderRelease(e); if (typeof e.target === 'number') { @@ -324,7 +349,7 @@ const ScrollResponderMixin = { if ( this.props.keyboardShouldPersistTaps !== true && this.props.keyboardShouldPersistTaps !== 'always' && - currentlyFocusedTextInput != null && + this.scrollResponderKeyboardIsDismissible() && e.target !== currentlyFocusedTextInput && !this.state.observedScrollSinceBecomingResponder && !this.state.becameResponderWhileAnimating @@ -653,8 +678,8 @@ const ScrollResponderMixin = { this.preventNegativeScrollOffset = false; }, - scrollResponderTextInputFocusError: function(msg: string) { - console.error('Error measuring text field: ', msg); + scrollResponderTextInputFocusError: function() { + console.warn('Error measuring text field.'); }, /** diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js index fa0a173a4fdcc5..dc222eda3a1aca 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js @@ -4,37 +4,24 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import {type ViewProps as Props} from '../View/ViewPropTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ViewProps} from '../View/ViewPropTypes'; +const AndroidHorizontalScrollContentViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'AndroidHorizontalScrollContentView', + () => ({ + uiViewClassName: 'AndroidHorizontalScrollContentView', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: {}, + }), +); -const AndroidHorizontalScrollContentViewViewConfig = { - uiViewClassName: 'AndroidHorizontalScrollContentView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: {}, -}; - -let AndroidHorizontalScrollContentViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'AndroidHorizontalScrollContentView', - AndroidHorizontalScrollContentViewViewConfig, - ); - AndroidHorizontalScrollContentViewNativeComponent = - 'AndroidHorizontalScrollContentView'; -} else { - AndroidHorizontalScrollContentViewNativeComponent = requireNativeComponent( - 'AndroidHorizontalScrollContentView', - ); -} - -export default ((AndroidHorizontalScrollContentViewNativeComponent: any): HostComponent); +export default AndroidHorizontalScrollContentViewNativeComponent; diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js index a4a0d4e6bb8dba..cd424858d048cc 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js @@ -4,54 +4,42 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; +import {type ScrollViewNativeProps as Props} from './ScrollViewNativeComponentType'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ScrollViewNativeProps} from './ScrollViewNativeComponentType'; +const AndroidHorizontalScrollViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'AndroidHorizontalScrollView', + () => ({ + uiViewClassName: 'AndroidHorizontalScrollView', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: { + decelerationRate: true, + disableIntervalMomentum: true, + endFillColor: {process: require('../../StyleSheet/processColor')}, + fadingEdgeLength: true, + nestedScrollEnabled: true, + overScrollMode: true, + pagingEnabled: true, + persistentScrollbar: true, + scrollEnabled: true, + scrollPerfTag: true, + sendMomentumEvents: true, + showsHorizontalScrollIndicator: true, + snapToEnd: true, + snapToInterval: true, + snapToStart: true, + snapToOffsets: true, + contentOffset: true, + }, + }), +); -const AndroidHorizontalScrollViewViewConfig = { - uiViewClassName: 'AndroidHorizontalScrollView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: { - decelerationRate: true, - disableIntervalMomentum: true, - endFillColor: {process: require('../../StyleSheet/processColor')}, - fadingEdgeLength: true, - nestedScrollEnabled: true, - overScrollMode: true, - pagingEnabled: true, - persistentScrollbar: true, - scrollEnabled: true, - scrollPerfTag: true, - sendMomentumEvents: true, - showsHorizontalScrollIndicator: true, - snapToEnd: true, - snapToInterval: true, - snapToStart: true, - snapToOffsets: true, - contentOffset: true, - }, -}; - -let AndroidHorizontalScrollViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'AndroidHorizontalScrollView', - AndroidHorizontalScrollViewViewConfig, - ); - AndroidHorizontalScrollViewNativeComponent = 'AndroidHorizontalScrollView'; -} else { - AndroidHorizontalScrollViewNativeComponent = requireNativeComponent( - 'AndroidHorizontalScrollView', - ); -} - -export default ((AndroidHorizontalScrollViewNativeComponent: any): HostComponent); +export default AndroidHorizontalScrollViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js b/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js index 6a94a30a72dae7..ad184c19dd1956 100644 --- a/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js +++ b/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js @@ -10,30 +10,18 @@ 'use strict'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import {type ViewProps as Props} from '../View/ViewPropTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ViewProps} from '../View/ViewPropTypes'; +const ScrollContentViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTScrollContentView', + () => ({ + uiViewClassName: 'RCTScrollContentView', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: {}, + }), +); -const ScrollContentViewViewConfig = { - uiViewClassName: 'RCTScrollContentView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: {}, -}; - -let ScrollContentViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'RCTScrollContentView', - ScrollContentViewViewConfig, - ); - ScrollContentViewNativeComponent = 'RCTScrollContentView'; -} else { - ScrollContentViewNativeComponent = requireNativeComponent( - 'RCTScrollContentView', - ); -} - -export default ((ScrollContentViewNativeComponent: any): HostComponent); +export default ScrollContentViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 4da263df2e56a6..4ef4f50d3f0ff5 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -40,28 +40,33 @@ import type { import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {State as ScrollResponderState} from '../ScrollResponder'; import type {ViewProps} from '../View/ViewPropTypes'; +import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeader'; -import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; -import ScrollViewNativeComponent from './ScrollViewNativeComponent'; -import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent'; -import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent'; import AndroidHorizontalScrollContentViewNativeComponent from './AndroidHorizontalScrollContentViewNativeComponent'; +import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent'; +import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent'; +import ScrollViewNativeComponent from './ScrollViewNativeComponent'; -let AndroidScrollView; -let AndroidHorizontalScrollContentView; -let AndroidHorizontalScrollView; -let RCTScrollView; -let RCTScrollContentView; - -if (Platform.OS === 'android') { - AndroidScrollView = ScrollViewNativeComponent; - AndroidHorizontalScrollView = AndroidHorizontalScrollViewNativeComponent; - AndroidHorizontalScrollContentView = AndroidHorizontalScrollContentViewNativeComponent; -} else { - RCTScrollView = ScrollViewNativeComponent; - RCTScrollContentView = ScrollContentViewNativeComponent; -} +const {NativeHorizontalScrollViewTuple, NativeVerticalScrollViewTuple} = + Platform.OS === 'android' + ? { + NativeHorizontalScrollViewTuple: [ + AndroidHorizontalScrollViewNativeComponent, + AndroidHorizontalScrollContentViewNativeComponent, + ], + NativeVerticalScrollViewTuple: [ScrollViewNativeComponent, View], + } + : { + NativeHorizontalScrollViewTuple: [ + ScrollViewNativeComponent, + ScrollContentViewNativeComponent, + ], + NativeVerticalScrollViewTuple: [ + ScrollViewNativeComponent, + ScrollContentViewNativeComponent, + ], + }; // Public methods for ScrollView export type ScrollViewImperativeMethods = $ReadOnly<{| @@ -803,13 +808,13 @@ class ScrollView extends React.Component { return ReactNative.findNodeHandle(this._scrollViewRef); }; - getInnerViewNode(): ?number { + getInnerViewNode: () => ?number = () => { return ReactNative.findNodeHandle(this._innerViewRef); - } + }; - getInnerViewRef(): ?React.ElementRef { + getInnerViewRef: () => ?React.ElementRef = () => { return this._innerViewRef; - } + }; getNativeScrollRef: () => ?React.ElementRef> = () => { return this._scrollViewRef; @@ -1008,30 +1013,10 @@ class ScrollView extends React.Component { }); render(): React.Node | React.Element { - let ScrollViewClass; - let ScrollContentContainerViewClass; - if (Platform.OS === 'android') { - if (this.props.horizontal === true) { - ScrollViewClass = AndroidHorizontalScrollView; - ScrollContentContainerViewClass = AndroidHorizontalScrollContentView; - } else { - ScrollViewClass = AndroidScrollView; - ScrollContentContainerViewClass = View; - } - } else { - ScrollViewClass = RCTScrollView; - ScrollContentContainerViewClass = RCTScrollContentView; - } - - invariant( - ScrollViewClass !== undefined, - 'ScrollViewClass must not be undefined', - ); - - invariant( - ScrollContentContainerViewClass !== undefined, - 'ScrollContentContainerViewClass must not be undefined', - ); + const [NativeDirectionalScrollView, NativeDirectionalScrollContentView] = + this.props.horizontal === true + ? NativeHorizontalScrollViewTuple + : NativeVerticalScrollViewTuple; const contentContainerStyle = [ this.props.horizontal === true && styles.contentContainerHorizontal, @@ -1050,12 +1035,12 @@ class ScrollView extends React.Component { ); } - let contentSizeChangeProps = {}; - if (this.props.onContentSizeChange) { - contentSizeChangeProps = { - onLayout: this._handleContentOnLayout, - }; - } + const contentSizeChangeProps = + this.props.onContentSizeChange == null + ? null + : { + onLayout: this._handleContentOnLayout, + }; const {stickyHeaderIndices} = this.props; let children = this.props.children; @@ -1101,10 +1086,7 @@ class ScrollView extends React.Component { Array.isArray(stickyHeaderIndices) && stickyHeaderIndices.length > 0; const contentContainer = ( - /* $FlowFixMe(>=0.112.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.112 was deployed. To see the error, delete - * this comment and run Flow. */ - { } collapsable={false}> {children} - + ); const alwaysBounceHorizontal = @@ -1138,7 +1120,7 @@ class ScrollView extends React.Component { ...this.props, alwaysBounceHorizontal, alwaysBounceVertical, - style: [baseStyle, this.props.style], + style: StyleSheet.compose(baseStyle, this.props.style), // Override the onContentSizeChange from props, since this event can // bubble up from TextInputs onContentSizeChange: null, @@ -1206,15 +1188,11 @@ class ScrollView extends React.Component { if (refreshControl) { if (Platform.OS === 'ios') { // On iOS the RefreshControl is a child of the ScrollView. - // tvOS lacks native support for RefreshControl, so don't include it in that case return ( - /* $FlowFixMe(>=0.117.0 site=react_native_fb) This comment suppresses - * an error found when Flow v0.117 was deployed. To see the error, - * delete this comment and run Flow. */ - - {Platform.isTV ? null : refreshControl} + + {refreshControl} {contentContainer} - + ); } else if (Platform.OS === 'android') { // On Android wrap the ScrollView with a AndroidSwipeRefreshLayout. @@ -1225,20 +1203,20 @@ class ScrollView extends React.Component { const {outer, inner} = splitLayoutProps(flattenStyle(props.style)); return React.cloneElement( refreshControl, - {style: [baseStyle, outer]}, - {contentContainer} - , + , ); } } return ( - + {contentContainer} - + ); } } diff --git a/Libraries/Components/ScrollView/ScrollViewContext.js b/Libraries/Components/ScrollView/ScrollViewContext.js index f774483912d928..894d7f0a56555d 100644 --- a/Libraries/Components/ScrollView/ScrollViewContext.js +++ b/Libraries/Components/ScrollView/ScrollViewContext.js @@ -15,7 +15,9 @@ import * as React from 'react'; type Value = {horizontal: boolean} | null; const ScrollViewContext: React.Context = React.createContext(null); - +if (__DEV__) { + ScrollViewContext.displayName = 'ScrollViewContext'; +} export default ScrollViewContext; export const HORIZONTAL: Value = Object.freeze({horizontal: true}); diff --git a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 1e1100f0cc3165..29585037ef40cb 100644 --- a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -4,29 +4,84 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; -import ScrollViewViewConfig from './ScrollViewViewConfig'; +import {type ScrollViewNativeProps as Props} from './ScrollViewNativeComponentType'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; -import type { - ScrollViewNativeProps, - ScrollViewNativeComponentType, -} from './ScrollViewNativeComponentType'; +const ScrollViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTScrollView', + () => ({ + uiViewClassName: 'RCTScrollView', + bubblingEventTypes: {}, + directEventTypes: { + topScrollToTop: { + registrationName: 'onScrollToTop', + }, + }, + validAttributes: { + alwaysBounceHorizontal: true, + alwaysBounceVertical: true, + automaticallyAdjustContentInsets: true, + bounces: true, + bouncesZoom: true, + canCancelContentTouches: true, + centerContent: true, + contentInset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentOffset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentInsetAdjustmentBehavior: true, + decelerationRate: true, + directionalLockEnabled: true, + disableIntervalMomentum: true, + endFillColor: { + process: require('../../StyleSheet/processColor'), + }, + fadingEdgeLength: true, + indicatorStyle: true, + inverted: true, + keyboardDismissMode: true, + maintainVisibleContentPosition: true, + maximumZoomScale: true, + minimumZoomScale: true, + nestedScrollEnabled: true, + onMomentumScrollBegin: true, + onMomentumScrollEnd: true, + onScroll: true, + onScrollBeginDrag: true, + onScrollEndDrag: true, + onScrollToTop: true, + overScrollMode: true, + pagingEnabled: true, + persistentScrollbar: true, + pinchGestureEnabled: true, + scrollEnabled: true, + scrollEventThrottle: true, + scrollIndicatorInsets: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + scrollPerfTag: true, + scrollToOverflowEnabled: true, + scrollsToTop: true, + sendMomentumEvents: true, + showsHorizontalScrollIndicator: true, + showsVerticalScrollIndicator: true, + snapToAlignment: true, + snapToEnd: true, + snapToInterval: true, + snapToOffsets: true, + snapToStart: true, + zoomScale: true, + }, + }), +); -let ScrollViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig('RCTScrollView', ScrollViewViewConfig); - ScrollViewNativeComponent = 'RCTScrollView'; -} else { - ScrollViewNativeComponent = requireNativeComponent( - 'RCTScrollView', - ); -} - -export default ((ScrollViewNativeComponent: any): ScrollViewNativeComponentType); +export default ScrollViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js b/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js index a6366e8b62b347..405667d1f38059 100644 --- a/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +++ b/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js @@ -4,18 +4,13 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {ViewProps} from '../View/ViewPropTypes'; -import type { - ViewStyleProp, - DangerouslyImpreciseStyle, -} from '../../StyleSheet/StyleSheet'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; import type {ScrollEvent} from '../../Types/CoreEventTypes'; @@ -45,10 +40,10 @@ export type ScrollViewNativeProps = $ReadOnly<{ fadingEdgeLength?: ?number, indicatorStyle?: ?('default' | 'black' | 'white'), keyboardDismissMode?: ?('none' | 'on-drag' | 'interactive'), - maintainVisibleContentPosition?: ?$ReadOnly<{| + maintainVisibleContentPosition?: ?$ReadOnly<{ minIndexForVisible: number, autoscrollToTopThreshold?: ?number, - |}>, + }>, maximumZoomScale?: ?number, minimumZoomScale?: ?number, nestedScrollEnabled?: ?boolean, @@ -78,9 +73,6 @@ export type ScrollViewNativeProps = $ReadOnly<{ snapToStart?: ?boolean, zoomScale?: ?number, // Overrides - style?: {...ViewStyleProp, ...} | DangerouslyImpreciseStyle, - onResponderGrant?: ?(e: any) => void | boolean, + onResponderGrant?: ?(e: $FlowFixMe) => void | boolean, ... }>; - -export type ScrollViewNativeComponentType = HostComponent; diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index 3bafcabcdb5c7d..521b965b53814f 100644 --- a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -67,6 +67,15 @@ class ScrollViewStickyHeader extends React.Component { this.setState({nextHeaderLayoutY: y}); } + componentWillUnmount() { + if (this._translateY != null && this._animatedValueListenerId != null) { + this._translateY.removeListener(this._animatedValueListenerId); + } + if (this._timer) { + clearTimeout(this._timer); + } + } + UNSAFE_componentWillReceiveProps(nextProps: Props) { if ( nextProps.scrollViewHeight !== this.props.scrollViewHeight || @@ -122,19 +131,6 @@ class ScrollViewStickyHeader extends React.Component { this.setState({ translateY: value, }); - // This fixes jank on iOS, especially around paging, - // but causes jank on Android. - // It seems that Native Animated Driver on iOS has - // more conflicts with values passed through the ShadowTree - // especially when connecting new Animated nodes + disconnecting - // old ones, compared to Android where that process seems fine. - if (Platform.OS === 'ios') { - setTimeout(() => { - this.setState({ - translateY: null, - }); - }, 0); - } } }, this._debounceTimeout); }; @@ -179,9 +175,10 @@ class ScrollViewStickyHeader extends React.Component { render(): React.Node { // Fabric Detection - // eslint-disable-next-line dot-notation const isFabric = !!( - this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical + // An internal transform mangles variables with leading "_" as private. + // eslint-disable-next-line dot-notation + (this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical) ); // Initially and in the case of updated props or layout, we diff --git a/Libraries/Components/ScrollView/ScrollViewViewConfig.js b/Libraries/Components/ScrollView/ScrollViewViewConfig.js index b2a3a9246b343b..19818e0fae8440 100644 --- a/Libraries/Components/ScrollView/ScrollViewViewConfig.js +++ b/Libraries/Components/ScrollView/ScrollViewViewConfig.js @@ -10,7 +10,7 @@ 'use strict'; -import type {GeneratedViewConfig} from '../../Utilities/registerGeneratedViewConfig'; +import type {PartialViewConfig} from '../../Renderer/shims/ReactNativeTypes'; const ScrollViewViewConfig = { uiViewClassName: 'RCTScrollView', @@ -28,15 +28,22 @@ const ScrollViewViewConfig = { bouncesZoom: true, canCancelContentTouches: true, centerContent: true, - contentInset: {diff: require('../../Utilities/differ/pointsDiffer')}, - contentOffset: {diff: require('../../Utilities/differ/pointsDiffer')}, + contentInset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentOffset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, contentInsetAdjustmentBehavior: true, decelerationRate: true, directionalLockEnabled: true, disableIntervalMomentum: true, - endFillColor: {process: require('../../StyleSheet/processColor')}, + endFillColor: { + process: require('../../StyleSheet/processColor'), + }, fadingEdgeLength: true, indicatorStyle: true, + inverted: true, keyboardDismissMode: true, maintainVisibleContentPosition: true, maximumZoomScale: true, @@ -72,4 +79,4 @@ const ScrollViewViewConfig = { }, }; -module.exports = (ScrollViewViewConfig: GeneratedViewConfig); +module.exports = (ScrollViewViewConfig: PartialViewConfig); diff --git a/Libraries/Components/ScrollView/__tests__/ScrollView-test.js b/Libraries/Components/ScrollView/__tests__/ScrollView-test.js index fb7aa74a55703e..6800bb2a681931 100644 --- a/Libraries/Components/ScrollView/__tests__/ScrollView-test.js +++ b/Libraries/Components/ScrollView/__tests__/ScrollView-test.js @@ -48,4 +48,20 @@ describe('', () => { jest.fn().constructor, ); }); + it('getInnerViewRef for case where it returns a native view', () => { + jest.resetModules(); + jest.unmock('../ScrollView'); + + const scrollViewRef = React.createRef(null); + + ReactTestRenderer.create(); + + const innerViewRef = scrollViewRef.current.getInnerViewRef(); + + // This is checking if the ref acts like a host component. If we had an + // `isHostComponent(ref)` method, that would be preferred. + expect(innerViewRef.measure).toBeInstanceOf(jest.fn().constructor); + expect(innerViewRef.measureLayout).toBeInstanceOf(jest.fn().constructor); + expect(innerViewRef.measureInWindow).toBeInstanceOf(jest.fn().constructor); + }); }); diff --git a/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap b/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap index 1afba0ee035cd2..de40fd6e028016 100644 --- a/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap +++ b/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap @@ -40,15 +40,12 @@ exports[` should render as expected: should deep render when not m snapToEnd={true} snapToStart={true} style={ - Array [ - Object { - "flexDirection": "column", - "flexGrow": 1, - "flexShrink": 1, - "overflow": "scroll", - }, - undefined, - ] + Object { + "flexDirection": "column", + "flexGrow": 1, + "flexShrink": 1, + "overflow": "scroll", + } } > {} module.exports = (new StatusBarIOS(NativeStatusBarManagerIOS): StatusBarIOS); diff --git a/Libraries/Components/Switch/Switch.js b/Libraries/Components/Switch/Switch.js index 9287c60e29af8e..d2f4cf750e35ae 100644 --- a/Libraries/Components/Switch/Switch.js +++ b/Libraries/Components/Switch/Switch.js @@ -173,39 +173,39 @@ class Switch extends React.Component { ref={this._handleSwitchNativeComponentRef} /> ); - } - - const platformProps = { - disabled, - onTintColor: trackColorForTrue, - style: StyleSheet.compose( - {height: 31, width: 51}, - StyleSheet.compose( - style, - ios_backgroundColor == null - ? null - : { - backgroundColor: ios_backgroundColor, - borderRadius: 16, - }, + } else { + const platformProps = { + disabled, + onTintColor: trackColorForTrue, + style: StyleSheet.compose( + {height: 31, width: 51}, + StyleSheet.compose( + style, + ios_backgroundColor == null + ? null + : { + backgroundColor: ios_backgroundColor, + borderRadius: 16, + }, + ), ), - ), - thumbTintColor: thumbColor, - tintColor: trackColorForFalse, - value: value === true, - }; + thumbTintColor: thumbColor, + tintColor: trackColorForFalse, + value: value === true, + }; - return ( - - ); + return ( + + ); + } } componentDidUpdate() { diff --git a/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js b/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js index dffccc428ff01a..9568442adf4f7a 100644 --- a/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +++ b/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js @@ -26,7 +26,7 @@ import requireNativeComponent from '../../ReactNative/requireNativeComponent'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; import type {TextInputNativeCommands} from './TextInputNativeCommands'; import AndroidTextInputViewConfig from './AndroidTextInputViewConfig'; -const ReactNativeViewConfigRegistry = require('../../Renderer/shims/ReactNativeViewConfigRegistry'); +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; export type KeyboardType = // Cross Platform @@ -545,17 +545,10 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['focus', 'blur', 'setTextAndSelection'], }); -let AndroidTextInputNativeComponent; -if (global.RN$Bridgeless) { - ReactNativeViewConfigRegistry.register('AndroidTextInput', () => { - return AndroidTextInputViewConfig; - }); - AndroidTextInputNativeComponent = 'AndroidTextInput'; -} else { - AndroidTextInputNativeComponent = requireNativeComponent( - 'AndroidTextInput', - ); -} +let AndroidTextInputNativeComponent = NativeComponentRegistry.get( + 'AndroidTextInput', + () => AndroidTextInputViewConfig, +); // flowlint-next-line unclear-type:off export default ((AndroidTextInputNativeComponent: any): HostComponent); diff --git a/Libraries/Components/TextInput/AndroidTextInputViewConfig.js b/Libraries/Components/TextInput/AndroidTextInputViewConfig.js index 0853b60a75dc65..553911491b1111 100644 --- a/Libraries/Components/TextInput/AndroidTextInputViewConfig.js +++ b/Libraries/Components/TextInput/AndroidTextInputViewConfig.js @@ -11,7 +11,7 @@ 'use strict'; import ReactNativeViewViewConfig from '../../Components/View/ReactNativeViewViewConfig'; -import type {ReactNativeBaseComponentViewConfig} from '../../Renderer/shims/ReactNativeTypes'; +import {type PartialViewConfig} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; const AndroidTextInputViewConfig = { uiViewClassName: 'AndroidTextInput', @@ -58,6 +58,9 @@ const AndroidTextInputViewConfig = { ...ReactNativeViewViewConfig.validAttributes, maxFontSizeMultiplier: true, + adjustsFontSizeToFit: true, + minimumFontScale: true, + autoFocus: true, placeholder: true, inlineImagePadding: true, contextMenuHidden: true, @@ -80,7 +83,7 @@ const AndroidTextInputViewConfig = { returnKeyType: true, keyboardType: true, multiline: true, - color: true, + color: {process: require('../../StyleSheet/processColor')}, autoCompleteType: true, numberOfLines: true, letterSpacing: true, @@ -111,4 +114,4 @@ const AndroidTextInputViewConfig = { }, }; -module.exports = (AndroidTextInputViewConfig: ReactNativeBaseComponentViewConfig<>); +module.exports = (AndroidTextInputViewConfig: PartialViewConfig); diff --git a/Libraries/Components/TextInput/RCTSinglelineTextInputViewConfig.js b/Libraries/Components/TextInput/RCTSinglelineTextInputViewConfig.js index 4836323d1a3615..990bcbb1c271ce 100644 --- a/Libraries/Components/TextInput/RCTSinglelineTextInputViewConfig.js +++ b/Libraries/Components/TextInput/RCTSinglelineTextInputViewConfig.js @@ -11,7 +11,7 @@ 'use strict'; import ReactNativeViewViewConfig from '../../Components/View/ReactNativeViewViewConfig'; -import type {ReactNativeBaseComponentViewConfig} from '../../Renderer/shims/ReactNativeTypes'; +import {type ViewConfig} from '../../Renderer/shims/ReactNativeTypes'; const RCTSinglelineTextInputViewConfig = { uiViewClassName: 'RCTSinglelineTextInputView', @@ -131,4 +131,4 @@ const RCTSinglelineTextInputViewConfig = { }, }; -module.exports = (RCTSinglelineTextInputViewConfig: ReactNativeBaseComponentViewConfig<>); +module.exports = (RCTSinglelineTextInputViewConfig: ViewConfig); diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index a46efe02c63e99..0e4c7faf3f63b0 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -206,26 +206,6 @@ export type TextContentType = type PasswordRules = string; type IOSProps = $ReadOnly<{| - /** - * If `false`, disables spell-check style (i.e. red underlines). - * The default value is inherited from `autoCorrect`. - * @platform ios - */ - spellCheck?: ?boolean, - - /** - * Determines the color of the keyboard. - * @platform ios - */ - keyboardAppearance?: ?('default' | 'light' | 'dark'), - - /** - * If `true`, the keyboard disables the return key when there is no text and - * automatically enables it when there is text. The default value is `false`. - * @platform ios - */ - enablesReturnKeyAutomatically?: ?boolean, - /** * When the clear button should appear on the right side of the text view. * This property is supported only for single-line TextInput component. @@ -261,6 +241,13 @@ type IOSProps = $ReadOnly<{| | ?DataDetectorTypesType | $ReadOnlyArray, + /** + * If `true`, the keyboard disables the return key when there is no text and + * automatically enables it when there is text. The default value is `false`. + * @platform ios + */ + enablesReturnKeyAutomatically?: ?boolean, + /** * An optional identifier which links a custom InputAccessoryView to * this text input. The InputAccessoryView is rendered above the @@ -270,11 +257,10 @@ type IOSProps = $ReadOnly<{| inputAccessoryViewID?: ?string, /** - * Give the keyboard and the system information about the - * expected semantic meaning for the content that users enter. + * Determines the color of the keyboard. * @platform ios */ - textContentType?: ?TextContentType, + keyboardAppearance?: ?('default' | 'light' | 'dark'), /** * Provide rules for your password. @@ -299,6 +285,20 @@ type IOSProps = $ReadOnly<{| * @platform ios */ scrollEnabled?: ?boolean, + + /** + * If `false`, disables spell-check style (i.e. red underlines). + * The default value is inherited from `autoCorrect`. + * @platform ios + */ + spellCheck?: ?boolean, + + /** + * Give the keyboard and the system information about the + * expected semantic meaning for the content that users enter. + * @platform ios + */ + textContentType?: ?TextContentType, |}>; type AndroidProps = $ReadOnly<{| @@ -342,19 +342,6 @@ type AndroidProps = $ReadOnly<{| | 'off' ), - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android - */ - returnKeyLabel?: ?string, - - /** - * Sets the number of lines for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. - * @platform android - */ - numberOfLines?: ?number, - /** * When `false`, if there is a small amount of space available around a text input * (e.g. landscape orientation on a phone), the OS may choose to have the user edit @@ -365,18 +352,13 @@ type AndroidProps = $ReadOnly<{| */ disableFullscreenUI?: ?boolean, - /** - * Set text break strategy on Android API Level 23+, possible values are `simple`, `highQuality`, `balanced` - * The default value is `simple`. - * @platform android - */ - textBreakStrategy?: ?('simple' | 'highQuality' | 'balanced'), - - /** - * The color of the `TextInput` underline. - * @platform android - */ - underlineColorAndroid?: ?ColorValue, + importantForAutofill?: ?( + | 'auto' + | 'no' + | 'noExcludeDescendants' + | 'yes' + | 'yesExcludeDescendants' + ), /** * If defined, the provided image resource will be rendered on the left. @@ -397,19 +379,37 @@ type AndroidProps = $ReadOnly<{| */ inlineImagePadding?: ?number, - importantForAutofill?: ?( - | 'auto' - | 'no' - | 'noExcludeDescendants' - | 'yes' - | 'yesExcludeDescendants' - ), + /** + * Sets the number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. + * @platform android + */ + numberOfLines?: ?number, + + /** + * Sets the return key to the label. Use it instead of `returnKeyType`. + * @platform android + */ + returnKeyLabel?: ?string, /** * When `false`, it will prevent the soft keyboard from showing when the field is focused. * Defaults to `true`. */ showSoftInputOnFocus?: ?boolean, + + /** + * Set text break strategy on Android API Level 23+, possible values are `simple`, `highQuality`, `balanced` + * The default value is `simple`. + * @platform android + */ + textBreakStrategy?: ?('simple' | 'highQuality' | 'balanced'), + + /** + * The color of the `TextInput` underline. + * @platform android + */ + underlineColorAndroid?: ?ColorValue, |}>; export type Props = $ReadOnly<{| @@ -445,19 +445,46 @@ export type Props = $ReadOnly<{| allowFontScaling?: ?boolean, /** - * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. - * Possible values: - * `null/undefined` (default): inherit from the parent node or the global default (0) - * `0`: no max, ignore parent/global default - * `>= 1`: sets the maxFontSizeMultiplier of this node to this value + * If `true`, the text field will blur when submitted. + * The default value is true for single-line fields and false for + * multiline fields. Note that for multiline fields, setting `blurOnSubmit` + * to `true` means that pressing return will blur the field and trigger the + * `onSubmitEditing` event instead of inserting a newline into the field. */ - maxFontSizeMultiplier?: ?number, + blurOnSubmit?: ?boolean, + + /** + * If `true`, caret is hidden. The default value is `false`. + * + * On Android devices manufactured by Xiaomi with Android Q, + * when keyboardType equals 'email-address'this will be set + * in native to 'true' to prevent a system related crash. This + * will cause cursor to be diabled as a side-effect. + * + */ + caretHidden?: ?boolean, + + /* + * If `true`, contextMenuHidden is hidden. The default value is `false`. + */ + contextMenuHidden?: ?boolean, + + /** + * Provides an initial value that will change when the user starts typing. + * Useful for simple use-cases where you do not want to deal with listening + * to events and updating the value prop to keep the controlled state in sync. + */ + defaultValue?: ?Stringish, /** * If `false`, text is not editable. The default value is `true`. */ editable?: ?boolean, + forwardedRef?: ?ReactRefSetter< + React.ElementRef> & ImperativeMethods, + >, + /** * Determines which keyboard to open, e.g.`numeric`. * @@ -491,38 +518,13 @@ export type Props = $ReadOnly<{| keyboardType?: ?KeyboardType, /** - * Determines how the return key should look. On Android you can also use - * `returnKeyLabel`. - * - * *Cross platform* - * - * The following values work across platforms: - * - * - `done` - * - `go` - * - `next` - * - `search` - * - `send` - * - * *Android Only* - * - * The following values work on Android only: - * - * - `none` - * - `previous` - * - * *iOS Only* - * - * The following values work on iOS only: - * - * - `default` - * - `emergency-call` - * - `google` - * - `join` - * - `route` - * - `yahoo` + * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. + * Possible values: + * `null/undefined` (default): inherit from the parent node or the global default (0) + * `0`: no max, ignore parent/global default + * `>= 1`: sets the maxFontSizeMultiplier of this node to this value */ - returnKeyType?: ?ReturnKeyType, + maxFontSizeMultiplier?: ?number, /** * Limits the maximum number of characters that can be entered. Use this @@ -541,11 +543,6 @@ export type Props = $ReadOnly<{| */ onBlur?: ?(e: BlurEvent) => mixed, - /** - * Callback that is called when the text input is focused. - */ - onFocus?: ?(e: FocusEvent) => mixed, - /** * Callback that is called when the text input's text changes. */ @@ -571,6 +568,20 @@ export type Props = $ReadOnly<{| */ onEndEditing?: ?(e: EditingEvent) => mixed, + /** + * Callback that is called when the text input is focused. + */ + onFocus?: ?(e: FocusEvent) => mixed, + + /** + * Callback that is called when a key is pressed. + * This will be called with `{ nativeEvent: { key: keyValue } }` + * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and + * the typed-in character otherwise including `' '` for space. + * Fires before `onChange` callbacks. + */ + onKeyPress?: ?(e: KeyPressEvent) => mixed, + /** * Called when a touch is engaged. */ @@ -594,15 +605,6 @@ export type Props = $ReadOnly<{| */ onSubmitEditing?: ?(e: EditingEvent) => mixed, - /** - * Callback that is called when a key is pressed. - * This will be called with `{ nativeEvent: { key: keyValue } }` - * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and - * the typed-in character otherwise including `' '` for space. - * Fires before `onChange` callbacks. - */ - onKeyPress?: ?(e: KeyPressEvent) => mixed, - /** * Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`. * May also contain other properties from ScrollEvent but on Android contentSize @@ -621,15 +623,44 @@ export type Props = $ReadOnly<{| placeholderTextColor?: ?ColorValue, /** - * 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}'. + * Determines how the return key should look. On Android you can also use + * `returnKeyLabel`. + * + * *Cross platform* + * + * The following values work across platforms: + * + * - `done` + * - `go` + * - `next` + * - `search` + * - `send` + * + * *Android Only* + * + * The following values work on Android only: + * + * - `none` + * - `previous` + * + * *iOS Only* + * + * The following values work on iOS only: + * + * - `default` + * - `emergency-call` + * - `google` + * - `join` + * - `route` + * - `yahoo` */ - secureTextEntry?: ?boolean, + returnKeyType?: ?ReturnKeyType, /** - * The highlight and cursor color of the text input. + * 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}'. */ - selectionColor?: ?ColorValue, + secureTextEntry?: ?boolean, /** * The start and end of the text input's selection. Set start and end to @@ -641,37 +672,15 @@ export type Props = $ReadOnly<{| |}>, /** - * The value to show for the text input. `TextInput` is a controlled - * component, which means the native value will be forced to match this - * value prop if provided. For most uses, this works great, but in some - * cases this may cause flickering - one common cause is preventing edits - * by keeping value the same. In addition to simply setting the same value, - * either set `editable={false}`, or set/update `maxLength` to prevent - * unwanted edits without flicker. - */ - value?: ?Stringish, - - /** - * Provides an initial value that will change when the user starts typing. - * Useful for simple use-cases where you do not want to deal with listening - * to events and updating the value prop to keep the controlled state in sync. + * The highlight and cursor color of the text input. */ - defaultValue?: ?Stringish, + selectionColor?: ?ColorValue, /** * If `true`, all text will automatically be selected on focus. */ selectTextOnFocus?: ?boolean, - /** - * If `true`, the text field will blur when submitted. - * The default value is true for single-line fields and false for - * multiline fields. Note that for multiline fields, setting `blurOnSubmit` - * to `true` means that pressing return will blur the field and trigger the - * `onSubmitEditing` event instead of inserting a newline into the field. - */ - blurOnSubmit?: ?boolean, - /** * Note that not all Text styles are supported, an incomplete list of what is not supported includes: * @@ -692,24 +701,15 @@ export type Props = $ReadOnly<{| style?: ?TextStyleProp, /** - * If `true`, caret is hidden. The default value is `false`. - * - * On Android devices manufactured by Xiaomi with Android Q, - * when keyboardType equals 'email-address'this will be set - * in native to 'true' to prevent a system related crash. This - * will cause cursor to be diabled as a side-effect. - * - */ - caretHidden?: ?boolean, - - /* - * If `true`, contextMenuHidden is hidden. The default value is `false`. + * The value to show for the text input. `TextInput` is a controlled + * component, which means the native value will be forced to match this + * value prop if provided. For most uses, this works great, but in some + * cases this may cause flickering - one common cause is preventing edits + * by keeping value the same. In addition to simply setting the same value, + * either set `editable={false}`, or set/update `maxLength` to prevent + * unwanted edits without flicker. */ - contextMenuHidden?: ?boolean, - - forwardedRef?: ?ReactRefSetter< - React.ElementRef> & ImperativeMethods, - >, + value?: ?Stringish, |}>; type ImperativeMethods = $ReadOnly<{| @@ -1164,21 +1164,27 @@ const ExportedForwardRef: React.AbstractComponent< React.ElementConfig, React.ElementRef> & ImperativeMethods, > = React.forwardRef(function TextInput( - props, + { + allowFontScaling = true, + rejectResponderTermination = true, + underlineColorAndroid = 'transparent', + ...restProps + }, forwardedRef: ReactRefSetter< React.ElementRef> & ImperativeMethods, >, ) { - return ; + return ( + + ); }); -// $FlowFixMe -ExportedForwardRef.defaultProps = { - allowFontScaling: true, - rejectResponderTermination: true, - underlineColorAndroid: 'transparent', -}; - // TODO: Deprecate this // $FlowFixMe ExportedForwardRef.propTypes = DeprecatedTextInputPropTypes; diff --git a/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap b/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap index 9ab974ba299412..ea9693e96244c5 100644 --- a/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap +++ b/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap @@ -56,18 +56,6 @@ exports[`TextInput tests should render as expected: should deep render when not /> `; -exports[`TextInput tests should render as expected: should shallow render as when mocked 1`] = ` - -`; +exports[`TextInput tests should render as expected: should shallow render as when mocked 1`] = ``; -exports[`TextInput tests should render as expected: should shallow render as when not mocked 1`] = ` - -`; +exports[`TextInput tests should render as expected: should shallow render as when not mocked 1`] = ``; diff --git a/Libraries/Components/Touchable/TVTouchable.js b/Libraries/Components/Touchable/TVTouchable.js deleted file mode 100644 index 01e51ba766509a..00000000000000 --- a/Libraries/Components/Touchable/TVTouchable.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -'use strict'; - -import invariant from 'invariant'; -import ReactNative from '../../Renderer/shims/ReactNative'; -import type { - BlurEvent, - FocusEvent, - PressEvent, -} from '../../Types/CoreEventTypes'; -import Platform from '../../Utilities/Platform'; -import TVEventHandler from '../../Components/AppleTV/TVEventHandler'; - -type TVTouchableConfig = $ReadOnly<{| - getDisabled: () => boolean, - onBlur: (event: BlurEvent) => mixed, - onFocus: (event: FocusEvent) => mixed, - onPress: (event: PressEvent) => mixed, -|}>; - -export default class TVTouchable { - _tvEventHandler: TVEventHandler; - - constructor(component: any, config: TVTouchableConfig) { - invariant(Platform.isTV, 'TVTouchable: Requires `Platform.isTV`.'); - this._tvEventHandler = new TVEventHandler(); - this._tvEventHandler.enable(component, (_, tvData) => { - tvData.dispatchConfig = {}; - if (ReactNative.findNodeHandle(component) === tvData.tag) { - if (tvData.eventType === 'focus') { - config.onFocus(tvData); - } else if (tvData.eventType === 'blur') { - config.onBlur(tvData); - } else if (tvData.eventType === 'select') { - if (!config.getDisabled()) { - config.onPress(tvData); - } - } - } - }); - } - - destroy(): void { - this._tvEventHandler.disable(); - } -} diff --git a/Libraries/Components/Touchable/Touchable.js b/Libraries/Components/Touchable/Touchable.js index 8bfa1cb75eeb26..6f05d2ea14b374 100644 --- a/Libraries/Components/Touchable/Touchable.js +++ b/Libraries/Components/Touchable/Touchable.js @@ -14,15 +14,12 @@ const BoundingDimensions = require('./BoundingDimensions'); const Platform = require('../../Utilities/Platform'); const Position = require('./Position'); const React = require('react'); -const ReactNative = require('../../Renderer/shims/ReactNative'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const TVEventHandler = require('../AppleTV/TVEventHandler'); const UIManager = require('../../ReactNative/UIManager'); -const View = require('../View/View'); const SoundManager = require('../Sound/SoundManager'); -const normalizeColor = require('../../StyleSheet/normalizeColor'); +import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; +import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; import type {PressEvent} from '../../Types/CoreEventTypes'; @@ -370,33 +367,12 @@ const TouchableMixin = { if (!Platform.isTV) { return; } - - this._tvEventHandler = new TVEventHandler(); - this._tvEventHandler.enable(this, function(cmp, evt) { - const myTag = ReactNative.findNodeHandle(cmp); - evt.dispatchConfig = {}; - if (myTag === evt.tag) { - if (evt.eventType === 'focus') { - cmp.touchableHandleFocus(evt); - } else if (evt.eventType === 'blur') { - cmp.touchableHandleBlur(evt); - } else if (evt.eventType === 'select' && Platform.OS !== 'android') { - cmp.touchableHandlePress && - !cmp.props.disabled && - cmp.touchableHandlePress(evt); - } - } - }); }, /** * Clear all timeouts on unmount */ componentWillUnmount: function() { - if (this._tvEventHandler) { - this._tvEventHandler.disable(); - delete this._tvEventHandler; - } this.touchableDelayTimeout && clearTimeout(this.touchableDelayTimeout); this.longPressDelayTimeout && clearTimeout(this.longPressDelayTimeout); this.pressOutDelayTimeout && clearTimeout(this.pressOutDelayTimeout); @@ -922,7 +898,6 @@ TouchableMixin.withoutDefaultFocusAndBlur = TouchableMixinWithoutDefaultFocusAnd const Touchable = { Mixin: TouchableMixin, - TOUCH_TARGET_DEBUG: false, // Highlights all touchable targets. Toggle with Inspector. /** * Renders a debugging overlay to visualize touch target with hitSlop (might not work on Android). */ @@ -930,54 +905,15 @@ const Touchable = { color, hitSlop, }: { - color: string | number, + color: ColorValue, hitSlop: EdgeInsetsProp, ... }): null | React.Node => { - if (!Touchable.TOUCH_TARGET_DEBUG) { - return null; - } - if (!__DEV__) { - throw Error( - 'Touchable.TOUCH_TARGET_DEBUG should not be enabled in prod!', - ); + if (__DEV__) { + return ; } - const debugHitSlopStyle = {}; - hitSlop = hitSlop || {top: 0, bottom: 0, left: 0, right: 0}; - for (const key in hitSlop) { - debugHitSlopStyle[key] = -hitSlop[key]; - } - const normalizedColor = normalizeColor(color); - if (typeof normalizedColor !== 'number') { - return null; - } - const hexColor = - '#' + ('00000000' + normalizedColor.toString(16)).substr(-8); - return ( - =0.111.0 site=react_native_fb) This comment suppresses - * an error found when Flow v0.111 was deployed. To see the error, - * delete this comment and run Flow. */ - { - borderColor: hexColor.slice(0, -2) + '55', // More opaque - backgroundColor: hexColor.slice(0, -2) + '0F', // Less opaque - ...debugHitSlopStyle, - }, - ]} - /> - ); + return null; }, }; -const styles = StyleSheet.create({ - debug: { - position: 'absolute', - borderWidth: 1, - borderStyle: 'dashed', - }, -}); - module.exports = Touchable; diff --git a/Libraries/Components/Touchable/TouchableBounce.js b/Libraries/Components/Touchable/TouchableBounce.js index 3a89c55d142d1b..49a9a35f078d64 100644 --- a/Libraries/Components/Touchable/TouchableBounce.js +++ b/Libraries/Components/Touchable/TouchableBounce.js @@ -15,7 +15,6 @@ import Pressability, { } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; -import TVTouchable from './TVTouchable'; import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback'; import {Animated, Platform} from 'react-native'; import * as React from 'react'; @@ -38,8 +37,6 @@ type State = $ReadOnly<{| |}>; class TouchableBounce extends React.Component { - _tvTouchable: ?TVTouchable; - state: State = { pressability: new Pressability(this._createPressabilityConfig()), scale: new Animated.Value(1), @@ -72,11 +69,7 @@ class TouchableBounce extends React.Component { this.props.onFocus(event); } }, - onLongPress: event => { - if (this.props.onLongPress != null) { - this.props.onLongPress(event); - } - }, + onLongPress: this.props.onLongPress, onPress: event => { const {onPressAnimationComplete, onPressWithCompletion} = this.props; const releaseBounciness = this.props.releaseBounciness ?? 10; @@ -176,39 +169,11 @@ class TouchableBounce extends React.Component { ); } - componentDidMount(): void { - if (Platform.isTV) { - this._tvTouchable = new TVTouchable(this, { - getDisabled: () => this.props.disabled === true, - onBlur: event => { - if (this.props.onBlur != null) { - this.props.onBlur(event); - } - }, - onFocus: event => { - if (this.props.onFocus != null) { - this.props.onFocus(event); - } - }, - onPress: event => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }, - }); - } - } - componentDidUpdate(prevProps: Props, prevState: State) { this.state.pressability.configure(this._createPressabilityConfig()); } componentWillUnmount(): void { - if (Platform.isTV) { - if (this._tvTouchable != null) { - this._tvTouchable.destroy(); - } - } this.state.pressability.reset(); } } diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index 350ea535e11fc3..d01fb7c595d463 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -16,7 +16,6 @@ import Pressability, { import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; import StyleSheet, {type ViewStyleProp} from '../../StyleSheet/StyleSheet'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; -import TVTouchable from './TVTouchable'; import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback'; import Platform from '../../Utilities/Platform'; import View from '../../Components/View/View'; @@ -158,7 +157,6 @@ type State = $ReadOnly<{| class TouchableHighlight extends React.Component { _hideTimeout: ?TimeoutID; _isMounted: boolean = false; - _tvTouchable: ?TVTouchable; state: State = { pressability: new Pressability(this._createPressabilityConfig()), @@ -193,11 +191,7 @@ class TouchableHighlight extends React.Component { this.props.onFocus(event); } }, - onLongPress: event => { - if (this.props.onLongPress != null) { - this.props.onLongPress(event); - } - }, + onLongPress: this.props.onLongPress, onPress: event => { if (this._hideTimeout != null) { clearTimeout(this._hideTimeout); @@ -339,26 +333,6 @@ class TouchableHighlight extends React.Component { componentDidMount(): void { this._isMounted = true; - if (Platform.isTV) { - this._tvTouchable = new TVTouchable(this, { - getDisabled: () => this.props.disabled === true, - onBlur: event => { - if (this.props.onBlur != null) { - this.props.onBlur(event); - } - }, - onFocus: event => { - if (this.props.onFocus != null) { - this.props.onFocus(event); - } - }, - onPress: event => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }, - }); - } } componentDidUpdate(prevProps: Props, prevState: State) { @@ -370,15 +344,13 @@ class TouchableHighlight extends React.Component { if (this._hideTimeout != null) { clearTimeout(this._hideTimeout); } - if (Platform.isTV) { - if (this._tvTouchable != null) { - this._tvTouchable.destroy(); - } - } this.state.pressability.reset(); } } module.exports = (React.forwardRef((props, hostRef) => ( -)): React.AbstractComponent<$ReadOnly<$Diff>>); +)): React.AbstractComponent< + $ReadOnly<$Diff|}>>, + React.ElementRef, +>); diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.js b/Libraries/Components/Touchable/TouchableNativeFeedback.js index dda6c4bf371093..907f9670537f52 100644 --- a/Libraries/Components/Touchable/TouchableNativeFeedback.js +++ b/Libraries/Components/Touchable/TouchableNativeFeedback.js @@ -14,7 +14,6 @@ import Pressability, { type PressabilityConfig, } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; -import TVTouchable from './TVTouchable'; import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback'; import {Commands} from 'react-native/Libraries/Components/View/ViewNativeComponent'; import ReactNative from 'react-native/Libraries/Renderer/shims/ReactNative'; @@ -164,8 +163,6 @@ class TouchableNativeFeedback extends React.Component { static canUseNativeForeground: () => boolean = () => Platform.OS === 'android' && Platform.Version >= 23; - _tvTouchable: ?TVTouchable; - state: State = { pressability: new Pressability(this._createPressabilityConfig()), }; @@ -301,39 +298,11 @@ class TouchableNativeFeedback extends React.Component { ); } - componentDidMount(): void { - if (Platform.isTV) { - this._tvTouchable = new TVTouchable(this, { - getDisabled: () => this.props.disabled === true, - onBlur: event => { - if (this.props.onBlur != null) { - this.props.onBlur(event); - } - }, - onFocus: event => { - if (this.props.onFocus != null) { - this.props.onFocus(event); - } - }, - onPress: event => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }, - }); - } - } - componentDidUpdate(prevProps: Props, prevState: State) { this.state.pressability.configure(this._createPressabilityConfig()); } componentWillUnmount(): void { - if (Platform.isTV) { - if (this._tvTouchable != null) { - this._tvTouchable.destroy(); - } - } this.state.pressability.reset(); } } diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index f1d09510e03cb8..eb6a3612b284e1 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -14,7 +14,6 @@ import Pressability, { type PressabilityConfig, } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; -import TVTouchable from './TVTouchable'; import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback'; import Animated from 'react-native/Libraries/Animated/Animated'; import Easing from 'react-native/Libraries/Animated/Easing'; @@ -39,7 +38,7 @@ type Props = $ReadOnly<{| activeOpacity?: ?number, style?: ?ViewStyleProp, - hostRef: React.Ref, + hostRef?: ?React.Ref, |}>; type State = $ReadOnly<{| @@ -132,8 +131,6 @@ type State = $ReadOnly<{| * */ class TouchableOpacity extends React.Component { - _tvTouchable: ?TVTouchable; - state: State = { anim: new Animated.Value(this._getChildStyleOpacityWithDefault()), pressability: new Pressability(this._createPressabilityConfig()), @@ -258,29 +255,6 @@ class TouchableOpacity extends React.Component { ); } - componentDidMount(): void { - if (Platform.isTV) { - this._tvTouchable = new TVTouchable(this, { - getDisabled: () => this.props.disabled === true, - onBlur: event => { - if (this.props.onBlur != null) { - this.props.onBlur(event); - } - }, - onFocus: event => { - if (this.props.onFocus != null) { - this.props.onFocus(event); - } - }, - onPress: event => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }, - }); - } - } - componentDidUpdate(prevProps: Props, prevState: State) { this.state.pressability.configure(this._createPressabilityConfig()); if (this.props.disabled !== prevProps.disabled) { @@ -289,15 +263,10 @@ class TouchableOpacity extends React.Component { } componentWillUnmount(): void { - if (Platform.isTV) { - if (this._tvTouchable != null) { - this._tvTouchable.destroy(); - } - } this.state.pressability.reset(); } } -module.exports = (React.forwardRef((props, hostRef) => ( - -)): React.AbstractComponent<$ReadOnly<$Diff>>); +module.exports = (React.forwardRef((props, ref) => ( + +)): React.AbstractComponent>); diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 0cb20d0dbad078..98a2e8ea13403e 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -14,7 +14,6 @@ import Pressability, { type PressabilityConfig, } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; -import TVTouchable from './TVTouchable'; import type { AccessibilityActionEvent, AccessibilityActionInfo, @@ -29,7 +28,6 @@ import type { LayoutEvent, PressEvent, } from '../../Types/CoreEventTypes'; -import Platform from '../../Utilities/Platform'; import View from '../../Components/View/View'; import * as React from 'react'; @@ -94,8 +92,6 @@ const PASSTHROUGH_PROPS = [ ]; class TouchableWithoutFeedback extends React.Component { - _tvTouchable: ?TVTouchable; - state: State = { pressability: new Pressability(createPressabilityConfig(this.props)), }; @@ -134,39 +130,11 @@ class TouchableWithoutFeedback extends React.Component { return React.cloneElement(element, elementProps, ...children); } - componentDidMount(): void { - if (Platform.isTV) { - this._tvTouchable = new TVTouchable(this, { - getDisabled: () => this.props.disabled === true, - onBlur: event => { - if (this.props.onBlur != null) { - this.props.onBlur(event); - } - }, - onFocus: event => { - if (this.props.onFocus != null) { - this.props.onFocus(event); - } - }, - onPress: event => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }, - }); - } - } - componentDidUpdate(): void { this.state.pressability.configure(createPressabilityConfig(this.props)); } componentWillUnmount(): void { - if (Platform.isTV) { - if (this._tvTouchable != null) { - this._tvTouchable.destroy(); - } - } this.state.pressability.reset(); } } diff --git a/Libraries/Components/View/ReactNativeViewViewConfig.js b/Libraries/Components/View/ReactNativeViewViewConfig.js index 4d6f0dd0a6ce10..95cfa81733b6a8 100644 --- a/Libraries/Components/View/ReactNativeViewViewConfig.js +++ b/Libraries/Components/View/ReactNativeViewViewConfig.js @@ -9,15 +9,17 @@ */ 'use strict'; + +import {type ViewConfig} from '../../Renderer/shims/ReactNativeTypes'; import ReactNativeViewViewConfigAndroid from './ReactNativeViewViewConfigAndroid'; import {Platform} from 'react-native'; -const ReactNativeViewConfig = { +const ReactNativeViewConfig: ViewConfig = { uiViewClassName: 'RCTView', baseModuleName: null, Manager: 'ViewManager', - Commands: ({}: {...}), - Constants: ({}: {...}), + Commands: {}, + Constants: {}, bubblingEventTypes: { ...ReactNativeViewViewConfigAndroid.bubblingEventTypes, topBlur: { @@ -171,7 +173,7 @@ const ReactNativeViewConfig = { flexShrink: true, flexWrap: true, height: true, - hitSlop: {diff: (require('../../Utilities/differ/insetsDiffer'): any)}, + hitSlop: {diff: require('../../Utilities/differ/insetsDiffer')}, importantForAccessibility: true, justifyContent: true, left: true, @@ -322,9 +324,10 @@ const ReactNativeViewConfig = { textTransform: true, tintColor: {process: require('../../StyleSheet/processColor')}, top: true, - transform: ((Platform.OS === 'ios' - ? {diff: require('../../Utilities/differ/matricesDiffer')} - : {process: require('../../StyleSheet/processTransform')}): any), + transform: + Platform.OS === 'ios' + ? {diff: require('../../Utilities/differ/matricesDiffer')} + : {process: require('../../StyleSheet/processTransform')}, transformMatrix: true, translateX: true, translateY: true, @@ -334,9 +337,10 @@ const ReactNativeViewConfig = { }, testID: true, top: true, - transform: ((Platform.OS === 'ios' - ? {diff: require('../../Utilities/differ/matricesDiffer')} - : {process: require('../../StyleSheet/processTransform')}): any), + transform: + Platform.OS === 'ios' + ? {diff: require('../../Utilities/differ/matricesDiffer')} + : {process: require('../../StyleSheet/processTransform')}, translateX: true, translateY: true, width: true, diff --git a/Libraries/Components/View/ViewNativeComponent.js b/Libraries/Components/View/ViewNativeComponent.js index 902414c4eb45e3..16970ecda376bc 100644 --- a/Libraries/Components/View/ViewNativeComponent.js +++ b/Libraries/Components/View/ViewNativeComponent.js @@ -4,72 +4,27 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -const Platform = require('../../Utilities/Platform'); -const ReactNativeViewViewConfigAndroid = require('./ReactNativeViewViewConfigAndroid'); - -const registerGeneratedViewConfig = require('../../Utilities/registerGeneratedViewConfig'); -const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); - -import * as React from 'react'; - +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import Platform from '../../Utilities/Platform'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import type {ViewProps} from './ViewPropTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; - -export type ViewNativeComponentType = HostComponent; - -let NativeViewComponent; -let viewConfig: - | {...} - | {| - bubblingEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| - phasedRegistrationNames: $ReadOnly<{| - bubbled: string, - captured: string, - |}>, - |}>, - ..., - }>, - directEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{|registrationName: string|}>, - ..., - }>, - uiViewClassName: string, - validAttributes?: { - [propName: string]: - | true - | $ReadOnly<{| - diff?: (arg1: any, arg2: any) => boolean, - process?: (arg1: any) => any, - |}>, - ..., - }, - |}; - -if (__DEV__ || global.RN$Bridgeless) { - // On Android, View extends the base component with additional view-only props - // On iOS, the base component is View - if (Platform.OS === 'android') { - viewConfig = ReactNativeViewViewConfigAndroid; - registerGeneratedViewConfig('RCTView', ReactNativeViewViewConfigAndroid); - } else { - viewConfig = {}; - registerGeneratedViewConfig('RCTView', {uiViewClassName: 'RCTView'}); - } - - NativeViewComponent = 'RCTView'; -} else { - NativeViewComponent = requireNativeComponent('RCTView'); -} +import ReactNativeViewViewConfigAndroid from './ReactNativeViewViewConfigAndroid'; +import {type ViewProps as Props} from './ViewPropTypes'; +import * as React from 'react'; -export const __INTERNAL_VIEW_CONFIG = viewConfig; +const ViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTView', + () => + Platform.OS === 'android' + ? ReactNativeViewViewConfigAndroid + : {uiViewClassName: 'RCTView'}, +); interface NativeCommands { +hotspotUpdate: ( @@ -87,4 +42,6 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['hotspotUpdate', 'setPressed'], }); -export default ((NativeViewComponent: any): ViewNativeComponentType); +export default ViewNativeComponent; + +export type ViewNativeComponentType = HostComponent; diff --git a/Libraries/Core/Devtools/symbolicateStackTrace.js b/Libraries/Core/Devtools/symbolicateStackTrace.js index 7a6b8cd80ceca7..cfb266c7339cdd 100644 --- a/Libraries/Core/Devtools/symbolicateStackTrace.js +++ b/Libraries/Core/Devtools/symbolicateStackTrace.js @@ -12,14 +12,9 @@ const getDevServer = require('./getDevServer'); -import NativeSourceCode from '../../NativeModules/specs/NativeSourceCode'; - -// Avoid requiring fetch on load of this module; see symbolicateStackTrace -let fetch; - import type {StackFrame} from '../NativeExceptionsManager'; -export type CodeFrame = $ReadOnly<{| +export type CodeFrame = $ReadOnly<{ content: string, location: ?{ row: number, @@ -27,68 +22,26 @@ export type CodeFrame = $ReadOnly<{| ... }, fileName: string, -|}>; +}>; -export type SymbolicatedStackTrace = $ReadOnly<{| +export type SymbolicatedStackTrace = $ReadOnly<{ stack: Array, codeFrame: ?CodeFrame, -|}>; - -function isSourcedFromDisk(sourcePath: string): boolean { - return !/^http/.test(sourcePath) && /[\\/]/.test(sourcePath); -} +}>; async function symbolicateStackTrace( stack: Array, ): Promise { - // RN currently lazy loads whatwg-fetch using a custom fetch module, which, - // when called for the first time, requires and re-exports 'whatwg-fetch'. - // However, when a dependency of the project tries to require whatwg-fetch - // either directly or indirectly, whatwg-fetch is required before - // RN can lazy load whatwg-fetch. As whatwg-fetch checks - // for a fetch polyfill before loading, it will in turn try to load - // RN's fetch module, which immediately tries to import whatwg-fetch AGAIN. - // This causes a circular require which results in RN's fetch module - // exporting fetch as 'undefined'. - // The fix below postpones trying to load fetch until the first call to symbolicateStackTrace. - // At that time, we will have either global.fetch (whatwg-fetch) or RN's fetch. - if (!fetch) { - // flowlint-next-line untyped-import:off - fetch = global.fetch || require('../../Network/fetch').fetch; - } - const devServer = getDevServer(); if (!devServer.bundleLoadedFromServer) { - throw new Error('Bundle was not loaded from the packager'); - } - - let stackCopy = stack; - - const {scriptURL} = NativeSourceCode.getConstants(); - if (scriptURL) { - let foundInternalSource: boolean = false; - stackCopy = stack.map((frame: StackFrame) => { - if (frame.file == null) { - return frame; - } - - // If the sources exist on disk rather than appearing to come from the packager, - // replace the location with the packager URL until we reach an internal source - // which does not have a path (no slashes), indicating a switch from within - // the application to a surrounding debugging environment. - if (!foundInternalSource && isSourcedFromDisk(frame.file)) { - // Copy frame into new object and replace 'file' property - return {...frame, file: scriptURL}; - } - - foundInternalSource = true; - return frame; - }); + throw new Error('Bundle was not loaded from Metro.'); } + // Lazy-load `fetch` until the first symbolication call to avoid circular requires. + const fetch = global.fetch ?? require('../../Network/fetch'); const response = await fetch(devServer.url + 'symbolicate', { method: 'POST', - body: JSON.stringify({stack: stackCopy}), + body: JSON.stringify({stack}), }); return await response.json(); } diff --git a/Libraries/Core/Timers/JSTimers.js b/Libraries/Core/Timers/JSTimers.js index 9c5d2a099e3887..504daa5f446193 100644 --- a/Libraries/Core/Timers/JSTimers.js +++ b/Libraries/Core/Timers/JSTimers.js @@ -11,7 +11,6 @@ 'use strict'; const BatchedBridge = require('../../BatchedBridge/BatchedBridge'); -const Platform = require('../../Utilities/Platform'); const Systrace = require('../../Performance/Systrace'); const invariant = require('invariant'); @@ -36,14 +35,6 @@ export type JSTimerType = const FRAME_DURATION = 1000 / 60; const IDLE_CALLBACK_FRAME_DEADLINE = 1; -const MAX_TIMER_DURATION_MS = 60 * 1000; -const IS_ANDROID = Platform.OS === 'android'; -const ANDROID_LONG_TIMER_MESSAGE = - 'Setting a timer for a long period of time, i.e. multiple minutes, is a ' + - 'performance and correctness issue on Android as it keeps the timer ' + - 'module awake, and timers can only be called when the app is in the foreground. ' + - 'See https://github.com/facebook/react-native/issues/12981 for more info.'; - // Parallel arrays const callbacks: Array = []; const types: Array = []; @@ -218,15 +209,6 @@ const JSTimers = { * @param {number} duration Number of milliseconds. */ setTimeout: function(func: Function, duration: number, ...args: any): number { - if (__DEV__ && IS_ANDROID && duration > MAX_TIMER_DURATION_MS) { - console.warn( - ANDROID_LONG_TIMER_MESSAGE + - '\n' + - '(Saw setTimeout with duration ' + - duration + - 'ms)', - ); - } const id = _allocateCallback( () => func.apply(undefined, args), 'setTimeout', @@ -244,15 +226,6 @@ const JSTimers = { duration: number, ...args: any ): number { - if (__DEV__ && IS_ANDROID && duration > MAX_TIMER_DURATION_MS) { - console.warn( - ANDROID_LONG_TIMER_MESSAGE + - '\n' + - '(Saw setInterval with duration ' + - duration + - 'ms)', - ); - } const id = _allocateCallback( () => func.apply(undefined, args), 'setInterval', diff --git a/Libraries/Core/polyfillPromise.js b/Libraries/Core/polyfillPromise.js index b15ccc2b301d25..6551745bf52c5d 100644 --- a/Libraries/Core/polyfillPromise.js +++ b/Libraries/Core/polyfillPromise.js @@ -19,4 +19,20 @@ const {polyfillGlobal} = require('../Utilities/PolyfillFunctions'); * If you don't need these polyfills, don't use InitializeCore; just directly * require the modules you need from InitializeCore for setup. */ -polyfillGlobal('Promise', () => require('../Promise')); + +// If global.Promise is provided by Hermes, we are confident that it can provide +// all the methods needed by React Native, so we can directly use it. +if (global?.HermesInternal?.hasPromise?.()) { + const HermesPromise = global.Promise; + + if (__DEV__) { + if (typeof HermesPromise !== 'function') { + console.error('HermesPromise does not exist'); + } + global.HermesInternal.enablePromiseRejectionTracker( + require('../promiseRejectionTrackingOptions').default, + ); + } +} else { + polyfillGlobal('Promise', () => require('../Promise')); +} diff --git a/Libraries/Core/setUpReactRefresh.js b/Libraries/Core/setUpReactRefresh.js index 4ee10acf086ffa..ccc67ca22398b5 100644 --- a/Libraries/Core/setUpReactRefresh.js +++ b/Libraries/Core/setUpReactRefresh.js @@ -45,5 +45,7 @@ if (__DEV__) { }, }; - (require: any).Refresh = Refresh; + // The metro require polyfill can not have dependencies (applies for all polyfills). + // Expose `Refresh` by assigning it to global to make it available in the polyfill. + global[(global.__METRO_GLOBAL_PREFIX__ || '') + '__ReactRefresh'] = Refresh; } diff --git a/Libraries/Core/setUpSegmentFetcher.js b/Libraries/Core/setUpSegmentFetcher.js index c31e2cea182ae5..d48810ae22cac5 100644 --- a/Libraries/Core/setUpSegmentFetcher.js +++ b/Libraries/Core/setUpSegmentFetcher.js @@ -20,10 +20,11 @@ export type GetSegmentFunction = typeof __getSegment; function __fetchSegment( segmentId: number, - options: {| - +otaBuildNumber: ?string, - +requestedModuleName?: ?string, - |}, + options: $ReadOnly<{ + otaBuildNumber: ?string, + requestedModuleName: string, + segmentHash: string, + }>, callback: (?Error) => void, ) { const SegmentFetcher = require('./SegmentFetcher/NativeSegmentFetcher') @@ -53,10 +54,11 @@ global.__fetchSegment = __fetchSegment; function __getSegment( segmentId: number, - options: {| - +otaBuildNumber: ?string, - +requestedModuleName?: ?string, - |}, + options: $ReadOnly<{ + otaBuildNumber: ?string, + requestedModuleName: string, + segmentHash: string, + }>, callback: (?Error, ?string) => void, ) { const SegmentFetcher = require('./SegmentFetcher/NativeSegmentFetcher') diff --git a/Libraries/DeprecatedPropTypes/DeprecatedTVViewPropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedTVViewPropTypes.js deleted file mode 100644 index 22628f0e469446..00000000000000 --- a/Libraries/DeprecatedPropTypes/DeprecatedTVViewPropTypes.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -const PropTypes = require('prop-types'); - -const DeprecatedTVViewPropTypes = { - hasTVPreferredFocus: PropTypes.bool, - tvParallaxShiftDistanceX: PropTypes.number, - tvParallaxShiftDistanceY: PropTypes.number, - tvParallaxTiltAngle: PropTypes.number, - tvParallaxMagnification: PropTypes.number, -}; - -module.exports = DeprecatedTVViewPropTypes; diff --git a/Libraries/DeprecatedPropTypes/DeprecatedTextInputPropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedTextInputPropTypes.js index 52a4714d84e914..dca4fe0a475776 100644 --- a/Libraries/DeprecatedPropTypes/DeprecatedTextInputPropTypes.js +++ b/Libraries/DeprecatedPropTypes/DeprecatedTextInputPropTypes.js @@ -466,6 +466,7 @@ module.exports = { * * [Styles](docs/style.html) */ + // $FlowFixMe[incompatible-use] style: Text.propTypes.style, /** * The color of the `TextInput` underline. diff --git a/Libraries/EventEmitter/NativeEventEmitter.js b/Libraries/EventEmitter/NativeEventEmitter.js index e04bc5f95d06c5..328a02300c4d7c 100644 --- a/Libraries/EventEmitter/NativeEventEmitter.js +++ b/Libraries/EventEmitter/NativeEventEmitter.js @@ -12,7 +12,7 @@ import Platform from '../Utilities/Platform'; import EventEmitter from '../vendor/emitter/EventEmitter'; -import {type EventSubscription} from '../vendor/emitter/EventEmitter'; +import type EmitterSubscription from '../vendor/emitter/_EmitterSubscription'; import RCTDeviceEventEmitter from './RCTDeviceEventEmitter'; import invariant from 'invariant'; @@ -22,43 +22,61 @@ type NativeModule = { ... }; +type NativeEventEmitterOptions = $ReadOnly<{| + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: boolean, +|}>; + +const DEFAULT_NATIVE_EVENT_EMITTER_OPTIONS = { + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: false, +}; + /** * Abstract base class for implementing event-emitting modules. This implements * a subset of the standard EventEmitter node module API. */ -export default class NativeEventEmitter extends EventEmitter { +export default class NativeEventEmitter< + EventDefinitions: {...}, +> extends EventEmitter { _nativeModule: ?NativeModule; + _disableCallsIntoModule: boolean; - constructor(nativeModule: ?NativeModule) { + constructor( + nativeModule: ?NativeModule, + options: NativeEventEmitterOptions = DEFAULT_NATIVE_EVENT_EMITTER_OPTIONS, + ) { super(RCTDeviceEventEmitter.sharedSubscriber); + this._disableCallsIntoModule = + options.__SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; if (Platform.OS === 'ios') { invariant(nativeModule, 'Native module cannot be null.'); this._nativeModule = nativeModule; } } - addListener( - eventType: string, - listener: Function, - context: ?Object, - ): EventSubscription { - if (this._nativeModule != null) { + addListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.addListener(eventType); } return super.addListener(eventType, listener, context); } - removeAllListeners(eventType: string) { + removeAllListeners>(eventType: ?K): void { invariant(eventType, 'eventType argument is required.'); const count = this.listenerCount(eventType); - if (this._nativeModule != null) { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.removeListeners(count); } super.removeAllListeners(eventType); } - removeSubscription(subscription: EventSubscription) { - if (this._nativeModule != null) { + removeSubscription>( + subscription: EmitterSubscription, + ): void { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.removeListeners(1); } super.removeSubscription(subscription); diff --git a/Libraries/EventEmitter/RCTDeviceEventEmitter.js b/Libraries/EventEmitter/RCTDeviceEventEmitter.js index 39e456b8096b52..5fe2757a610afd 100644 --- a/Libraries/EventEmitter/RCTDeviceEventEmitter.js +++ b/Libraries/EventEmitter/RCTDeviceEventEmitter.js @@ -44,34 +44,38 @@ function checkNativeEventModule(eventType: ?string) { * Deprecated - subclass NativeEventEmitter to create granular event modules instead of * adding all event listeners directly to RCTDeviceEventEmitter. */ -class RCTDeviceEventEmitter extends EventEmitter { - sharedSubscriber: EventSubscriptionVendor; +class RCTDeviceEventEmitter< + EventDefinitions: {...}, +> extends EventEmitter { + sharedSubscriber: EventSubscriptionVendor; constructor() { - const sharedSubscriber = new EventSubscriptionVendor(); + const sharedSubscriber = new EventSubscriptionVendor(); super(sharedSubscriber); this.sharedSubscriber = sharedSubscriber; } - addListener( - eventType: string, - listener: Function, - context: ?Object, - ): EmitterSubscription { + addListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription { if (__DEV__) { checkNativeEventModule(eventType); } return super.addListener(eventType, listener, context); } - removeAllListeners(eventType: ?string) { + removeAllListeners>(eventType: ?K): void { if (__DEV__) { checkNativeEventModule(eventType); } super.removeAllListeners(eventType); } - removeSubscription(subscription: EmitterSubscription) { + removeSubscription>( + subscription: EmitterSubscription, + ): void { if (subscription.emitter !== this) { subscription.emitter.removeSubscription(subscription); } else { @@ -80,4 +84,7 @@ class RCTDeviceEventEmitter extends EventEmitter { } } -export default (new RCTDeviceEventEmitter(): RCTDeviceEventEmitter); +// FIXME: use typed events +type RCTDeviceEventDefinitions = $FlowFixMe; + +export default (new RCTDeviceEventEmitter(): RCTDeviceEventEmitter); diff --git a/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js b/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js index cf812706d0266f..fc303ff4e1aff2 100644 --- a/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +++ b/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js @@ -16,7 +16,9 @@ import RCTDeviceEventEmitter from '../RCTDeviceEventEmitter'; /** * Mock the NativeEventEmitter as a normal JS EventEmitter. */ -export default class NativeEventEmitter extends EventEmitter { +export default class NativeEventEmitter< + EventDefinitions: {...}, +> extends EventEmitter { constructor() { super(RCTDeviceEventEmitter.sharedSubscriber); } diff --git a/Libraries/FBLazyVector/FBLazyVector.podspec b/Libraries/FBLazyVector/FBLazyVector.podspec index 439c326f9de31f..ec8b554df3476c 100644 --- a/Libraries/FBLazyVector/FBLazyVector.podspec +++ b/Libraries/FBLazyVector/FBLazyVector.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "**/*.{c,h,m,mm,cpp}" s.header_dir = "FBLazyVector" diff --git a/Libraries/FBReactNativeSpec/BUCK b/Libraries/FBReactNativeSpec/BUCK deleted file mode 100644 index 3ab64ac8a7a14a..00000000000000 --- a/Libraries/FBReactNativeSpec/BUCK +++ /dev/null @@ -1,25 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "fb_apple_library", "react_native_xplat_target_apple", "subdir_glob") - -fb_apple_library( - name = "FBReactNativeSpecApple", - srcs = glob(["FBReactNativeSpec/**/*.mm"]), - exported_headers = subdir_glob( - [ - ("FBReactNativeSpec", "*.h"), - ], - prefix = "FBReactNativeSpec", - ), - contacts = ["oncall+react_native@xmail.facebook.com"], - extension_api_only = True, - frameworks = [ - "Foundation", - "UIKit", - ], - labels = ["supermodule:xplat/default/public.react_native.infra"], - reexport_all_header_dependencies = True, - deps = [ - "//xplat/js/react-native-github:RCTTypeSafety", - "//xplat/js/react-native-github/Libraries/RCTRequired:RCTRequired", - react_native_xplat_target_apple("turbomodule/core:core"), - ], -) diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec.podspec b/Libraries/FBReactNativeSpec/FBReactNativeSpec.podspec index bd2a78e45cccbb..0be878326215b2 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec.podspec +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec.podspec @@ -4,6 +4,7 @@ # LICENSE file in the root directory of this source tree. require "json" +require_relative "../../scripts/react_native_pods.rb" package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) version = package['version'] @@ -26,10 +27,11 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "**/*.{c,h,m,mm,cpp}" + s.exclude_files = "jni" s.header_dir = "FBReactNativeSpec" s.pod_target_xcconfig = { @@ -44,4 +46,6 @@ Pod::Spec.new do |s| s.dependency "React-Core", version s.dependency "React-jsi", version s.dependency "ReactCommon/turbomodule/core", version + + use_react_native_codegen! (s) end diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm deleted file mode 100644 index 1f7227f478f872..00000000000000 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm +++ /dev/null @@ -1,2897 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal genrule from Flow types. - * - * We create an umbrella header (and corresponding implementation) here since - * Cxx compilation in BUCK has a limitation: source-code producing genrule()s - * must have a single output. More files => more genrule()s => slower builds. - */ -#import "FBReactNativeSpec.h" - -#import - - -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_isReduceMotionEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "isReduceMotionEnabled", @selector(isReduceMotionEnabled:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_isTouchExplorationEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "isTouchExplorationEnabled", @selector(isTouchExplorationEnabled:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_setAccessibilityFocus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAccessibilityFocus", @selector(setAccessibilityFocus:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_announceForAccessibility(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "announceForAccessibility", @selector(announceForAccessibility:), args, count); - } - - - NativeAccessibilityInfoSpecJSI::NativeAccessibilityInfoSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["isReduceMotionEnabled"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_isReduceMotionEnabled}; - - - methodMap_["isTouchExplorationEnabled"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_isTouchExplorationEnabled}; - - - methodMap_["setAccessibilityFocus"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_setAccessibilityFocus}; - - - methodMap_["announceForAccessibility"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_announceForAccessibility}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAccessibilityManager_SpecSetAccessibilityContentSizeMultipliersJSMultipliers) -+ (RCTManagedPointer *)JS_NativeAccessibilityManager_SpecSetAccessibilityContentSizeMultipliersJSMultipliers:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentBoldTextState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentBoldTextState", @selector(getCurrentBoldTextState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentGrayscaleState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentGrayscaleState", @selector(getCurrentGrayscaleState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentInvertColorsState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentInvertColorsState", @selector(getCurrentInvertColorsState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceMotionState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentReduceMotionState", @selector(getCurrentReduceMotionState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceTransparencyState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentReduceTransparencyState", @selector(getCurrentReduceTransparencyState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentVoiceOverState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentVoiceOverState", @selector(getCurrentVoiceOverState:onError:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityContentSizeMultipliers(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAccessibilityContentSizeMultipliers", @selector(setAccessibilityContentSizeMultipliers:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityFocus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAccessibilityFocus", @selector(setAccessibilityFocus:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_announceForAccessibility(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "announceForAccessibility", @selector(announceForAccessibility:), args, count); - } - - - NativeAccessibilityManagerSpecJSI::NativeAccessibilityManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getCurrentBoldTextState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentBoldTextState}; - - - methodMap_["getCurrentGrayscaleState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentGrayscaleState}; - - - methodMap_["getCurrentInvertColorsState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentInvertColorsState}; - - - methodMap_["getCurrentReduceMotionState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceMotionState}; - - - methodMap_["getCurrentReduceTransparencyState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceTransparencyState}; - - - methodMap_["getCurrentVoiceOverState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentVoiceOverState}; - - - methodMap_["setAccessibilityContentSizeMultipliers"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityContentSizeMultipliers}; - - setMethodArgConversionSelector(@"setAccessibilityContentSizeMultipliers", 0, @"JS_NativeAccessibilityManager_SpecSetAccessibilityContentSizeMultipliersJSMultipliers:"); - - methodMap_["setAccessibilityFocus"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityFocus}; - - - methodMap_["announceForAccessibility"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_announceForAccessibility}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeActionSheetManager_SpecShowActionSheetWithOptionsOptions) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowActionSheetWithOptionsOptions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeActionSheetManager_SpecShowShareActionSheetWithOptionsOptions) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowShareActionSheetWithOptionsOptions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeActionSheetManager_SpecShowShareActionSheetWithOptionsFailureCallbackError) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowShareActionSheetWithOptionsFailureCallbackError:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeActionSheetManagerSpecJSI_showActionSheetWithOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showActionSheetWithOptions", @selector(showActionSheetWithOptions:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeActionSheetManagerSpecJSI_showShareActionSheetWithOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showShareActionSheetWithOptions", @selector(showShareActionSheetWithOptions:failureCallback:successCallback:), args, count); - } - - - NativeActionSheetManagerSpecJSI::NativeActionSheetManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["showActionSheetWithOptions"] = MethodMetadata {2, __hostFunction_NativeActionSheetManagerSpecJSI_showActionSheetWithOptions}; - - setMethodArgConversionSelector(@"showActionSheetWithOptions", 0, @"JS_NativeActionSheetManager_SpecShowActionSheetWithOptionsOptions:"); - - methodMap_["showShareActionSheetWithOptions"] = MethodMetadata {3, __hostFunction_NativeActionSheetManagerSpecJSI_showShareActionSheetWithOptions}; - - setMethodArgConversionSelector(@"showShareActionSheetWithOptions", 0, @"JS_NativeActionSheetManager_SpecShowShareActionSheetWithOptionsOptions:"); - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAlertManager_Args) -+ (RCTManagedPointer *)JS_NativeAlertManager_Args:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAlertManagerSpecJSI_alertWithArgs(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "alertWithArgs", @selector(alertWithArgs:callback:), args, count); - } - - - NativeAlertManagerSpecJSI::NativeAlertManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["alertWithArgs"] = MethodMetadata {2, __hostFunction_NativeAlertManagerSpecJSI_alertWithArgs}; - - setMethodArgConversionSelector(@"alertWithArgs", 0, @"JS_NativeAlertManager_Args:"); - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAnimatedModule_EndResult) -+ (RCTManagedPointer *)JS_NativeAnimatedModule_EndResult:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAnimatedModule_EventMapping) -+ (RCTManagedPointer *)JS_NativeAnimatedModule_EventMapping:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startOperationBatch", @selector(startOperationBatch), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_finishOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "finishOperationBatch", @selector(finishOperationBatch), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_createAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "createAnimatedNode", @selector(createAnimatedNode:config:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getValue", @selector(getValue:saveValueCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startListeningToAnimatedNodeValue", @selector(startListeningToAnimatedNodeValue:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_stopListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "stopListeningToAnimatedNodeValue", @selector(stopListeningToAnimatedNodeValue:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "connectAnimatedNodes", @selector(connectAnimatedNodes:childTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "disconnectAnimatedNodes", @selector(disconnectAnimatedNodes:childTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startAnimatingNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startAnimatingNode", @selector(startAnimatingNode:nodeTag:config:endCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_stopAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "stopAnimation", @selector(stopAnimation:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAnimatedNodeValue", @selector(setAnimatedNodeValue:value:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAnimatedNodeOffset", @selector(setAnimatedNodeOffset:offset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_flattenAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "flattenAnimatedNodeOffset", @selector(flattenAnimatedNodeOffset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_extractAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "extractAnimatedNodeOffset", @selector(extractAnimatedNodeOffset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodeToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "connectAnimatedNodeToView", @selector(connectAnimatedNodeToView:viewTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodeFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "disconnectAnimatedNodeFromView", @selector(disconnectAnimatedNodeFromView:viewTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_restoreDefaultValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "restoreDefaultValues", @selector(restoreDefaultValues:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_dropAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dropAnimatedNode", @selector(dropAnimatedNode:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_addAnimatedEventToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addAnimatedEventToView", @selector(addAnimatedEventToView:eventName:eventMapping:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_removeAnimatedEventFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeAnimatedEventFromView", @selector(removeAnimatedEventFromView:eventName:animatedNodeTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeAnimatedModuleSpecJSI::NativeAnimatedModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["startOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedModuleSpecJSI_startOperationBatch}; - - - methodMap_["finishOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedModuleSpecJSI_finishOperationBatch}; - - - methodMap_["createAnimatedNode"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_createAnimatedNode}; - - - methodMap_["getValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_getValue}; - - - methodMap_["startListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue}; - - - methodMap_["stopListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_stopListeningToAnimatedNodeValue}; - - - methodMap_["connectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodes}; - - - methodMap_["disconnectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodes}; - - - methodMap_["startAnimatingNode"] = MethodMetadata {4, __hostFunction_NativeAnimatedModuleSpecJSI_startAnimatingNode}; - - - methodMap_["stopAnimation"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_stopAnimation}; - - - methodMap_["setAnimatedNodeValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeValue}; - - - methodMap_["setAnimatedNodeOffset"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeOffset}; - - - methodMap_["flattenAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_flattenAnimatedNodeOffset}; - - - methodMap_["extractAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_extractAnimatedNodeOffset}; - - - methodMap_["connectAnimatedNodeToView"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodeToView}; - - - methodMap_["disconnectAnimatedNodeFromView"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodeFromView}; - - - methodMap_["restoreDefaultValues"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_restoreDefaultValues}; - - - methodMap_["dropAnimatedNode"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_dropAnimatedNode}; - - - methodMap_["addAnimatedEventToView"] = MethodMetadata {3, __hostFunction_NativeAnimatedModuleSpecJSI_addAnimatedEventToView}; - - setMethodArgConversionSelector(@"addAnimatedEventToView", 2, @"JS_NativeAnimatedModule_EventMapping:"); - - methodMap_["removeAnimatedEventFromView"] = MethodMetadata {3, __hostFunction_NativeAnimatedModuleSpecJSI_removeAnimatedEventFromView}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAnimatedTurboModule_EndResult) -+ (RCTManagedPointer *)JS_NativeAnimatedTurboModule_EndResult:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAnimatedTurboModule_EventMapping) -+ (RCTManagedPointer *)JS_NativeAnimatedTurboModule_EventMapping:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startOperationBatch", @selector(startOperationBatch), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_finishOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "finishOperationBatch", @selector(finishOperationBatch), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_createAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "createAnimatedNode", @selector(createAnimatedNode:config:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getValue", @selector(getValue:saveValueCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startListeningToAnimatedNodeValue", @selector(startListeningToAnimatedNodeValue:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "stopListeningToAnimatedNodeValue", @selector(stopListeningToAnimatedNodeValue:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "connectAnimatedNodes", @selector(connectAnimatedNodes:childTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "disconnectAnimatedNodes", @selector(disconnectAnimatedNodes:childTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startAnimatingNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startAnimatingNode", @selector(startAnimatingNode:nodeTag:config:endCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "stopAnimation", @selector(stopAnimation:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAnimatedNodeValue", @selector(setAnimatedNodeValue:value:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setAnimatedNodeOffset", @selector(setAnimatedNodeOffset:offset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_flattenAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "flattenAnimatedNodeOffset", @selector(flattenAnimatedNodeOffset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_extractAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "extractAnimatedNodeOffset", @selector(extractAnimatedNodeOffset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodeToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "connectAnimatedNodeToView", @selector(connectAnimatedNodeToView:viewTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodeFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "disconnectAnimatedNodeFromView", @selector(disconnectAnimatedNodeFromView:viewTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_restoreDefaultValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "restoreDefaultValues", @selector(restoreDefaultValues:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_dropAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dropAnimatedNode", @selector(dropAnimatedNode:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_addAnimatedEventToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addAnimatedEventToView", @selector(addAnimatedEventToView:eventName:eventMapping:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeAnimatedEventFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeAnimatedEventFromView", @selector(removeAnimatedEventFromView:eventName:animatedNodeTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeAnimatedTurboModuleSpecJSI::NativeAnimatedTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["startOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startOperationBatch}; - - - methodMap_["finishOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedTurboModuleSpecJSI_finishOperationBatch}; - - - methodMap_["createAnimatedNode"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_createAnimatedNode}; - - - methodMap_["getValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_getValue}; - - - methodMap_["startListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startListeningToAnimatedNodeValue}; - - - methodMap_["stopListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopListeningToAnimatedNodeValue}; - - - methodMap_["connectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodes}; - - - methodMap_["disconnectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodes}; - - - methodMap_["startAnimatingNode"] = MethodMetadata {4, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startAnimatingNode}; - - - methodMap_["stopAnimation"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopAnimation}; - - - methodMap_["setAnimatedNodeValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeValue}; - - - methodMap_["setAnimatedNodeOffset"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeOffset}; - - - methodMap_["flattenAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_flattenAnimatedNodeOffset}; - - - methodMap_["extractAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_extractAnimatedNodeOffset}; - - - methodMap_["connectAnimatedNodeToView"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodeToView}; - - - methodMap_["disconnectAnimatedNodeFromView"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodeFromView}; - - - methodMap_["restoreDefaultValues"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_restoreDefaultValues}; - - - methodMap_["dropAnimatedNode"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_dropAnimatedNode}; - - - methodMap_["addAnimatedEventToView"] = MethodMetadata {3, __hostFunction_NativeAnimatedTurboModuleSpecJSI_addAnimatedEventToView}; - - setMethodArgConversionSelector(@"addAnimatedEventToView", 2, @"JS_NativeAnimatedTurboModule_EventMapping:"); - - methodMap_["removeAnimatedEventFromView"] = MethodMetadata {3, __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeAnimatedEventFromView}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimationsDebugModuleSpecJSI_startRecordingFps(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startRecordingFps", @selector(startRecordingFps), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimationsDebugModuleSpecJSI_stopRecordingFps(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "stopRecordingFps", @selector(stopRecordingFps:), args, count); - } - - - NativeAnimationsDebugModuleSpecJSI::NativeAnimationsDebugModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["startRecordingFps"] = MethodMetadata {0, __hostFunction_NativeAnimationsDebugModuleSpecJSI_startRecordingFps}; - - - methodMap_["stopRecordingFps"] = MethodMetadata {1, __hostFunction_NativeAnimationsDebugModuleSpecJSI_stopRecordingFps}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAppState_SpecGetCurrentAppStateSuccessAppState) -+ (RCTManagedPointer *)JS_NativeAppState_SpecGetCurrentAppStateSuccessAppState:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_getCurrentAppState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getCurrentAppState", @selector(getCurrentAppState:error:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeAppStateSpecJSI::NativeAppStateSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getCurrentAppState"] = MethodMetadata {2, __hostFunction_NativeAppStateSpecJSI_getCurrentAppState}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppStateSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppStateSpecJSI_removeListeners}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeAppStateSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_getColorScheme(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, StringKind, "getColorScheme", @selector(getColorScheme), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeAppearanceSpecJSI::NativeAppearanceSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getColorScheme"] = MethodMetadata {0, __hostFunction_NativeAppearanceSpecJSI_getColorScheme}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppearanceSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppearanceSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeAppearance_AppearancePreferences) -+ (RCTManagedPointer *)JS_NativeAppearance_AppearancePreferences:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -folly::Optional NSStringToNativeAppearanceColorSchemeName(NSString *value) { - static NSDictionary *dict = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dict = @{ - @"light": @0, - @"dark": @1, - }; - }); - return value ? (NativeAppearanceColorSchemeName)[dict[value] integerValue] : folly::Optional{}; -} - -NSString *NativeAppearanceColorSchemeNameToNSString(folly::Optional value) { - static NSDictionary *dict = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dict = @{ - @0: @"light", - @1: @"dark", - }; - }); - return value.hasValue() ? dict[@(value.value())] : nil; -} -@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiGetCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiGetCallbackErrorsElement:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiSetCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiSetCallbackErrorsElement:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAsyncStorage_SpecClearCallbackError) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecClearCallbackError:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeAsyncStorage_SpecGetAllKeysCallbackError) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecGetAllKeysCallbackError:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiGet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiGet", @selector(multiGet:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiSet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiSet", @selector(multiSet:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiMerge(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiMerge", @selector(multiMerge:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiRemove(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "multiRemove", @selector(multiRemove:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_clear(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clear", @selector(clear:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getAllKeys", @selector(getAllKeys:), args, count); - } - - - NativeAsyncStorageSpecJSI::NativeAsyncStorageSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["multiGet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiGet}; - - - methodMap_["multiSet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiSet}; - - - methodMap_["multiMerge"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiMerge}; - - - methodMap_["multiRemove"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiRemove}; - - - methodMap_["clear"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_clear}; - - - methodMap_["getAllKeys"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_addNetworkingHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addNetworkingHandler", @selector(addNetworkingHandler), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_addWebSocketHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addWebSocketHandler", @selector(addWebSocketHandler:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_removeWebSocketHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeWebSocketHandler", @selector(removeWebSocketHandler:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_sendOverSocket(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "sendOverSocket", @selector(sendOverSocket:socketID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_createFromParts(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "createFromParts", @selector(createFromParts:withId:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_release(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "release", @selector(release:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeBlobModuleSpecJSI::NativeBlobModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["addNetworkingHandler"] = MethodMetadata {0, __hostFunction_NativeBlobModuleSpecJSI_addNetworkingHandler}; - - - methodMap_["addWebSocketHandler"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_addWebSocketHandler}; - - - methodMap_["removeWebSocketHandler"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_removeWebSocketHandler}; - - - methodMap_["sendOverSocket"] = MethodMetadata {2, __hostFunction_NativeBlobModuleSpecJSI_sendOverSocket}; - - - methodMap_["createFromParts"] = MethodMetadata {2, __hostFunction_NativeBlobModuleSpecJSI_createFromParts}; - - - methodMap_["release"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_release}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeBlobModuleSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_startReportAProblemFlow(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "startReportAProblemFlow", @selector(startReportAProblemFlow), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_setExtraData(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setExtraData", @selector(setExtraData:extraFiles:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_setCategoryID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setCategoryID", @selector(setCategoryID:), args, count); - } - - - NativeBugReportingSpecJSI::NativeBugReportingSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["startReportAProblemFlow"] = MethodMetadata {0, __hostFunction_NativeBugReportingSpecJSI_startReportAProblemFlow}; - - - methodMap_["setExtraData"] = MethodMetadata {2, __hostFunction_NativeBugReportingSpecJSI_setExtraData}; - - - methodMap_["setCategoryID"] = MethodMetadata {1, __hostFunction_NativeBugReportingSpecJSI_setCategoryID}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeClipboardSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getString", @selector(getString:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeClipboardSpecJSI_setString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setString", @selector(setString:), args, count); - } - - - NativeClipboardSpecJSI::NativeClipboardSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getString"] = MethodMetadata {0, __hostFunction_NativeClipboardSpecJSI_getString}; - - - methodMap_["setString"] = MethodMetadata {1, __hostFunction_NativeClipboardSpecJSI_setString}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDatePickerAndroidSpecJSI_open(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "open", @selector(open:resolve:reject:), args, count); - } - - - NativeDatePickerAndroidSpecJSI::NativeDatePickerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["open"] = MethodMetadata {1, __hostFunction_NativeDatePickerAndroidSpecJSI_open}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevLoadingViewSpecJSI_showMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showMessage", @selector(showMessage:withColor:withBackgroundColor:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevLoadingViewSpecJSI_hide(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "hide", @selector(hide), args, count); - } - - - NativeDevLoadingViewSpecJSI::NativeDevLoadingViewSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["showMessage"] = MethodMetadata {3, __hostFunction_NativeDevLoadingViewSpecJSI_showMessage}; - - - methodMap_["hide"] = MethodMetadata {0, __hostFunction_NativeDevLoadingViewSpecJSI_hide}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "show", @selector(show), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_reload(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reload", @selector(reload), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_debugRemotely(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "debugRemotely", @selector(debugRemotely:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_setProfilingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setProfilingEnabled", @selector(setProfilingEnabled:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_setHotLoadingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setHotLoadingEnabled", @selector(setHotLoadingEnabled:), args, count); - } - - - NativeDevMenuSpecJSI::NativeDevMenuSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["show"] = MethodMetadata {0, __hostFunction_NativeDevMenuSpecJSI_show}; - - - methodMap_["reload"] = MethodMetadata {0, __hostFunction_NativeDevMenuSpecJSI_reload}; - - - methodMap_["debugRemotely"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_debugRemotely}; - - - methodMap_["setProfilingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_setProfilingEnabled}; - - - methodMap_["setHotLoadingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_setHotLoadingEnabled}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_reload(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reload", @selector(reload), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_reloadWithReason(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reloadWithReason", @selector(reloadWithReason:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_onFastRefresh(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "onFastRefresh", @selector(onFastRefresh), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setHotLoadingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setHotLoadingEnabled", @selector(setHotLoadingEnabled:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setIsDebuggingRemotely(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setIsDebuggingRemotely", @selector(setIsDebuggingRemotely:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setProfilingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setProfilingEnabled", @selector(setProfilingEnabled:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_toggleElementInspector(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "toggleElementInspector", @selector(toggleElementInspector), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_addMenuItem(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addMenuItem", @selector(addMenuItem:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setIsShakeToShowDevMenuEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setIsShakeToShowDevMenuEnabled", @selector(setIsShakeToShowDevMenuEnabled:), args, count); - } - - - NativeDevSettingsSpecJSI::NativeDevSettingsSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["reload"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_reload}; - - - methodMap_["reloadWithReason"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_reloadWithReason}; - - - methodMap_["onFastRefresh"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_onFastRefresh}; - - - methodMap_["setHotLoadingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setHotLoadingEnabled}; - - - methodMap_["setIsDebuggingRemotely"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setIsDebuggingRemotely}; - - - methodMap_["setProfilingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setProfilingEnabled}; - - - methodMap_["toggleElementInspector"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_toggleElementInspector}; - - - methodMap_["addMenuItem"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_addMenuItem}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_removeListeners}; - - - methodMap_["setIsShakeToShowDevMenuEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setIsShakeToShowDevMenuEnabled}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevSplitBundleLoaderSpecJSI_loadBundle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "loadBundle", @selector(loadBundle:resolve:reject:), args, count); - } - - - NativeDevSplitBundleLoaderSpecJSI::NativeDevSplitBundleLoaderSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["loadBundle"] = MethodMetadata {1, __hostFunction_NativeDevSplitBundleLoaderSpecJSI_loadBundle}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDeviceEventManagerSpecJSI_invokeDefaultBackPressHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "invokeDefaultBackPressHandler", @selector(invokeDefaultBackPressHandler), args, count); - } - - - NativeDeviceEventManagerSpecJSI::NativeDeviceEventManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["invokeDefaultBackPressHandler"] = MethodMetadata {0, __hostFunction_NativeDeviceEventManagerSpecJSI_invokeDefaultBackPressHandler}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDeviceInfoSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeDeviceInfoSpecJSI::NativeDeviceInfoSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDeviceInfoSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeDialogManagerAndroid_DialogOptions) -+ (RCTManagedPointer *)JS_NativeDialogManagerAndroid_DialogOptions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDialogManagerAndroidSpecJSI_showAlert(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showAlert", @selector(showAlert:onError:onAction:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDialogManagerAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeDialogManagerAndroidSpecJSI::NativeDialogManagerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["showAlert"] = MethodMetadata {3, __hostFunction_NativeDialogManagerAndroidSpecJSI_showAlert}; - - setMethodArgConversionSelector(@"showAlert", 0, @"JS_NativeDialogManagerAndroid_DialogOptions:"); - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDialogManagerAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeExceptionsManager_StackFrame) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeExceptionsManager_ExceptionData) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reportFatalException", @selector(reportFatalException:stack:exceptionId:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reportSoftException", @selector(reportSoftException:stack:exceptionId:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "reportException", @selector(reportException:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "updateExceptionMessage", @selector(updateExceptionMessage:stack:exceptionId:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dismissRedbox", @selector(dismissRedbox), args, count); - } - - - NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["reportFatalException"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; - - - methodMap_["reportSoftException"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; - - - methodMap_["reportException"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; - - setMethodArgConversionSelector(@"reportException", 0, @"JS_NativeExceptionsManager_ExceptionData:"); - - methodMap_["updateExceptionMessage"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; - - - methodMap_["dismissRedbox"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeFileReaderModuleSpecJSI_readAsDataURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "readAsDataURL", @selector(readAsDataURL:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFileReaderModuleSpecJSI_readAsText(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "readAsText", @selector(readAsText:encoding:resolve:reject:), args, count); - } - - - NativeFileReaderModuleSpecJSI::NativeFileReaderModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["readAsDataURL"] = MethodMetadata {1, __hostFunction_NativeFileReaderModuleSpecJSI_readAsDataURL}; - - - methodMap_["readAsText"] = MethodMetadata {2, __hostFunction_NativeFileReaderModuleSpecJSI_readAsText}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeFrameRateLogger_SpecSetGlobalOptionsOptions) -+ (RCTManagedPointer *)JS_NativeFrameRateLogger_SpecSetGlobalOptionsOptions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_setGlobalOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setGlobalOptions", @selector(setGlobalOptions:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_setContext(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setContext", @selector(setContext:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_beginScroll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "beginScroll", @selector(beginScroll), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_endScroll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "endScroll", @selector(endScroll), args, count); - } - - - NativeFrameRateLoggerSpecJSI::NativeFrameRateLoggerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["setGlobalOptions"] = MethodMetadata {1, __hostFunction_NativeFrameRateLoggerSpecJSI_setGlobalOptions}; - - setMethodArgConversionSelector(@"setGlobalOptions", 0, @"JS_NativeFrameRateLogger_SpecSetGlobalOptionsOptions:"); - - methodMap_["setContext"] = MethodMetadata {1, __hostFunction_NativeFrameRateLoggerSpecJSI_setContext}; - - - methodMap_["beginScroll"] = MethodMetadata {0, __hostFunction_NativeFrameRateLoggerSpecJSI_beginScroll}; - - - methodMap_["endScroll"] = MethodMetadata {0, __hostFunction_NativeFrameRateLoggerSpecJSI_endScroll}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskFinished(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "notifyTaskFinished", @selector(notifyTaskFinished:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskRetry(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "notifyTaskRetry", @selector(notifyTaskRetry:resolve:reject:), args, count); - } - - - NativeHeadlessJsTaskSupportSpecJSI::NativeHeadlessJsTaskSupportSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["notifyTaskFinished"] = MethodMetadata {1, __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskFinished}; - - - methodMap_["notifyTaskRetry"] = MethodMetadata {1, __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskRetry}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_allowRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "allowRTL", @selector(allowRTL:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_forceRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "forceRTL", @selector(forceRTL:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_swapLeftAndRightInRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "swapLeftAndRightInRTL", @selector(swapLeftAndRightInRTL:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeI18nManagerSpecJSI::NativeI18nManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["allowRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_allowRTL}; - - - methodMap_["forceRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_forceRTL}; - - - methodMap_["swapLeftAndRightInRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_swapLeftAndRightInRTL}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeI18nManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeImageEditor_OptionsOffset) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsOffset:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeImageEditor_OptionsSize) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsSize:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeImageEditor_OptionsDisplaySize) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsDisplaySize:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeImageEditor_Options) -+ (RCTManagedPointer *)JS_NativeImageEditor_Options:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageEditorSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "cropImage", @selector(cropImage:cropData:successCallback:errorCallback:), args, count); - } - - - NativeImageEditorSpecJSI::NativeImageEditorSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["cropImage"] = MethodMetadata {4, __hostFunction_NativeImageEditorSpecJSI_cropImage}; - - setMethodArgConversionSelector(@"cropImage", 1, @"JS_NativeImageEditor_Options:"); - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "abortRequest", @selector(abortRequest:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_getSize(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getSize", @selector(getSize:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_getSizeWithHeaders(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getSizeWithHeaders", @selector(getSizeWithHeaders:headers:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_prefetchImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "prefetchImage", @selector(prefetchImage:requestId:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_queryCache(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "queryCache", @selector(queryCache:resolve:reject:), args, count); - } - - - NativeImageLoaderAndroidSpecJSI::NativeImageLoaderAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_abortRequest}; - - - methodMap_["getSize"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_getSize}; - - - methodMap_["getSizeWithHeaders"] = MethodMetadata {2, __hostFunction_NativeImageLoaderAndroidSpecJSI_getSizeWithHeaders}; - - - methodMap_["prefetchImage"] = MethodMetadata {2, __hostFunction_NativeImageLoaderAndroidSpecJSI_prefetchImage}; - - - methodMap_["queryCache"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_queryCache}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_getSize(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getSize", @selector(getSize:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_getSizeWithHeaders(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getSizeWithHeaders", @selector(getSizeWithHeaders:headers:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_prefetchImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "prefetchImage", @selector(prefetchImage:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_queryCache(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "queryCache", @selector(queryCache:resolve:reject:), args, count); - } - - - NativeImageLoaderIOSSpecJSI::NativeImageLoaderIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getSize"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_getSize}; - - - methodMap_["getSizeWithHeaders"] = MethodMetadata {2, __hostFunction_NativeImageLoaderIOSSpecJSI_getSizeWithHeaders}; - - - methodMap_["prefetchImage"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_prefetchImage}; - - - methodMap_["queryCache"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_queryCache}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenSelectDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenSelectDialogConfig:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_canRecordVideos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "canRecordVideos", @selector(canRecordVideos:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_canUseCamera(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "canUseCamera", @selector(canUseCamera:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "openCameraDialog", @selector(openCameraDialog:successCallback:cancelCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openSelectDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "openSelectDialog", @selector(openSelectDialog:successCallback:cancelCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_clearAllPendingVideos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clearAllPendingVideos", @selector(clearAllPendingVideos), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_removePendingVideo(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removePendingVideo", @selector(removePendingVideo:), args, count); - } - - - NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["canRecordVideos"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_canRecordVideos}; - - - methodMap_["canUseCamera"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_canUseCamera}; - - - methodMap_["openCameraDialog"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; - - setMethodArgConversionSelector(@"openCameraDialog", 0, @"JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:"); - - methodMap_["openSelectDialog"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openSelectDialog}; - - setMethodArgConversionSelector(@"openSelectDialog", 0, @"JS_NativeImagePickerIOS_SpecOpenSelectDialogConfig:"); - - methodMap_["clearAllPendingVideos"] = MethodMetadata {0, __hostFunction_NativeImagePickerIOSSpecJSI_clearAllPendingVideos}; - - - methodMap_["removePendingVideo"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_removePendingVideo}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError) -+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getBase64ForTag", @selector(getBase64ForTag:successCallback:errorCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "hasImageForTag", @selector(hasImageForTag:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeImageForTag", @selector(removeImageForTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addImageFromBase64", @selector(addImageFromBase64:successCallback:errorCallback:), args, count); - } - - - NativeImageStoreSpecJSI::NativeImageStoreSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag}; - - - methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreSpecJSI_hasImageForTag}; - - - methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreSpecJSI_removeImageForTag}; - - - methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSCHeapCaptureSpecJSI_captureComplete(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "captureComplete", @selector(captureComplete:error:), args, count); - } - - - NativeJSCHeapCaptureSpecJSI::NativeJSCHeapCaptureSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["captureComplete"] = MethodMetadata {2, __hostFunction_NativeJSCHeapCaptureSpecJSI_captureComplete}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSCSamplingProfilerSpecJSI_operationComplete(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "operationComplete", @selector(operationComplete:result:error:), args, count); - } - - - NativeJSCSamplingProfilerSpecJSI::NativeJSCSamplingProfilerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["operationComplete"] = MethodMetadata {3, __hostFunction_NativeJSCSamplingProfilerSpecJSI_operationComplete}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_onSuccess(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "onSuccess", @selector(onSuccess:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_onFailure(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "onFailure", @selector(onFailure:error:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeJSDevSupportSpecJSI::NativeJSDevSupportSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["onSuccess"] = MethodMetadata {1, __hostFunction_NativeJSDevSupportSpecJSI_onSuccess}; - - - methodMap_["onFailure"] = MethodMetadata {2, __hostFunction_NativeJSDevSupportSpecJSI_onFailure}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeJSDevSupportSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeKeyboardObserverSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeKeyboardObserverSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeKeyboardObserverSpecJSI::NativeKeyboardObserverSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeKeyboardObserverSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeKeyboardObserverSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeLinking_SpecSendIntentExtrasElement) -+ (RCTManagedPointer *)JS_NativeLinking_SpecSendIntentExtrasElement:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_getInitialURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getInitialURL", @selector(getInitialURL:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_canOpenURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "canOpenURL", @selector(canOpenURL:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_openURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "openURL", @selector(openURL:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_openSettings(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "openSettings", @selector(openSettings:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_sendIntent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "sendIntent", @selector(sendIntent:extras:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeLinkingSpecJSI::NativeLinkingSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getInitialURL"] = MethodMetadata {0, __hostFunction_NativeLinkingSpecJSI_getInitialURL}; - - - methodMap_["canOpenURL"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_canOpenURL}; - - - methodMap_["openURL"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_openURL}; - - - methodMap_["openSettings"] = MethodMetadata {0, __hostFunction_NativeLinkingSpecJSI_openSettings}; - - - methodMap_["sendIntent"] = MethodMetadata {2, __hostFunction_NativeLinkingSpecJSI_sendIntent}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "show", @selector(show), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_hide(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "hide", @selector(hide), args, count); - } - - - NativeLogBoxSpecJSI::NativeLogBoxSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["show"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_show}; - - - methodMap_["hide"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_hide}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeModalManagerSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeModalManagerSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeModalManagerSpecJSI::NativeModalManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeModalManagerSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeModalManagerSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_sendRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "sendRequest", @selector(sendRequest:url:requestId:headers:data:responseType:useIncrementalUpdates:timeout:withCredentials:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "abortRequest", @selector(abortRequest:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_clearCookies(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clearCookies", @selector(clearCookies:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeNetworkingAndroidSpecJSI::NativeNetworkingAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["sendRequest"] = MethodMetadata {9, __hostFunction_NativeNetworkingAndroidSpecJSI_sendRequest}; - - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_abortRequest}; - - - methodMap_["clearCookies"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_clearCookies}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeNetworkingIOS_SpecSendRequestQuery) -+ (RCTManagedPointer *)JS_NativeNetworkingIOS_SpecSendRequestQuery:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_sendRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "sendRequest", @selector(sendRequest:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "abortRequest", @selector(abortRequest:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_clearCookies(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clearCookies", @selector(clearCookies:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeNetworkingIOSSpecJSI::NativeNetworkingIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["sendRequest"] = MethodMetadata {2, __hostFunction_NativeNetworkingIOSSpecJSI_sendRequest}; - - setMethodArgConversionSelector(@"sendRequest", 0, @"JS_NativeNetworkingIOS_SpecSendRequestQuery:"); - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_abortRequest}; - - - methodMap_["clearCookies"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_clearCookies}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_checkPermission(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "checkPermission", @selector(checkPermission:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_requestPermission(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "requestPermission", @selector(requestPermission:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_shouldShowRequestPermissionRationale(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "shouldShowRequestPermissionRationale", @selector(shouldShowRequestPermissionRationale:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_requestMultiplePermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "requestMultiplePermissions", @selector(requestMultiplePermissions:resolve:reject:), args, count); - } - - - NativePermissionsAndroidSpecJSI::NativePermissionsAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["checkPermission"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_checkPermission}; - - - methodMap_["requestPermission"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_requestPermission}; - - - methodMap_["shouldShowRequestPermissionRationale"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_shouldShowRequestPermissionRationale}; - - - methodMap_["requestMultiplePermissions"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_requestMultiplePermissions}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsAndroidSpecJSI_getAndroidID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, StringKind, "getAndroidID", @selector(getAndroidID), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativePlatformConstantsAndroidSpecJSI::NativePlatformConstantsAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getAndroidID"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsAndroidSpecJSI_getAndroidID}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsIOSSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativePlatformConstantsIOSSpecJSI::NativePlatformConstantsIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsIOSSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativePushNotificationManagerIOS_SpecRequestPermissionsPermission) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_SpecRequestPermissionsPermission:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativePushNotificationManagerIOS_Permissions) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_Permissions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -@implementation RCTCxxConvert (NativePushNotificationManagerIOS_Notification) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_Notification:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_onFinishRemoteNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "onFinishRemoteNotification", @selector(onFinishRemoteNotification:fetchResult:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_setApplicationIconBadgeNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setApplicationIconBadgeNumber", @selector(setApplicationIconBadgeNumber:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getApplicationIconBadgeNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getApplicationIconBadgeNumber", @selector(getApplicationIconBadgeNumber:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_requestPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "requestPermissions", @selector(requestPermissions:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_abandonPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "abandonPermissions", @selector(abandonPermissions), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_checkPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "checkPermissions", @selector(checkPermissions:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_presentLocalNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "presentLocalNotification", @selector(presentLocalNotification:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_scheduleLocalNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "scheduleLocalNotification", @selector(scheduleLocalNotification:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelAllLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "cancelAllLocalNotifications", @selector(cancelAllLocalNotifications), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "cancelLocalNotifications", @selector(cancelLocalNotifications:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getInitialNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "getInitialNotification", @selector(getInitialNotification:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getScheduledLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getScheduledLocalNotifications", @selector(getScheduledLocalNotifications:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeAllDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeAllDeliveredNotifications", @selector(removeAllDeliveredNotifications), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeDeliveredNotifications", @selector(removeDeliveredNotifications:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getDeliveredNotifications", @selector(getDeliveredNotifications:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativePushNotificationManagerIOSSpecJSI::NativePushNotificationManagerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["onFinishRemoteNotification"] = MethodMetadata {2, __hostFunction_NativePushNotificationManagerIOSSpecJSI_onFinishRemoteNotification}; - - - methodMap_["setApplicationIconBadgeNumber"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_setApplicationIconBadgeNumber}; - - - methodMap_["getApplicationIconBadgeNumber"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getApplicationIconBadgeNumber}; - - - methodMap_["requestPermissions"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_requestPermissions}; - - setMethodArgConversionSelector(@"requestPermissions", 0, @"JS_NativePushNotificationManagerIOS_SpecRequestPermissionsPermission:"); - - methodMap_["abandonPermissions"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_abandonPermissions}; - - - methodMap_["checkPermissions"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_checkPermissions}; - - - methodMap_["presentLocalNotification"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_presentLocalNotification}; - - setMethodArgConversionSelector(@"presentLocalNotification", 0, @"JS_NativePushNotificationManagerIOS_Notification:"); - - methodMap_["scheduleLocalNotification"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_scheduleLocalNotification}; - - setMethodArgConversionSelector(@"scheduleLocalNotification", 0, @"JS_NativePushNotificationManagerIOS_Notification:"); - - methodMap_["cancelAllLocalNotifications"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelAllLocalNotifications}; - - - methodMap_["cancelLocalNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelLocalNotifications}; - - - methodMap_["getInitialNotification"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getInitialNotification}; - - - methodMap_["getScheduledLocalNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getScheduledLocalNotifications}; - - - methodMap_["removeAllDeliveredNotifications"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeAllDeliveredNotifications}; - - - methodMap_["removeDeliveredNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeDeliveredNotifications}; - - - methodMap_["getDeliveredNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getDeliveredNotifications}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeRedBoxSpecJSI_setExtraData(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setExtraData", @selector(setExtraData:forIdentifier:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeRedBoxSpecJSI_dismiss(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dismiss", @selector(dismiss), args, count); - } - - - NativeRedBoxSpecJSI::NativeRedBoxSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["setExtraData"] = MethodMetadata {2, __hostFunction_NativeRedBoxSpecJSI_setExtraData}; - - - methodMap_["dismiss"] = MethodMetadata {0, __hostFunction_NativeRedBoxSpecJSI_dismiss}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSegmentFetcherSpecJSI_fetchSegment(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "fetchSegment", @selector(fetchSegment:options:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSegmentFetcherSpecJSI_getSegment(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getSegment", @selector(getSegment:options:callback:), args, count); - } - - - NativeSegmentFetcherSpecJSI::NativeSegmentFetcherSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["fetchSegment"] = MethodMetadata {3, __hostFunction_NativeSegmentFetcherSpecJSI_fetchSegment}; - - - methodMap_["getSegment"] = MethodMetadata {3, __hostFunction_NativeSegmentFetcherSpecJSI_getSegment}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_setValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setValues", @selector(setValues:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_deleteValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "deleteValues", @selector(deleteValues:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeSettingsManagerSpecJSI::NativeSettingsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["setValues"] = MethodMetadata {1, __hostFunction_NativeSettingsManagerSpecJSI_setValues}; - - - methodMap_["deleteValues"] = MethodMetadata {1, __hostFunction_NativeSettingsManagerSpecJSI_deleteValues}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeSettingsManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeShareModule_SpecShareContent) -+ (RCTManagedPointer *)JS_NativeShareModule_SpecShareContent:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeShareModuleSpecJSI_share(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, "share", @selector(share:dialogTitle:resolve:reject:), args, count); - } - - - NativeShareModuleSpecJSI::NativeShareModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["share"] = MethodMetadata {2, __hostFunction_NativeShareModuleSpecJSI_share}; - - setMethodArgConversionSelector(@"share", 0, @"JS_NativeShareModule_SpecShareContent:"); - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSoundManagerSpecJSI_playTouchSound(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "playTouchSound", @selector(playTouchSound), args, count); - } - - - NativeSoundManagerSpecJSI::NativeSoundManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["playTouchSound"] = MethodMetadata {0, __hostFunction_NativeSoundManagerSpecJSI_playTouchSound}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSourceCodeSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeSourceCodeSpecJSI::NativeSourceCodeSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeSourceCodeSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setColor(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setColor", @selector(setColor:animated:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setTranslucent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setTranslucent", @selector(setTranslucent:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setStyle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setStyle", @selector(setStyle:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setHidden(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setHidden", @selector(setHidden:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeStatusBarManagerAndroidSpecJSI::NativeStatusBarManagerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["setColor"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setColor}; - - - methodMap_["setTranslucent"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setTranslucent}; - - - methodMap_["setStyle"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setStyle}; - - - methodMap_["setHidden"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setHidden}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeStatusBarManagerIOS_SpecGetHeightCallbackResult) -+ (RCTManagedPointer *)JS_NativeStatusBarManagerIOS_SpecGetHeightCallbackResult:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_getHeight(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getHeight", @selector(getHeight:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setNetworkActivityIndicatorVisible(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setNetworkActivityIndicatorVisible", @selector(setNetworkActivityIndicatorVisible:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setStyle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setStyle", @selector(setStyle:animated:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setHidden(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setHidden", @selector(setHidden:withAnimation:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeStatusBarManagerIOSSpecJSI::NativeStatusBarManagerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getHeight"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_getHeight}; - - - methodMap_["setNetworkActivityIndicatorVisible"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setNetworkActivityIndicatorVisible}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_removeListeners}; - - - methodMap_["setStyle"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setStyle}; - - - methodMap_["setHidden"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setHidden}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeStatusBarManagerIOSSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeTVNavigationEventEmitterSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTVNavigationEventEmitterSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeTVNavigationEventEmitterSpecJSI::NativeTVNavigationEventEmitterSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeTVNavigationEventEmitterSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeTVNavigationEventEmitterSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_createTimer(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "createTimer", @selector(createTimer:duration:jsSchedulingTime:repeats:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_deleteTimer(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "deleteTimer", @selector(deleteTimer:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_setSendIdleEvents(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setSendIdleEvents", @selector(setSendIdleEvents:), args, count); - } - - - NativeTimingSpecJSI::NativeTimingSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["createTimer"] = MethodMetadata {4, __hostFunction_NativeTimingSpecJSI_createTimer}; - - - methodMap_["deleteTimer"] = MethodMetadata {1, __hostFunction_NativeTimingSpecJSI_deleteTimer}; - - - methodMap_["setSendIdleEvents"] = MethodMetadata {1, __hostFunction_NativeTimingSpecJSI_setSendIdleEvents}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "show", @selector(show:duration:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_showWithGravity(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showWithGravity", @selector(showWithGravity:duration:gravity:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_showWithGravityAndOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showWithGravityAndOffset", @selector(showWithGravityAndOffset:duration:gravity:xOffset:yOffset:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeToastAndroidSpecJSI::NativeToastAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["show"] = MethodMetadata {2, __hostFunction_NativeToastAndroidSpecJSI_show}; - - - methodMap_["showWithGravity"] = MethodMetadata {3, __hostFunction_NativeToastAndroidSpecJSI_showWithGravity}; - - - methodMap_["showWithGravityAndOffset"] = MethodMetadata {5, __hostFunction_NativeToastAndroidSpecJSI_showWithGravityAndOffset}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeToastAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getConstantsForViewManager(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstantsForViewManager", @selector(getConstantsForViewManager:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getDefaultEventTypes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, "getDefaultEventTypes", @selector(getDefaultEventTypes), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_lazilyLoadView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "lazilyLoadView", @selector(lazilyLoadView:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_createView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "createView", @selector(createView:viewName:rootTag:props:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_updateView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "updateView", @selector(updateView:viewName:props:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_focus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "focus", @selector(focus:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_blur(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "blur", @selector(blur:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_findSubviewIn(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "findSubviewIn", @selector(findSubviewIn:point:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_dispatchViewManagerCommand(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dispatchViewManagerCommand", @selector(dispatchViewManagerCommand:commandID:commandArgs:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measure(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "measure", @selector(measure:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureInWindow(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "measureInWindow", @selector(measureInWindow:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_viewIsDescendantOf(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "viewIsDescendantOf", @selector(viewIsDescendantOf:ancestorReactTag:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureLayout(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "measureLayout", @selector(measureLayout:ancestorReactTag:errorCallback:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureLayoutRelativeToParent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "measureLayoutRelativeToParent", @selector(measureLayoutRelativeToParent:errorCallback:callback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setJSResponder(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setJSResponder", @selector(setJSResponder:blockNativeResponder:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_clearJSResponder(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "clearJSResponder", @selector(clearJSResponder), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_configureNextLayoutAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "configureNextLayoutAnimation", @selector(configureNextLayoutAnimation:callback:errorCallback:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_removeSubviewsFromContainerWithID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeSubviewsFromContainerWithID", @selector(removeSubviewsFromContainerWithID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_replaceExistingNonRootView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "replaceExistingNonRootView", @selector(replaceExistingNonRootView:newReactTag:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setChildren(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setChildren", @selector(setChildren:reactTags:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_manageChildren(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "manageChildren", @selector(manageChildren:moveFromIndices:moveToIndices:addChildReactTags:addAtIndices:removeAtIndices:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setLayoutAnimationEnabledExperimental(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "setLayoutAnimationEnabledExperimental", @selector(setLayoutAnimationEnabledExperimental:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_sendAccessibilityEvent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "sendAccessibilityEvent", @selector(sendAccessibilityEvent:eventType:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_showPopupMenu(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "showPopupMenu", @selector(showPopupMenu:items:error:success:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_dismissPopupMenu(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "dismissPopupMenu", @selector(dismissPopupMenu), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count); - } - - - NativeUIManagerSpecJSI::NativeUIManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["getConstantsForViewManager"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_getConstantsForViewManager}; - - - methodMap_["getDefaultEventTypes"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_getDefaultEventTypes}; - - - methodMap_["lazilyLoadView"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_lazilyLoadView}; - - - methodMap_["createView"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_createView}; - - - methodMap_["updateView"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_updateView}; - - - methodMap_["focus"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_focus}; - - - methodMap_["blur"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_blur}; - - - methodMap_["findSubviewIn"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_findSubviewIn}; - - - methodMap_["dispatchViewManagerCommand"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_dispatchViewManagerCommand}; - - - methodMap_["measure"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_measure}; - - - methodMap_["measureInWindow"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_measureInWindow}; - - - methodMap_["viewIsDescendantOf"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_viewIsDescendantOf}; - - - methodMap_["measureLayout"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_measureLayout}; - - - methodMap_["measureLayoutRelativeToParent"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_measureLayoutRelativeToParent}; - - - methodMap_["setJSResponder"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_setJSResponder}; - - - methodMap_["clearJSResponder"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_clearJSResponder}; - - - methodMap_["configureNextLayoutAnimation"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_configureNextLayoutAnimation}; - - - methodMap_["removeSubviewsFromContainerWithID"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_removeSubviewsFromContainerWithID}; - - - methodMap_["replaceExistingNonRootView"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_replaceExistingNonRootView}; - - - methodMap_["setChildren"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_setChildren}; - - - methodMap_["manageChildren"] = MethodMetadata {6, __hostFunction_NativeUIManagerSpecJSI_manageChildren}; - - - methodMap_["setLayoutAnimationEnabledExperimental"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_setLayoutAnimationEnabledExperimental}; - - - methodMap_["sendAccessibilityEvent"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_sendAccessibilityEvent}; - - - methodMap_["showPopupMenu"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_showPopupMenu}; - - - methodMap_["dismissPopupMenu"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_dismissPopupMenu}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_vibrate(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "vibrate", @selector(vibrate:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_vibrateByPattern(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "vibrateByPattern", @selector(vibrateByPattern:repeat:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_cancel(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "cancel", @selector(cancel), args, count); - } - - - NativeVibrationSpecJSI::NativeVibrationSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["vibrate"] = MethodMetadata {1, __hostFunction_NativeVibrationSpecJSI_vibrate}; - - - methodMap_["vibrateByPattern"] = MethodMetadata {2, __hostFunction_NativeVibrationSpecJSI_vibrateByPattern}; - - - methodMap_["cancel"] = MethodMetadata {0, __hostFunction_NativeVibrationSpecJSI_cancel}; - - - - } - - } // namespace react -} // namespace facebook -@implementation RCTCxxConvert (NativeWebSocketModule_SpecConnectOptions) -+ (RCTManagedPointer *)JS_NativeWebSocketModule_SpecConnectOptions:(id)json -{ - return facebook::react::managedPointer(json); -} -@end -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_connect(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "connect", @selector(connect:protocols:options:socketID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_send(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "send", @selector(send:forSocketID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_sendBinary(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "sendBinary", @selector(sendBinary:forSocketID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_ping(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "ping", @selector(ping:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_close(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "close", @selector(close:reason:socketID:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count); - } - - - NativeWebSocketModuleSpecJSI::NativeWebSocketModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_["connect"] = MethodMetadata {4, __hostFunction_NativeWebSocketModuleSpecJSI_connect}; - - setMethodArgConversionSelector(@"connect", 2, @"JS_NativeWebSocketModule_SpecConnectOptions:"); - - methodMap_["send"] = MethodMetadata {2, __hostFunction_NativeWebSocketModuleSpecJSI_send}; - - - methodMap_["sendBinary"] = MethodMetadata {2, __hostFunction_NativeWebSocketModuleSpecJSI_sendBinary}; - - - methodMap_["ping"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_ping}; - - - methodMap_["close"] = MethodMetadata {3, __hostFunction_NativeWebSocketModuleSpecJSI_close}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h deleted file mode 100644 index 93f4a41177323f..00000000000000 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +++ /dev/null @@ -1,3597 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal genrule from Flow types. - * - * We create an umbrella header (and corresponding implementation) here since - * Cxx compilation in BUCK has a limitation: source-code producing genrule()s - * must have a single output. More files => more genrule()s => slower builds. - */ - -#ifndef __cplusplus -#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. -#endif -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - - -@protocol NativeAccessibilityInfoSpec - -- (void)isReduceMotionEnabled:(RCTResponseSenderBlock)onSuccess; -- (void)isTouchExplorationEnabled:(RCTResponseSenderBlock)onSuccess; -- (void)setAccessibilityFocus:(double)reactTag; -- (void)announceForAccessibility:(NSString *)announcement; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AccessibilityInfo' - */ - - class JSI_EXPORT NativeAccessibilityInfoSpecJSI : public ObjCTurboModule { - public: - NativeAccessibilityInfoSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAccessibilityManager { - struct SpecSetAccessibilityContentSizeMultipliersJSMultipliers { - folly::Optional extraSmall() const; - folly::Optional small() const; - folly::Optional medium() const; - folly::Optional large() const; - folly::Optional extraLarge() const; - folly::Optional extraExtraLarge() const; - folly::Optional extraExtraExtraLarge() const; - folly::Optional accessibilityMedium() const; - folly::Optional accessibilityLarge() const; - folly::Optional accessibilityExtraLarge() const; - folly::Optional accessibilityExtraExtraLarge() const; - folly::Optional accessibilityExtraExtraExtraLarge() const; - - SpecSetAccessibilityContentSizeMultipliersJSMultipliers(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAccessibilityManager_SpecSetAccessibilityContentSizeMultipliersJSMultipliers) -+ (RCTManagedPointer *)JS_NativeAccessibilityManager_SpecSetAccessibilityContentSizeMultipliersJSMultipliers:(id)json; -@end -@protocol NativeAccessibilityManagerSpec - -- (void)getCurrentBoldTextState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)getCurrentGrayscaleState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)getCurrentInvertColorsState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)getCurrentReduceMotionState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)getCurrentReduceTransparencyState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)getCurrentVoiceOverState:(RCTResponseSenderBlock)onSuccess - onError:(RCTResponseSenderBlock)onError; -- (void)setAccessibilityContentSizeMultipliers:(JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers &)JSMultipliers; -- (void)setAccessibilityFocus:(double)reactTag; -- (void)announceForAccessibility:(NSString *)announcement; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AccessibilityManager' - */ - - class JSI_EXPORT NativeAccessibilityManagerSpecJSI : public ObjCTurboModule { - public: - NativeAccessibilityManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeActionSheetManager { - struct SpecShowActionSheetWithOptionsOptions { - NSString *title() const; - NSString *message() const; - folly::Optional> options() const; - folly::Optional> destructiveButtonIndices() const; - folly::Optional cancelButtonIndex() const; - folly::Optional anchor() const; - folly::Optional tintColor() const; - NSString *userInterfaceStyle() const; - - SpecShowActionSheetWithOptionsOptions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeActionSheetManager_SpecShowActionSheetWithOptionsOptions) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowActionSheetWithOptionsOptions:(id)json; -@end - -namespace JS { - namespace NativeActionSheetManager { - struct SpecShowShareActionSheetWithOptionsOptions { - NSString *message() const; - NSString *url() const; - NSString *subject() const; - folly::Optional anchor() const; - folly::Optional tintColor() const; - folly::Optional> excludedActivityTypes() const; - NSString *userInterfaceStyle() const; - - SpecShowShareActionSheetWithOptionsOptions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeActionSheetManager_SpecShowShareActionSheetWithOptionsOptions) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowShareActionSheetWithOptionsOptions:(id)json; -@end - -namespace JS { - namespace NativeActionSheetManager { - struct SpecShowShareActionSheetWithOptionsFailureCallbackError { - NSString *domain() const; - NSString *code() const; - id _Nullable userInfo() const; - NSString *message() const; - - SpecShowShareActionSheetWithOptionsFailureCallbackError(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeActionSheetManager_SpecShowShareActionSheetWithOptionsFailureCallbackError) -+ (RCTManagedPointer *)JS_NativeActionSheetManager_SpecShowShareActionSheetWithOptionsFailureCallbackError:(id)json; -@end -@protocol NativeActionSheetManagerSpec - -- (void)showActionSheetWithOptions:(JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions &)options - callback:(RCTResponseSenderBlock)callback; -- (void)showShareActionSheetWithOptions:(JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions &)options - failureCallback:(RCTResponseSenderBlock)failureCallback - successCallback:(RCTResponseSenderBlock)successCallback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ActionSheetManager' - */ - - class JSI_EXPORT NativeActionSheetManagerSpecJSI : public ObjCTurboModule { - public: - NativeActionSheetManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAlertManager { - struct Args { - NSString *title() const; - NSString *message() const; - folly::Optional>> buttons() const; - NSString *type() const; - NSString *defaultValue() const; - NSString *cancelButtonKey() const; - NSString *destructiveButtonKey() const; - NSString *keyboardType() const; - - Args(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAlertManager_Args) -+ (RCTManagedPointer *)JS_NativeAlertManager_Args:(id)json; -@end -@protocol NativeAlertManagerSpec - -- (void)alertWithArgs:(JS::NativeAlertManager::Args &)args - callback:(RCTResponseSenderBlock)callback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AlertManager' - */ - - class JSI_EXPORT NativeAlertManagerSpecJSI : public ObjCTurboModule { - public: - NativeAlertManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAnimatedModule { - struct EndResult { - bool finished() const; - - EndResult(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAnimatedModule_EndResult) -+ (RCTManagedPointer *)JS_NativeAnimatedModule_EndResult:(id)json; -@end - -namespace JS { - namespace NativeAnimatedModule { - struct EventMapping { - facebook::react::LazyVector nativeEventPath() const; - folly::Optional animatedValueTag() const; - - EventMapping(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAnimatedModule_EventMapping) -+ (RCTManagedPointer *)JS_NativeAnimatedModule_EventMapping:(id)json; -@end -@protocol NativeAnimatedModuleSpec - -- (void)startOperationBatch; -- (void)finishOperationBatch; -- (void)createAnimatedNode:(double)tag - config:(NSDictionary *)config; -- (void)getValue:(double)tag -saveValueCallback:(RCTResponseSenderBlock)saveValueCallback; -- (void)startListeningToAnimatedNodeValue:(double)tag; -- (void)stopListeningToAnimatedNodeValue:(double)tag; -- (void)connectAnimatedNodes:(double)parentTag - childTag:(double)childTag; -- (void)disconnectAnimatedNodes:(double)parentTag - childTag:(double)childTag; -- (void)startAnimatingNode:(double)animationId - nodeTag:(double)nodeTag - config:(NSDictionary *)config - endCallback:(RCTResponseSenderBlock)endCallback; -- (void)stopAnimation:(double)animationId; -- (void)setAnimatedNodeValue:(double)nodeTag - value:(double)value; -- (void)setAnimatedNodeOffset:(double)nodeTag - offset:(double)offset; -- (void)flattenAnimatedNodeOffset:(double)nodeTag; -- (void)extractAnimatedNodeOffset:(double)nodeTag; -- (void)connectAnimatedNodeToView:(double)nodeTag - viewTag:(double)viewTag; -- (void)disconnectAnimatedNodeFromView:(double)nodeTag - viewTag:(double)viewTag; -- (void)restoreDefaultValues:(double)nodeTag; -- (void)dropAnimatedNode:(double)tag; -- (void)addAnimatedEventToView:(double)viewTag - eventName:(NSString *)eventName - eventMapping:(JS::NativeAnimatedModule::EventMapping &)eventMapping; -- (void)removeAnimatedEventFromView:(double)viewTag - eventName:(NSString *)eventName - animatedNodeTag:(double)animatedNodeTag; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AnimatedModule' - */ - - class JSI_EXPORT NativeAnimatedModuleSpecJSI : public ObjCTurboModule { - public: - NativeAnimatedModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAnimatedTurboModule { - struct EndResult { - bool finished() const; - - EndResult(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAnimatedTurboModule_EndResult) -+ (RCTManagedPointer *)JS_NativeAnimatedTurboModule_EndResult:(id)json; -@end - -namespace JS { - namespace NativeAnimatedTurboModule { - struct EventMapping { - facebook::react::LazyVector nativeEventPath() const; - folly::Optional animatedValueTag() const; - - EventMapping(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAnimatedTurboModule_EventMapping) -+ (RCTManagedPointer *)JS_NativeAnimatedTurboModule_EventMapping:(id)json; -@end -@protocol NativeAnimatedTurboModuleSpec - -- (void)startOperationBatch; -- (void)finishOperationBatch; -- (void)createAnimatedNode:(double)tag - config:(NSDictionary *)config; -- (void)getValue:(double)tag -saveValueCallback:(RCTResponseSenderBlock)saveValueCallback; -- (void)startListeningToAnimatedNodeValue:(double)tag; -- (void)stopListeningToAnimatedNodeValue:(double)tag; -- (void)connectAnimatedNodes:(double)parentTag - childTag:(double)childTag; -- (void)disconnectAnimatedNodes:(double)parentTag - childTag:(double)childTag; -- (void)startAnimatingNode:(double)animationId - nodeTag:(double)nodeTag - config:(NSDictionary *)config - endCallback:(RCTResponseSenderBlock)endCallback; -- (void)stopAnimation:(double)animationId; -- (void)setAnimatedNodeValue:(double)nodeTag - value:(double)value; -- (void)setAnimatedNodeOffset:(double)nodeTag - offset:(double)offset; -- (void)flattenAnimatedNodeOffset:(double)nodeTag; -- (void)extractAnimatedNodeOffset:(double)nodeTag; -- (void)connectAnimatedNodeToView:(double)nodeTag - viewTag:(double)viewTag; -- (void)disconnectAnimatedNodeFromView:(double)nodeTag - viewTag:(double)viewTag; -- (void)restoreDefaultValues:(double)nodeTag; -- (void)dropAnimatedNode:(double)tag; -- (void)addAnimatedEventToView:(double)viewTag - eventName:(NSString *)eventName - eventMapping:(JS::NativeAnimatedTurboModule::EventMapping &)eventMapping; -- (void)removeAnimatedEventFromView:(double)viewTag - eventName:(NSString *)eventName - animatedNodeTag:(double)animatedNodeTag; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AnimatedTurboModule' - */ - - class JSI_EXPORT NativeAnimatedTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeAnimatedTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeAnimationsDebugModuleSpec - -- (void)startRecordingFps; -- (void)stopRecordingFps:(double)animationStopTimeMs; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AnimationsDebugModule' - */ - - class JSI_EXPORT NativeAnimationsDebugModuleSpecJSI : public ObjCTurboModule { - public: - NativeAnimationsDebugModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAppState { - struct SpecGetCurrentAppStateSuccessAppState { - NSString *app_state() const; - - SpecGetCurrentAppStateSuccessAppState(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAppState_SpecGetCurrentAppStateSuccessAppState) -+ (RCTManagedPointer *)JS_NativeAppState_SpecGetCurrentAppStateSuccessAppState:(id)json; -@end - -namespace JS { - namespace NativeAppState { - struct Constants { - - struct Builder { - struct Input { - RCTRequired initialAppState; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeAppStateSpec - -- (void)getCurrentAppState:(RCTResponseSenderBlock)success - error:(RCTResponseSenderBlock)error; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AppState' - */ - - class JSI_EXPORT NativeAppStateSpecJSI : public ObjCTurboModule { - public: - NativeAppStateSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeAppearanceSpec - -- (NSString *)getColorScheme; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'Appearance' - */ - - class JSI_EXPORT NativeAppearanceSpecJSI : public ObjCTurboModule { - public: - NativeAppearanceSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeAppearance { - struct AppearancePreferences { - NSString *colorScheme() const; - - AppearancePreferences(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAppearance_AppearancePreferences) -+ (RCTManagedPointer *)JS_NativeAppearance_AppearancePreferences:(id)json; -@end -typedef NS_ENUM(NSInteger, NativeAppearanceColorSchemeName) { - NativeAppearanceColorSchemeNameLight = 0, - NativeAppearanceColorSchemeNameDark, -}; - -folly::Optional NSStringToNativeAppearanceColorSchemeName(NSString *value); -NSString *NativeAppearanceColorSchemeNameToNSString(folly::Optional value); - -namespace JS { - namespace NativeAsyncStorage { - struct SpecMultiGetCallbackErrorsElement { - NSString *message() const; - - SpecMultiGetCallbackErrorsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiGetCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiGetCallbackErrorsElement:(id)json; -@end - -namespace JS { - namespace NativeAsyncStorage { - struct SpecMultiSetCallbackErrorsElement { - NSString *message() const; - - SpecMultiSetCallbackErrorsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiSetCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiSetCallbackErrorsElement:(id)json; -@end - -namespace JS { - namespace NativeAsyncStorage { - struct SpecMultiMergeCallbackErrorsElement { - NSString *message() const; - - SpecMultiMergeCallbackErrorsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiMergeCallbackErrorsElement:(id)json; -@end - -namespace JS { - namespace NativeAsyncStorage { - struct SpecMultiRemoveCallbackErrorsElement { - NSString *message() const; - - SpecMultiRemoveCallbackErrorsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecMultiRemoveCallbackErrorsElement:(id)json; -@end - -namespace JS { - namespace NativeAsyncStorage { - struct SpecClearCallbackError { - NSString *message() const; - - SpecClearCallbackError(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecClearCallbackError) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecClearCallbackError:(id)json; -@end - -namespace JS { - namespace NativeAsyncStorage { - struct SpecGetAllKeysCallbackError { - NSString *message() const; - - SpecGetAllKeysCallbackError(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeAsyncStorage_SpecGetAllKeysCallbackError) -+ (RCTManagedPointer *)JS_NativeAsyncStorage_SpecGetAllKeysCallbackError:(id)json; -@end -@protocol NativeAsyncStorageSpec - -- (void)multiGet:(NSArray *)keys - callback:(RCTResponseSenderBlock)callback; -- (void)multiSet:(NSArray *)kvPairs - callback:(RCTResponseSenderBlock)callback; -- (void)multiMerge:(NSArray *)kvPairs - callback:(RCTResponseSenderBlock)callback; -- (void)multiRemove:(NSArray *)keys - callback:(RCTResponseSenderBlock)callback; -- (void)clear:(RCTResponseSenderBlock)callback; -- (void)getAllKeys:(RCTResponseSenderBlock)callback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AsyncStorage' - */ - - class JSI_EXPORT NativeAsyncStorageSpecJSI : public ObjCTurboModule { - public: - NativeAsyncStorageSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeBlobModule { - struct Constants { - - struct Builder { - struct Input { - RCTRequired BLOB_URI_SCHEME; - RCTRequired BLOB_URI_HOST; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeBlobModuleSpec - -- (void)addNetworkingHandler; -- (void)addWebSocketHandler:(double)id; -- (void)removeWebSocketHandler:(double)id; -- (void)sendOverSocket:(NSDictionary *)blob - socketID:(double)socketID; -- (void)createFromParts:(NSArray *)parts - withId:(NSString *)withId; -- (void)release:(NSString *)blobId; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'BlobModule' - */ - - class JSI_EXPORT NativeBlobModuleSpecJSI : public ObjCTurboModule { - public: - NativeBlobModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeBugReportingSpec - -- (void)startReportAProblemFlow; -- (void)setExtraData:(NSDictionary *)extraData - extraFiles:(NSDictionary *)extraFiles; -- (void)setCategoryID:(NSString *)categoryID; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'BugReporting' - */ - - class JSI_EXPORT NativeBugReportingSpecJSI : public ObjCTurboModule { - public: - NativeBugReportingSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeClipboardSpec - -- (void)getString:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)setString:(NSString *)content; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'Clipboard' - */ - - class JSI_EXPORT NativeClipboardSpecJSI : public ObjCTurboModule { - public: - NativeClipboardSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDatePickerAndroidSpec - -- (void)open:(NSDictionary *)options - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DatePickerAndroid' - */ - - class JSI_EXPORT NativeDatePickerAndroidSpecJSI : public ObjCTurboModule { - public: - NativeDatePickerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDevLoadingViewSpec - -- (void)showMessage:(NSString *)message - withColor:(NSNumber *)withColor -withBackgroundColor:(NSNumber *)withBackgroundColor; -- (void)hide; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DevLoadingView' - */ - - class JSI_EXPORT NativeDevLoadingViewSpecJSI : public ObjCTurboModule { - public: - NativeDevLoadingViewSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDevMenuSpec - -- (void)show; -- (void)reload; -- (void)debugRemotely:(BOOL)enableDebug; -- (void)setProfilingEnabled:(BOOL)enabled; -- (void)setHotLoadingEnabled:(BOOL)enabled; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DevMenu' - */ - - class JSI_EXPORT NativeDevMenuSpecJSI : public ObjCTurboModule { - public: - NativeDevMenuSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDevSettingsSpec - -- (void)reload; -- (void)reloadWithReason:(NSString *)reason; -- (void)onFastRefresh; -- (void)setHotLoadingEnabled:(BOOL)isHotLoadingEnabled; -- (void)setIsDebuggingRemotely:(BOOL)isDebuggingRemotelyEnabled; -- (void)setProfilingEnabled:(BOOL)isProfilingEnabled; -- (void)toggleElementInspector; -- (void)addMenuItem:(NSString *)title; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; -- (void)setIsShakeToShowDevMenuEnabled:(BOOL)enabled; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DevSettings' - */ - - class JSI_EXPORT NativeDevSettingsSpecJSI : public ObjCTurboModule { - public: - NativeDevSettingsSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDevSplitBundleLoaderSpec - -- (void)loadBundle:(NSString *)bundlePath - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DevSplitBundleLoader' - */ - - class JSI_EXPORT NativeDevSplitBundleLoaderSpecJSI : public ObjCTurboModule { - public: - NativeDevSplitBundleLoaderSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeDeviceEventManagerSpec - -- (void)invokeDefaultBackPressHandler; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DeviceEventManager' - */ - - class JSI_EXPORT NativeDeviceEventManagerSpecJSI : public ObjCTurboModule { - public: - NativeDeviceEventManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeDeviceInfo { - struct DisplayMetrics { - - struct Builder { - struct Input { - RCTRequired width; - RCTRequired height; - RCTRequired scale; - RCTRequired fontScale; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing DisplayMetrics */ - Builder(DisplayMetrics i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static DisplayMetrics fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - DisplayMetrics(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -namespace JS { - namespace NativeDeviceInfo { - struct DisplayMetricsAndroid { - - struct Builder { - struct Input { - RCTRequired width; - RCTRequired height; - RCTRequired scale; - RCTRequired fontScale; - RCTRequired densityDpi; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing DisplayMetricsAndroid */ - Builder(DisplayMetricsAndroid i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static DisplayMetricsAndroid fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - DisplayMetricsAndroid(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -namespace JS { - namespace NativeDeviceInfo { - struct DimensionsPayload { - - struct Builder { - struct Input { - folly::Optional window; - folly::Optional screen; - folly::Optional windowPhysicalPixels; - folly::Optional screenPhysicalPixels; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing DimensionsPayload */ - Builder(DimensionsPayload i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static DimensionsPayload fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - DimensionsPayload(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -namespace JS { - namespace NativeDeviceInfo { - struct Constants { - - struct Builder { - struct Input { - RCTRequired Dimensions; - folly::Optional isIPhoneX_deprecated; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeDeviceInfoSpec - -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DeviceInfo' - */ - - class JSI_EXPORT NativeDeviceInfoSpecJSI : public ObjCTurboModule { - public: - NativeDeviceInfoSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeDialogManagerAndroid { - struct DialogOptions { - NSString *title() const; - NSString *message() const; - NSString *buttonPositive() const; - NSString *buttonNegative() const; - NSString *buttonNeutral() const; - folly::Optional> items() const; - folly::Optional cancelable() const; - - DialogOptions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeDialogManagerAndroid_DialogOptions) -+ (RCTManagedPointer *)JS_NativeDialogManagerAndroid_DialogOptions:(id)json; -@end - -namespace JS { - namespace NativeDialogManagerAndroid { - struct Constants { - - struct Builder { - struct Input { - RCTRequired buttonClicked; - RCTRequired dismissed; - RCTRequired buttonPositive; - RCTRequired buttonNegative; - RCTRequired buttonNeutral; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeDialogManagerAndroidSpec - -- (void)showAlert:(JS::NativeDialogManagerAndroid::DialogOptions &)config - onError:(RCTResponseSenderBlock)onError - onAction:(RCTResponseSenderBlock)onAction; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'DialogManagerAndroid' - */ - - class JSI_EXPORT NativeDialogManagerAndroidSpecJSI : public ObjCTurboModule { - public: - NativeDialogManagerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeExceptionsManager { - struct StackFrame { - folly::Optional column() const; - NSString *file() const; - folly::Optional lineNumber() const; - NSString *methodName() const; - folly::Optional collapse() const; - - StackFrame(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeExceptionsManager_StackFrame) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json; -@end - -namespace JS { - namespace NativeExceptionsManager { - struct ExceptionData { - NSString *message() const; - NSString *originalMessage() const; - NSString *name() const; - NSString *componentStack() const; - facebook::react::LazyVector stack() const; - double id_() const; - bool isFatal() const; - id _Nullable extraData() const; - - ExceptionData(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeExceptionsManager_ExceptionData) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json; -@end -@protocol NativeExceptionsManagerSpec - -- (void)reportFatalException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void)reportSoftException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void)reportException:(JS::NativeExceptionsManager::ExceptionData &)data; -- (void)updateExceptionMessage:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void)dismissRedbox; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ExceptionsManager' - */ - - class JSI_EXPORT NativeExceptionsManagerSpecJSI : public ObjCTurboModule { - public: - NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeFileReaderModuleSpec - -- (void)readAsDataURL:(NSDictionary *)data - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)readAsText:(NSDictionary *)data - encoding:(NSString *)encoding - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'FileReaderModule' - */ - - class JSI_EXPORT NativeFileReaderModuleSpecJSI : public ObjCTurboModule { - public: - NativeFileReaderModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeFrameRateLogger { - struct SpecSetGlobalOptionsOptions { - folly::Optional debug() const; - folly::Optional reportStackTraces() const; - - SpecSetGlobalOptionsOptions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeFrameRateLogger_SpecSetGlobalOptionsOptions) -+ (RCTManagedPointer *)JS_NativeFrameRateLogger_SpecSetGlobalOptionsOptions:(id)json; -@end -@protocol NativeFrameRateLoggerSpec - -- (void)setGlobalOptions:(JS::NativeFrameRateLogger::SpecSetGlobalOptionsOptions &)options; -- (void)setContext:(NSString *)context; -- (void)beginScroll; -- (void)endScroll; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'FrameRateLogger' - */ - - class JSI_EXPORT NativeFrameRateLoggerSpecJSI : public ObjCTurboModule { - public: - NativeFrameRateLoggerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeHeadlessJsTaskSupportSpec - -- (void)notifyTaskFinished:(double)taskId; -- (void)notifyTaskRetry:(double)taskId - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'HeadlessJsTaskSupport' - */ - - class JSI_EXPORT NativeHeadlessJsTaskSupportSpecJSI : public ObjCTurboModule { - public: - NativeHeadlessJsTaskSupportSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeI18nManager { - struct Constants { - - struct Builder { - struct Input { - RCTRequired isRTL; - RCTRequired doLeftAndRightSwapInRTL; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeI18nManagerSpec - -- (void)allowRTL:(BOOL)allowRTL; -- (void)forceRTL:(BOOL)forceRTL; -- (void)swapLeftAndRightInRTL:(BOOL)flipStyles; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'I18nManager' - */ - - class JSI_EXPORT NativeI18nManagerSpecJSI : public ObjCTurboModule { - public: - NativeI18nManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeImageEditor { - struct OptionsOffset { - double x() const; - double y() const; - - OptionsOffset(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImageEditor_OptionsOffset) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsOffset:(id)json; -@end - -namespace JS { - namespace NativeImageEditor { - struct OptionsSize { - double width() const; - double height() const; - - OptionsSize(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImageEditor_OptionsSize) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsSize:(id)json; -@end - -namespace JS { - namespace NativeImageEditor { - struct OptionsDisplaySize { - double width() const; - double height() const; - - OptionsDisplaySize(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImageEditor_OptionsDisplaySize) -+ (RCTManagedPointer *)JS_NativeImageEditor_OptionsDisplaySize:(id)json; -@end - -namespace JS { - namespace NativeImageEditor { - struct Options { - JS::NativeImageEditor::OptionsOffset offset() const; - JS::NativeImageEditor::OptionsSize size() const; - folly::Optional displaySize() const; - NSString *resizeMode() const; - folly::Optional allowExternalStorage() const; - - Options(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImageEditor_Options) -+ (RCTManagedPointer *)JS_NativeImageEditor_Options:(id)json; -@end -@protocol NativeImageEditorSpec - -- (void)cropImage:(NSString *)uri - cropData:(JS::NativeImageEditor::Options &)cropData - successCallback:(RCTResponseSenderBlock)successCallback - errorCallback:(RCTResponseSenderBlock)errorCallback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ImageEditor' - */ - - class JSI_EXPORT NativeImageEditorSpecJSI : public ObjCTurboModule { - public: - NativeImageEditorSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeImageLoaderAndroidSpec - -- (void)abortRequest:(double)requestId; -- (void)getSize:(NSString *)uri - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)getSizeWithHeaders:(NSString *)uri - headers:(NSDictionary *)headers - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)prefetchImage:(NSString *)uri - requestId:(double)requestId - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)queryCache:(NSArray *)uris - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ImageLoaderAndroid' - */ - - class JSI_EXPORT NativeImageLoaderAndroidSpecJSI : public ObjCTurboModule { - public: - NativeImageLoaderAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeImageLoaderIOSSpec - -- (void)getSize:(NSString *)uri - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)getSizeWithHeaders:(NSString *)uri - headers:(NSDictionary *)headers - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)prefetchImage:(NSString *)uri - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)queryCache:(NSArray *)uris - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ImageLoaderIOS' - */ - - class JSI_EXPORT NativeImageLoaderIOSSpecJSI : public ObjCTurboModule { - public: - NativeImageLoaderIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeImagePickerIOS { - struct SpecOpenCameraDialogConfig { - bool unmirrorFrontFacingCamera() const; - bool videoMode() const; - - SpecOpenCameraDialogConfig(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json; -@end - -namespace JS { - namespace NativeImagePickerIOS { - struct SpecOpenSelectDialogConfig { - bool showImages() const; - bool showVideos() const; - - SpecOpenSelectDialogConfig(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenSelectDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenSelectDialogConfig:(id)json; -@end -@protocol NativeImagePickerIOSSpec - -- (void)canRecordVideos:(RCTResponseSenderBlock)callback; -- (void)canUseCamera:(RCTResponseSenderBlock)callback; -- (void)openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config - successCallback:(RCTResponseSenderBlock)successCallback - cancelCallback:(RCTResponseSenderBlock)cancelCallback; -- (void)openSelectDialog:(JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig &)config - successCallback:(RCTResponseSenderBlock)successCallback - cancelCallback:(RCTResponseSenderBlock)cancelCallback; -- (void)clearAllPendingVideos; -- (void)removePendingVideo:(NSString *)url; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ImagePickerIOS' - */ - - class JSI_EXPORT NativeImagePickerIOSSpecJSI : public ObjCTurboModule { - public: - NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeImageStore { - struct SpecAddImageFromBase64ErrorCallbackError { - NSString *message() const; - - SpecAddImageFromBase64ErrorCallbackError(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError) -+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json; -@end -@protocol NativeImageStoreSpec - -- (void)getBase64ForTag:(NSString *)uri - successCallback:(RCTResponseSenderBlock)successCallback - errorCallback:(RCTResponseSenderBlock)errorCallback; -- (void)hasImageForTag:(NSString *)uri - callback:(RCTResponseSenderBlock)callback; -- (void)removeImageForTag:(NSString *)uri; -- (void)addImageFromBase64:(NSString *)base64ImageData - successCallback:(RCTResponseSenderBlock)successCallback - errorCallback:(RCTResponseSenderBlock)errorCallback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ImageStore' - */ - - class JSI_EXPORT NativeImageStoreSpecJSI : public ObjCTurboModule { - public: - NativeImageStoreSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeJSCHeapCaptureSpec - -- (void)captureComplete:(NSString *)path - error:(NSString * _Nullable)error; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'JSCHeapCapture' - */ - - class JSI_EXPORT NativeJSCHeapCaptureSpecJSI : public ObjCTurboModule { - public: - NativeJSCHeapCaptureSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeJSCSamplingProfilerSpec - -- (void)operationComplete:(double)token - result:(NSString * _Nullable)result - error:(NSString * _Nullable)error; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'JSCSamplingProfiler' - */ - - class JSI_EXPORT NativeJSCSamplingProfilerSpecJSI : public ObjCTurboModule { - public: - NativeJSCSamplingProfilerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeJSDevSupport { - struct Constants { - - struct Builder { - struct Input { - RCTRequired ERROR_CODE_EXCEPTION; - RCTRequired ERROR_CODE_VIEW_NOT_FOUND; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeJSDevSupportSpec - -- (void)onSuccess:(NSString *)data; -- (void)onFailure:(double)errorCode - error:(NSString *)error; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'JSDevSupport' - */ - - class JSI_EXPORT NativeJSDevSupportSpecJSI : public ObjCTurboModule { - public: - NativeJSDevSupportSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeKeyboardObserverSpec - -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'KeyboardObserver' - */ - - class JSI_EXPORT NativeKeyboardObserverSpecJSI : public ObjCTurboModule { - public: - NativeKeyboardObserverSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeLinking { - struct SpecSendIntentExtrasElement { - NSString *key() const; - id value() const; - - SpecSendIntentExtrasElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeLinking_SpecSendIntentExtrasElement) -+ (RCTManagedPointer *)JS_NativeLinking_SpecSendIntentExtrasElement:(id)json; -@end -@protocol NativeLinkingSpec - -- (void)getInitialURL:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)canOpenURL:(NSString *)url - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)openURL:(NSString *)url - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)openSettings:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)sendIntent:(NSString *)action - extras:(NSArray *_Nullable)extras - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'Linking' - */ - - class JSI_EXPORT NativeLinkingSpecJSI : public ObjCTurboModule { - public: - NativeLinkingSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeLogBoxSpec - -- (void)show; -- (void)hide; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'LogBox' - */ - - class JSI_EXPORT NativeLogBoxSpecJSI : public ObjCTurboModule { - public: - NativeLogBoxSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeModalManagerSpec - -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ModalManager' - */ - - class JSI_EXPORT NativeModalManagerSpecJSI : public ObjCTurboModule { - public: - NativeModalManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeNetworkingAndroidSpec - -- (void)sendRequest:(NSString *)method - url:(NSString *)url - requestId:(double)requestId - headers:(NSArray *)headers - data:(NSDictionary *)data - responseType:(NSString *)responseType -useIncrementalUpdates:(BOOL)useIncrementalUpdates - timeout:(double)timeout - withCredentials:(BOOL)withCredentials; -- (void)abortRequest:(double)requestId; -- (void)clearCookies:(RCTResponseSenderBlock)callback; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'NetworkingAndroid' - */ - - class JSI_EXPORT NativeNetworkingAndroidSpecJSI : public ObjCTurboModule { - public: - NativeNetworkingAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeNetworkingIOS { - struct SpecSendRequestQuery { - NSString *method() const; - NSString *url() const; - id data() const; - id headers() const; - NSString *responseType() const; - bool incrementalUpdates() const; - double timeout() const; - bool withCredentials() const; - - SpecSendRequestQuery(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeNetworkingIOS_SpecSendRequestQuery) -+ (RCTManagedPointer *)JS_NativeNetworkingIOS_SpecSendRequestQuery:(id)json; -@end -@protocol NativeNetworkingIOSSpec - -- (void)sendRequest:(JS::NativeNetworkingIOS::SpecSendRequestQuery &)query - callback:(RCTResponseSenderBlock)callback; -- (void)abortRequest:(double)requestId; -- (void)clearCookies:(RCTResponseSenderBlock)callback; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'NetworkingIOS' - */ - - class JSI_EXPORT NativeNetworkingIOSSpecJSI : public ObjCTurboModule { - public: - NativeNetworkingIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativePermissionsAndroidSpec - -- (void)checkPermission:(NSString *)permission - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)requestPermission:(NSString *)permission - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)shouldShowRequestPermissionRationale:(NSString *)permission - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)requestMultiplePermissions:(NSArray *)permissions - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'PermissionsAndroid' - */ - - class JSI_EXPORT NativePermissionsAndroidSpecJSI : public ObjCTurboModule { - public: - NativePermissionsAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativePlatformConstantsAndroid { - struct ConstantsReactNativeVersion { - - struct Builder { - struct Input { - RCTRequired major; - RCTRequired minor; - RCTRequired patch; - RCTRequired> prerelease; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsReactNativeVersion */ - Builder(ConstantsReactNativeVersion i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsReactNativeVersion fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsReactNativeVersion(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -namespace JS { - namespace NativePlatformConstantsAndroid { - struct Constants { - - struct Builder { - struct Input { - RCTRequired isTesting; - RCTRequired reactNativeVersion; - RCTRequired Version; - RCTRequired Release; - RCTRequired Serial; - RCTRequired Fingerprint; - RCTRequired Model; - NSString *ServerHost; - RCTRequired uiMode; - RCTRequired Brand; - RCTRequired Manufacturer; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativePlatformConstantsAndroidSpec - -- (NSString *)getAndroidID; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'PlatformConstantsAndroid' - */ - - class JSI_EXPORT NativePlatformConstantsAndroidSpecJSI : public ObjCTurboModule { - public: - NativePlatformConstantsAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativePlatformConstantsIOS { - struct ConstantsReactNativeVersion { - - struct Builder { - struct Input { - RCTRequired major; - RCTRequired minor; - RCTRequired patch; - RCTRequired> prerelease; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsReactNativeVersion */ - Builder(ConstantsReactNativeVersion i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsReactNativeVersion fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsReactNativeVersion(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -namespace JS { - namespace NativePlatformConstantsIOS { - struct Constants { - - struct Builder { - struct Input { - RCTRequired isTesting; - RCTRequired reactNativeVersion; - RCTRequired forceTouchAvailable; - RCTRequired osVersion; - RCTRequired systemName; - RCTRequired interfaceIdiom; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativePlatformConstantsIOSSpec - -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'PlatformConstantsIOS' - */ - - class JSI_EXPORT NativePlatformConstantsIOSSpecJSI : public ObjCTurboModule { - public: - NativePlatformConstantsIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativePushNotificationManagerIOS { - struct SpecRequestPermissionsPermission { - bool alert() const; - bool badge() const; - bool sound() const; - - SpecRequestPermissionsPermission(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativePushNotificationManagerIOS_SpecRequestPermissionsPermission) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_SpecRequestPermissionsPermission:(id)json; -@end - -namespace JS { - namespace NativePushNotificationManagerIOS { - struct Permissions { - bool alert() const; - bool badge() const; - bool sound() const; - - Permissions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativePushNotificationManagerIOS_Permissions) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_Permissions:(id)json; -@end - -namespace JS { - namespace NativePushNotificationManagerIOS { - struct Notification { - NSString *alertTitle() const; - folly::Optional fireDate() const; - NSString *alertBody() const; - NSString *alertAction() const; - id _Nullable userInfo() const; - NSString *category() const; - NSString *repeatInterval() const; - folly::Optional applicationIconBadgeNumber() const; - folly::Optional isSilent() const; - - Notification(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativePushNotificationManagerIOS_Notification) -+ (RCTManagedPointer *)JS_NativePushNotificationManagerIOS_Notification:(id)json; -@end -@protocol NativePushNotificationManagerIOSSpec - -- (void)onFinishRemoteNotification:(NSString *)notificationId - fetchResult:(NSString *)fetchResult; -- (void)setApplicationIconBadgeNumber:(double)num; -- (void)getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback; -- (void)requestPermissions:(JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission &)permission - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)abandonPermissions; -- (void)checkPermissions:(RCTResponseSenderBlock)callback; -- (void)presentLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification; -- (void)scheduleLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification; -- (void)cancelAllLocalNotifications; -- (void)cancelLocalNotifications:(NSDictionary *)userInfo; -- (void)getInitialNotification:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void)getScheduledLocalNotifications:(RCTResponseSenderBlock)callback; -- (void)removeAllDeliveredNotifications; -- (void)removeDeliveredNotifications:(NSArray *)identifiers; -- (void)getDeliveredNotifications:(RCTResponseSenderBlock)callback; -- (void)addListener:(NSString *)eventType; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'PushNotificationManagerIOS' - */ - - class JSI_EXPORT NativePushNotificationManagerIOSSpecJSI : public ObjCTurboModule { - public: - NativePushNotificationManagerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeRedBoxSpec - -- (void)setExtraData:(NSDictionary *)extraData - forIdentifier:(NSString *)forIdentifier; -- (void)dismiss; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'RedBox' - */ - - class JSI_EXPORT NativeRedBoxSpecJSI : public ObjCTurboModule { - public: - NativeRedBoxSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeSegmentFetcherSpec - -- (void)fetchSegment:(double)segmentId - options:(NSDictionary *)options - callback:(RCTResponseSenderBlock)callback; -- (void)getSegment:(double)segmentId - options:(NSDictionary *)options - callback:(RCTResponseSenderBlock)callback; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SegmentFetcher' - */ - - class JSI_EXPORT NativeSegmentFetcherSpecJSI : public ObjCTurboModule { - public: - NativeSegmentFetcherSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeSettingsManager { - struct Constants { - - struct Builder { - struct Input { - RCTRequired> settings; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeSettingsManagerSpec - -- (void)setValues:(NSDictionary *)values; -- (void)deleteValues:(NSArray *)values; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SettingsManager' - */ - - class JSI_EXPORT NativeSettingsManagerSpecJSI : public ObjCTurboModule { - public: - NativeSettingsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeShareModule { - struct SpecShareContent { - NSString *title() const; - NSString *message() const; - - SpecShareContent(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeShareModule_SpecShareContent) -+ (RCTManagedPointer *)JS_NativeShareModule_SpecShareContent:(id)json; -@end -@protocol NativeShareModuleSpec - -- (void)share:(JS::NativeShareModule::SpecShareContent &)content - dialogTitle:(NSString *)dialogTitle - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ShareModule' - */ - - class JSI_EXPORT NativeShareModuleSpecJSI : public ObjCTurboModule { - public: - NativeShareModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeSoundManagerSpec - -- (void)playTouchSound; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SoundManager' - */ - - class JSI_EXPORT NativeSoundManagerSpecJSI : public ObjCTurboModule { - public: - NativeSoundManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeSourceCode { - struct Constants { - - struct Builder { - struct Input { - RCTRequired scriptURL; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeSourceCodeSpec - -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SourceCode' - */ - - class JSI_EXPORT NativeSourceCodeSpecJSI : public ObjCTurboModule { - public: - NativeSourceCodeSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeStatusBarManagerAndroid { - struct Constants { - - struct Builder { - struct Input { - RCTRequired HEIGHT; - RCTRequired DEFAULT_BACKGROUND_COLOR; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeStatusBarManagerAndroidSpec - -- (void)setColor:(double)color - animated:(BOOL)animated; -- (void)setTranslucent:(BOOL)translucent; -- (void)setStyle:(NSString * _Nullable)statusBarStyle; -- (void)setHidden:(BOOL)hidden; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'StatusBarManagerAndroid' - */ - - class JSI_EXPORT NativeStatusBarManagerAndroidSpecJSI : public ObjCTurboModule { - public: - NativeStatusBarManagerAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeStatusBarManagerIOS { - struct SpecGetHeightCallbackResult { - double height() const; - - SpecGetHeightCallbackResult(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeStatusBarManagerIOS_SpecGetHeightCallbackResult) -+ (RCTManagedPointer *)JS_NativeStatusBarManagerIOS_SpecGetHeightCallbackResult:(id)json; -@end - -namespace JS { - namespace NativeStatusBarManagerIOS { - struct Constants { - - struct Builder { - struct Input { - RCTRequired HEIGHT; - folly::Optional DEFAULT_BACKGROUND_COLOR; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeStatusBarManagerIOSSpec - -- (void)getHeight:(RCTResponseSenderBlock)callback; -- (void)setNetworkActivityIndicatorVisible:(BOOL)visible; -- (void)addListener:(NSString *)eventType; -- (void)removeListeners:(double)count; -- (void)setStyle:(NSString * _Nullable)statusBarStyle - animated:(BOOL)animated; -- (void)setHidden:(BOOL)hidden - withAnimation:(NSString *)withAnimation; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'StatusBarManagerIOS' - */ - - class JSI_EXPORT NativeStatusBarManagerIOSSpecJSI : public ObjCTurboModule { - public: - NativeStatusBarManagerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeTVNavigationEventEmitterSpec - -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'TVNavigationEventEmitter' - */ - - class JSI_EXPORT NativeTVNavigationEventEmitterSpecJSI : public ObjCTurboModule { - public: - NativeTVNavigationEventEmitterSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeTimingSpec - -- (void)createTimer:(double)callbackID - duration:(double)duration - jsSchedulingTime:(double)jsSchedulingTime - repeats:(BOOL)repeats; -- (void)deleteTimer:(double)timerID; -- (void)setSendIdleEvents:(BOOL)sendIdleEvents; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'Timing' - */ - - class JSI_EXPORT NativeTimingSpecJSI : public ObjCTurboModule { - public: - NativeTimingSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeToastAndroid { - struct Constants { - - struct Builder { - struct Input { - RCTRequired SHORT; - RCTRequired LONG; - RCTRequired TOP; - RCTRequired BOTTOM; - RCTRequired CENTER; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeToastAndroidSpec - -- (void)show:(NSString *)message - duration:(double)duration; -- (void)showWithGravity:(NSString *)message - duration:(double)duration - gravity:(double)gravity; -- (void)showWithGravityAndOffset:(NSString *)message - duration:(double)duration - gravity:(double)gravity - xOffset:(double)xOffset - yOffset:(double)yOffset; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'ToastAndroid' - */ - - class JSI_EXPORT NativeToastAndroidSpecJSI : public ObjCTurboModule { - public: - NativeToastAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeUIManager { - struct Constants { - - struct Builder { - struct Input { - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} -@protocol NativeUIManagerSpec - -- (NSDictionary *)getConstantsForViewManager:(NSString *)viewManagerName; -- (NSArray *)getDefaultEventTypes; -- (NSDictionary *)lazilyLoadView:(NSString *)name; -- (void)createView:(NSNumber *)reactTag - viewName:(NSString *)viewName - rootTag:(double)rootTag - props:(NSDictionary *)props; -- (void)updateView:(double)reactTag - viewName:(NSString *)viewName - props:(NSDictionary *)props; -- (void)focus:(NSNumber *)reactTag; -- (void)blur:(NSNumber *)reactTag; -- (void)findSubviewIn:(NSNumber *)reactTag - point:(NSArray *)point - callback:(RCTResponseSenderBlock)callback; -- (void)dispatchViewManagerCommand:(NSNumber *)reactTag - commandID:(double)commandID - commandArgs:(NSArray *_Nullable)commandArgs; -- (void)measure:(NSNumber *)reactTag - callback:(RCTResponseSenderBlock)callback; -- (void)measureInWindow:(NSNumber *)reactTag - callback:(RCTResponseSenderBlock)callback; -- (void)viewIsDescendantOf:(NSNumber *)reactTag - ancestorReactTag:(NSNumber *)ancestorReactTag - callback:(RCTResponseSenderBlock)callback; -- (void)measureLayout:(NSNumber *)reactTag - ancestorReactTag:(NSNumber *)ancestorReactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(RCTResponseSenderBlock)callback; -- (void)measureLayoutRelativeToParent:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(RCTResponseSenderBlock)callback; -- (void)setJSResponder:(NSNumber *)reactTag - blockNativeResponder:(BOOL)blockNativeResponder; -- (void)clearJSResponder; -- (void)configureNextLayoutAnimation:(NSDictionary *)config - callback:(RCTResponseSenderBlock)callback - errorCallback:(RCTResponseSenderBlock)errorCallback; -- (void)removeSubviewsFromContainerWithID:(double)containerID; -- (void)replaceExistingNonRootView:(NSNumber *)reactTag - newReactTag:(NSNumber *)newReactTag; -- (void)setChildren:(NSNumber *)containerTag - reactTags:(NSArray *)reactTags; -- (void)manageChildren:(NSNumber *)containerTag - moveFromIndices:(NSArray *)moveFromIndices - moveToIndices:(NSArray *)moveToIndices - addChildReactTags:(NSArray *)addChildReactTags - addAtIndices:(NSArray *)addAtIndices - removeAtIndices:(NSArray *)removeAtIndices; -- (void)setLayoutAnimationEnabledExperimental:(BOOL)enabled; -- (void)sendAccessibilityEvent:(NSNumber *)reactTag - eventType:(double)eventType; -- (void)showPopupMenu:(NSNumber *)reactTag - items:(NSArray *)items - error:(RCTResponseSenderBlock)error - success:(RCTResponseSenderBlock)success; -- (void)dismissPopupMenu; -- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'UIManager' - */ - - class JSI_EXPORT NativeUIManagerSpecJSI : public ObjCTurboModule { - public: - NativeUIManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook -@protocol NativeVibrationSpec - -- (void)vibrate:(double)pattern; -- (void)vibrateByPattern:(NSArray *)pattern - repeat:(double)repeat; -- (void)cancel; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'Vibration' - */ - - class JSI_EXPORT NativeVibrationSpecJSI : public ObjCTurboModule { - public: - NativeVibrationSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace JS { - namespace NativeWebSocketModule { - struct SpecConnectOptions { - id _Nullable headers() const; - - SpecConnectOptions(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeWebSocketModule_SpecConnectOptions) -+ (RCTManagedPointer *)JS_NativeWebSocketModule_SpecConnectOptions:(id)json; -@end -@protocol NativeWebSocketModuleSpec - -- (void)connect:(NSString *)url - protocols:(NSArray *_Nullable)protocols - options:(JS::NativeWebSocketModule::SpecConnectOptions &)options - socketID:(double)socketID; -- (void)send:(NSString *)message - forSocketID:(double)forSocketID; -- (void)sendBinary:(NSString *)base64String - forSocketID:(double)forSocketID; -- (void)ping:(double)socketID; -- (void)close:(double)code - reason:(NSString *)reason - socketID:(double)socketID; -- (void)addListener:(NSString *)eventName; -- (void)removeListeners:(double)count; - -@end -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'WebSocketModule' - */ - - class JSI_EXPORT NativeWebSocketModuleSpecJSI : public ObjCTurboModule { - public: - NativeWebSocketModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -#import - - -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::extraSmall() const -{ - id const p = _v[@"extraSmall"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::small() const -{ - id const p = _v[@"small"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::medium() const -{ - id const p = _v[@"medium"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::large() const -{ - id const p = _v[@"large"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::extraLarge() const -{ - id const p = _v[@"extraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::extraExtraLarge() const -{ - id const p = _v[@"extraExtraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::extraExtraExtraLarge() const -{ - id const p = _v[@"extraExtraExtraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::accessibilityMedium() const -{ - id const p = _v[@"accessibilityMedium"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::accessibilityLarge() const -{ - id const p = _v[@"accessibilityLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::accessibilityExtraLarge() const -{ - id const p = _v[@"accessibilityExtraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::accessibilityExtraExtraLarge() const -{ - id const p = _v[@"accessibilityExtraExtraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeAccessibilityManager::SpecSetAccessibilityContentSizeMultipliersJSMultipliers::accessibilityExtraExtraExtraLarge() const -{ - id const p = _v[@"accessibilityExtraExtraExtraLarge"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::title() const -{ - id const p = _v[@"title"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline folly::Optional> JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::options() const -{ - id const p = _v[@"options"]; - return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); -} -inline folly::Optional> JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::destructiveButtonIndices() const -{ - id const p = _v[@"destructiveButtonIndices"]; - return RCTBridgingToOptionalVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); }); -} -inline folly::Optional JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::cancelButtonIndex() const -{ - id const p = _v[@"cancelButtonIndex"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::anchor() const -{ - id const p = _v[@"anchor"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::tintColor() const -{ - id const p = _v[@"tintColor"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowActionSheetWithOptionsOptions::userInterfaceStyle() const -{ - id const p = _v[@"userInterfaceStyle"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::url() const -{ - id const p = _v[@"url"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::subject() const -{ - id const p = _v[@"subject"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::anchor() const -{ - id const p = _v[@"anchor"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::tintColor() const -{ - id const p = _v[@"tintColor"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional> JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::excludedActivityTypes() const -{ - id const p = _v[@"excludedActivityTypes"]; - return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsOptions::userInterfaceStyle() const -{ - id const p = _v[@"userInterfaceStyle"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsFailureCallbackError::domain() const -{ - id const p = _v[@"domain"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsFailureCallbackError::code() const -{ - id const p = _v[@"code"]; - return RCTBridgingToString(p); -} -inline id _Nullable JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsFailureCallbackError::userInfo() const -{ - id const p = _v[@"userInfo"]; - return p; -} -inline NSString *JS::NativeActionSheetManager::SpecShowShareActionSheetWithOptionsFailureCallbackError::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::title() const -{ - id const p = _v[@"title"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline folly::Optional>> JS::NativeAlertManager::Args::buttons() const -{ - id const p = _v[@"buttons"]; - return RCTBridgingToOptionalVec(p, ^id(id itemValue_0) { return itemValue_0; }); -} -inline NSString *JS::NativeAlertManager::Args::type() const -{ - id const p = _v[@"type"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::defaultValue() const -{ - id const p = _v[@"defaultValue"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::cancelButtonKey() const -{ - id const p = _v[@"cancelButtonKey"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::destructiveButtonKey() const -{ - id const p = _v[@"destructiveButtonKey"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAlertManager::Args::keyboardType() const -{ - id const p = _v[@"keyboardType"]; - return RCTBridgingToString(p); -} -inline bool JS::NativeAnimatedModule::EndResult::finished() const -{ - id const p = _v[@"finished"]; - return RCTBridgingToBool(p); -} -inline facebook::react::LazyVector JS::NativeAnimatedModule::EventMapping::nativeEventPath() const -{ - id const p = _v[@"nativeEventPath"]; - return RCTBridgingToVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); -} -inline folly::Optional JS::NativeAnimatedModule::EventMapping::animatedValueTag() const -{ - id const p = _v[@"animatedValueTag"]; - return RCTBridgingToOptionalDouble(p); -} -inline bool JS::NativeAnimatedTurboModule::EndResult::finished() const -{ - id const p = _v[@"finished"]; - return RCTBridgingToBool(p); -} -inline facebook::react::LazyVector JS::NativeAnimatedTurboModule::EventMapping::nativeEventPath() const -{ - id const p = _v[@"nativeEventPath"]; - return RCTBridgingToVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); -} -inline folly::Optional JS::NativeAnimatedTurboModule::EventMapping::animatedValueTag() const -{ - id const p = _v[@"animatedValueTag"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativeAppState::SpecGetCurrentAppStateSuccessAppState::app_state() const -{ - id const p = _v[@"app_state"]; - return RCTBridgingToString(p); -} -inline JS::NativeAppState::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto initialAppState = i.initialAppState.get(); - d[@"initialAppState"] = initialAppState; - return d; -}) {} -inline JS::NativeAppState::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline NSString *JS::NativeAppearance::AppearancePreferences::colorScheme() const -{ - id const p = _v[@"colorScheme"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecMultiGetCallbackErrorsElement::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecMultiSetCallbackErrorsElement::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecMultiMergeCallbackErrorsElement::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecMultiRemoveCallbackErrorsElement::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecClearCallbackError::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeAsyncStorage::SpecGetAllKeysCallbackError::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline JS::NativeBlobModule::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto BLOB_URI_SCHEME = i.BLOB_URI_SCHEME.get(); - d[@"BLOB_URI_SCHEME"] = BLOB_URI_SCHEME; - auto BLOB_URI_HOST = i.BLOB_URI_HOST.get(); - d[@"BLOB_URI_HOST"] = BLOB_URI_HOST; - return d; -}) {} -inline JS::NativeBlobModule::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeDeviceInfo::DisplayMetrics::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto width = i.width.get(); - d[@"width"] = @(width); - auto height = i.height.get(); - d[@"height"] = @(height); - auto scale = i.scale.get(); - d[@"scale"] = @(scale); - auto fontScale = i.fontScale.get(); - d[@"fontScale"] = @(fontScale); - return d; -}) {} -inline JS::NativeDeviceInfo::DisplayMetrics::Builder::Builder(DisplayMetrics i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeDeviceInfo::DisplayMetricsAndroid::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto width = i.width.get(); - d[@"width"] = @(width); - auto height = i.height.get(); - d[@"height"] = @(height); - auto scale = i.scale.get(); - d[@"scale"] = @(scale); - auto fontScale = i.fontScale.get(); - d[@"fontScale"] = @(fontScale); - auto densityDpi = i.densityDpi.get(); - d[@"densityDpi"] = @(densityDpi); - return d; -}) {} -inline JS::NativeDeviceInfo::DisplayMetricsAndroid::Builder::Builder(DisplayMetricsAndroid i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeDeviceInfo::DimensionsPayload::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto window = i.window; - d[@"window"] = window.hasValue() ? window.value().buildUnsafeRawValue() : nil; - auto screen = i.screen; - d[@"screen"] = screen.hasValue() ? screen.value().buildUnsafeRawValue() : nil; - auto windowPhysicalPixels = i.windowPhysicalPixels; - d[@"windowPhysicalPixels"] = windowPhysicalPixels.hasValue() ? windowPhysicalPixels.value().buildUnsafeRawValue() : nil; - auto screenPhysicalPixels = i.screenPhysicalPixels; - d[@"screenPhysicalPixels"] = screenPhysicalPixels.hasValue() ? screenPhysicalPixels.value().buildUnsafeRawValue() : nil; - return d; -}) {} -inline JS::NativeDeviceInfo::DimensionsPayload::Builder::Builder(DimensionsPayload i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeDeviceInfo::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto Dimensions = i.Dimensions.get(); - d[@"Dimensions"] = Dimensions.buildUnsafeRawValue(); - auto isIPhoneX_deprecated = i.isIPhoneX_deprecated; - d[@"isIPhoneX_deprecated"] = isIPhoneX_deprecated.hasValue() ? @((BOOL)isIPhoneX_deprecated.value()) : nil; - return d; -}) {} -inline JS::NativeDeviceInfo::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline NSString *JS::NativeDialogManagerAndroid::DialogOptions::title() const -{ - id const p = _v[@"title"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeDialogManagerAndroid::DialogOptions::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeDialogManagerAndroid::DialogOptions::buttonPositive() const -{ - id const p = _v[@"buttonPositive"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeDialogManagerAndroid::DialogOptions::buttonNegative() const -{ - id const p = _v[@"buttonNegative"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeDialogManagerAndroid::DialogOptions::buttonNeutral() const -{ - id const p = _v[@"buttonNeutral"]; - return RCTBridgingToString(p); -} -inline folly::Optional> JS::NativeDialogManagerAndroid::DialogOptions::items() const -{ - id const p = _v[@"items"]; - return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); -} -inline folly::Optional JS::NativeDialogManagerAndroid::DialogOptions::cancelable() const -{ - id const p = _v[@"cancelable"]; - return RCTBridgingToOptionalBool(p); -} -inline JS::NativeDialogManagerAndroid::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto buttonClicked = i.buttonClicked.get(); - d[@"buttonClicked"] = buttonClicked; - auto dismissed = i.dismissed.get(); - d[@"dismissed"] = dismissed; - auto buttonPositive = i.buttonPositive.get(); - d[@"buttonPositive"] = @(buttonPositive); - auto buttonNegative = i.buttonNegative.get(); - d[@"buttonNegative"] = @(buttonNegative); - auto buttonNeutral = i.buttonNeutral.get(); - d[@"buttonNeutral"] = @(buttonNeutral); - return d; -}) {} -inline JS::NativeDialogManagerAndroid::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline folly::Optional JS::NativeExceptionsManager::StackFrame::column() const -{ - id const p = _v[@"column"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativeExceptionsManager::StackFrame::file() const -{ - id const p = _v[@"file"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativeExceptionsManager::StackFrame::lineNumber() const -{ - id const p = _v[@"lineNumber"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const -{ - id const p = _v[@"methodName"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const -{ - id const p = _v[@"collapse"]; - return RCTBridgingToOptionalBool(p); -} -inline NSString *JS::NativeExceptionsManager::ExceptionData::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeExceptionsManager::ExceptionData::originalMessage() const -{ - id const p = _v[@"originalMessage"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeExceptionsManager::ExceptionData::name() const -{ - id const p = _v[@"name"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeExceptionsManager::ExceptionData::componentStack() const -{ - id const p = _v[@"componentStack"]; - return RCTBridgingToString(p); -} -inline facebook::react::LazyVector JS::NativeExceptionsManager::ExceptionData::stack() const -{ - id const p = _v[@"stack"]; - return RCTBridgingToVec(p, ^JS::NativeExceptionsManager::StackFrame(id itemValue_0) { return JS::NativeExceptionsManager::StackFrame(itemValue_0); }); -} -inline double JS::NativeExceptionsManager::ExceptionData::id_() const -{ - id const p = _v[@"id"]; - return RCTBridgingToDouble(p); -} -inline bool JS::NativeExceptionsManager::ExceptionData::isFatal() const -{ - id const p = _v[@"isFatal"]; - return RCTBridgingToBool(p); -} -inline id _Nullable JS::NativeExceptionsManager::ExceptionData::extraData() const -{ - id const p = _v[@"extraData"]; - return p; -} -inline folly::Optional JS::NativeFrameRateLogger::SpecSetGlobalOptionsOptions::debug() const -{ - id const p = _v[@"debug"]; - return RCTBridgingToOptionalBool(p); -} -inline folly::Optional JS::NativeFrameRateLogger::SpecSetGlobalOptionsOptions::reportStackTraces() const -{ - id const p = _v[@"reportStackTraces"]; - return RCTBridgingToOptionalBool(p); -} -inline JS::NativeI18nManager::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto isRTL = i.isRTL.get(); - d[@"isRTL"] = @(isRTL); - auto doLeftAndRightSwapInRTL = i.doLeftAndRightSwapInRTL.get(); - d[@"doLeftAndRightSwapInRTL"] = @(doLeftAndRightSwapInRTL); - return d; -}) {} -inline JS::NativeI18nManager::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline double JS::NativeImageEditor::OptionsOffset::x() const -{ - id const p = _v[@"x"]; - return RCTBridgingToDouble(p); -} -inline double JS::NativeImageEditor::OptionsOffset::y() const -{ - id const p = _v[@"y"]; - return RCTBridgingToDouble(p); -} -inline double JS::NativeImageEditor::OptionsSize::width() const -{ - id const p = _v[@"width"]; - return RCTBridgingToDouble(p); -} -inline double JS::NativeImageEditor::OptionsSize::height() const -{ - id const p = _v[@"height"]; - return RCTBridgingToDouble(p); -} -inline double JS::NativeImageEditor::OptionsDisplaySize::width() const -{ - id const p = _v[@"width"]; - return RCTBridgingToDouble(p); -} -inline double JS::NativeImageEditor::OptionsDisplaySize::height() const -{ - id const p = _v[@"height"]; - return RCTBridgingToDouble(p); -} -inline JS::NativeImageEditor::OptionsOffset JS::NativeImageEditor::Options::offset() const -{ - id const p = _v[@"offset"]; - return JS::NativeImageEditor::OptionsOffset(p); -} -inline JS::NativeImageEditor::OptionsSize JS::NativeImageEditor::Options::size() const -{ - id const p = _v[@"size"]; - return JS::NativeImageEditor::OptionsSize(p); -} -inline folly::Optional JS::NativeImageEditor::Options::displaySize() const -{ - id const p = _v[@"displaySize"]; - return (p == nil ? folly::none : folly::make_optional(JS::NativeImageEditor::OptionsDisplaySize(p))); -} -inline NSString *JS::NativeImageEditor::Options::resizeMode() const -{ - id const p = _v[@"resizeMode"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativeImageEditor::Options::allowExternalStorage() const -{ - id const p = _v[@"allowExternalStorage"]; - return RCTBridgingToOptionalBool(p); -} -inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::unmirrorFrontFacingCamera() const -{ - id const p = _v[@"unmirrorFrontFacingCamera"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::videoMode() const -{ - id const p = _v[@"videoMode"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig::showImages() const -{ - id const p = _v[@"showImages"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig::showVideos() const -{ - id const p = _v[@"showVideos"]; - return RCTBridgingToBool(p); -} -inline NSString *JS::NativeImageStore::SpecAddImageFromBase64ErrorCallbackError::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline JS::NativeJSDevSupport::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto ERROR_CODE_EXCEPTION = i.ERROR_CODE_EXCEPTION.get(); - d[@"ERROR_CODE_EXCEPTION"] = @(ERROR_CODE_EXCEPTION); - auto ERROR_CODE_VIEW_NOT_FOUND = i.ERROR_CODE_VIEW_NOT_FOUND.get(); - d[@"ERROR_CODE_VIEW_NOT_FOUND"] = @(ERROR_CODE_VIEW_NOT_FOUND); - return d; -}) {} -inline JS::NativeJSDevSupport::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline NSString *JS::NativeLinking::SpecSendIntentExtrasElement::key() const -{ - id const p = _v[@"key"]; - return RCTBridgingToString(p); -} -inline id JS::NativeLinking::SpecSendIntentExtrasElement::value() const -{ - id const p = _v[@"value"]; - return p; -} -inline NSString *JS::NativeNetworkingIOS::SpecSendRequestQuery::method() const -{ - id const p = _v[@"method"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeNetworkingIOS::SpecSendRequestQuery::url() const -{ - id const p = _v[@"url"]; - return RCTBridgingToString(p); -} -inline id JS::NativeNetworkingIOS::SpecSendRequestQuery::data() const -{ - id const p = _v[@"data"]; - return p; -} -inline id JS::NativeNetworkingIOS::SpecSendRequestQuery::headers() const -{ - id const p = _v[@"headers"]; - return p; -} -inline NSString *JS::NativeNetworkingIOS::SpecSendRequestQuery::responseType() const -{ - id const p = _v[@"responseType"]; - return RCTBridgingToString(p); -} -inline bool JS::NativeNetworkingIOS::SpecSendRequestQuery::incrementalUpdates() const -{ - id const p = _v[@"incrementalUpdates"]; - return RCTBridgingToBool(p); -} -inline double JS::NativeNetworkingIOS::SpecSendRequestQuery::timeout() const -{ - id const p = _v[@"timeout"]; - return RCTBridgingToDouble(p); -} -inline bool JS::NativeNetworkingIOS::SpecSendRequestQuery::withCredentials() const -{ - id const p = _v[@"withCredentials"]; - return RCTBridgingToBool(p); -} -inline JS::NativePlatformConstantsAndroid::ConstantsReactNativeVersion::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto major = i.major.get(); - d[@"major"] = @(major); - auto minor = i.minor.get(); - d[@"minor"] = @(minor); - auto patch = i.patch.get(); - d[@"patch"] = @(patch); - auto prerelease = i.prerelease.get(); - d[@"prerelease"] = prerelease.hasValue() ? @((double)prerelease.value()) : nil; - return d; -}) {} -inline JS::NativePlatformConstantsAndroid::ConstantsReactNativeVersion::Builder::Builder(ConstantsReactNativeVersion i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativePlatformConstantsAndroid::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto isTesting = i.isTesting.get(); - d[@"isTesting"] = @(isTesting); - auto reactNativeVersion = i.reactNativeVersion.get(); - d[@"reactNativeVersion"] = reactNativeVersion.buildUnsafeRawValue(); - auto Version = i.Version.get(); - d[@"Version"] = @(Version); - auto Release = i.Release.get(); - d[@"Release"] = Release; - auto Serial = i.Serial.get(); - d[@"Serial"] = Serial; - auto Fingerprint = i.Fingerprint.get(); - d[@"Fingerprint"] = Fingerprint; - auto Model = i.Model.get(); - d[@"Model"] = Model; - auto ServerHost = i.ServerHost; - d[@"ServerHost"] = ServerHost; - auto uiMode = i.uiMode.get(); - d[@"uiMode"] = uiMode; - auto Brand = i.Brand.get(); - d[@"Brand"] = Brand; - auto Manufacturer = i.Manufacturer.get(); - d[@"Manufacturer"] = Manufacturer; - return d; -}) {} -inline JS::NativePlatformConstantsAndroid::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativePlatformConstantsIOS::ConstantsReactNativeVersion::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto major = i.major.get(); - d[@"major"] = @(major); - auto minor = i.minor.get(); - d[@"minor"] = @(minor); - auto patch = i.patch.get(); - d[@"patch"] = @(patch); - auto prerelease = i.prerelease.get(); - d[@"prerelease"] = prerelease.hasValue() ? @((double)prerelease.value()) : nil; - return d; -}) {} -inline JS::NativePlatformConstantsIOS::ConstantsReactNativeVersion::Builder::Builder(ConstantsReactNativeVersion i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativePlatformConstantsIOS::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto isTesting = i.isTesting.get(); - d[@"isTesting"] = @(isTesting); - auto reactNativeVersion = i.reactNativeVersion.get(); - d[@"reactNativeVersion"] = reactNativeVersion.buildUnsafeRawValue(); - auto forceTouchAvailable = i.forceTouchAvailable.get(); - d[@"forceTouchAvailable"] = @(forceTouchAvailable); - auto osVersion = i.osVersion.get(); - d[@"osVersion"] = osVersion; - auto systemName = i.systemName.get(); - d[@"systemName"] = systemName; - auto interfaceIdiom = i.interfaceIdiom.get(); - d[@"interfaceIdiom"] = interfaceIdiom; - return d; -}) {} -inline JS::NativePlatformConstantsIOS::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::alert() const -{ - id const p = _v[@"alert"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::badge() const -{ - id const p = _v[@"badge"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::sound() const -{ - id const p = _v[@"sound"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativePushNotificationManagerIOS::Permissions::alert() const -{ - id const p = _v[@"alert"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativePushNotificationManagerIOS::Permissions::badge() const -{ - id const p = _v[@"badge"]; - return RCTBridgingToBool(p); -} -inline bool JS::NativePushNotificationManagerIOS::Permissions::sound() const -{ - id const p = _v[@"sound"]; - return RCTBridgingToBool(p); -} -inline NSString *JS::NativePushNotificationManagerIOS::Notification::alertTitle() const -{ - id const p = _v[@"alertTitle"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativePushNotificationManagerIOS::Notification::fireDate() const -{ - id const p = _v[@"fireDate"]; - return RCTBridgingToOptionalDouble(p); -} -inline NSString *JS::NativePushNotificationManagerIOS::Notification::alertBody() const -{ - id const p = _v[@"alertBody"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativePushNotificationManagerIOS::Notification::alertAction() const -{ - id const p = _v[@"alertAction"]; - return RCTBridgingToString(p); -} -inline id _Nullable JS::NativePushNotificationManagerIOS::Notification::userInfo() const -{ - id const p = _v[@"userInfo"]; - return p; -} -inline NSString *JS::NativePushNotificationManagerIOS::Notification::category() const -{ - id const p = _v[@"category"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativePushNotificationManagerIOS::Notification::repeatInterval() const -{ - id const p = _v[@"repeatInterval"]; - return RCTBridgingToString(p); -} -inline folly::Optional JS::NativePushNotificationManagerIOS::Notification::applicationIconBadgeNumber() const -{ - id const p = _v[@"applicationIconBadgeNumber"]; - return RCTBridgingToOptionalDouble(p); -} -inline folly::Optional JS::NativePushNotificationManagerIOS::Notification::isSilent() const -{ - id const p = _v[@"isSilent"]; - return RCTBridgingToOptionalBool(p); -} -inline JS::NativeSettingsManager::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto settings = i.settings.get(); - d[@"settings"] = settings; - return d; -}) {} -inline JS::NativeSettingsManager::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline NSString *JS::NativeShareModule::SpecShareContent::title() const -{ - id const p = _v[@"title"]; - return RCTBridgingToString(p); -} -inline NSString *JS::NativeShareModule::SpecShareContent::message() const -{ - id const p = _v[@"message"]; - return RCTBridgingToString(p); -} -inline JS::NativeSourceCode::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto scriptURL = i.scriptURL.get(); - d[@"scriptURL"] = scriptURL; - return d; -}) {} -inline JS::NativeSourceCode::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeStatusBarManagerAndroid::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto HEIGHT = i.HEIGHT.get(); - d[@"HEIGHT"] = @(HEIGHT); - auto DEFAULT_BACKGROUND_COLOR = i.DEFAULT_BACKGROUND_COLOR.get(); - d[@"DEFAULT_BACKGROUND_COLOR"] = @(DEFAULT_BACKGROUND_COLOR); - return d; -}) {} -inline JS::NativeStatusBarManagerAndroid::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline double JS::NativeStatusBarManagerIOS::SpecGetHeightCallbackResult::height() const -{ - id const p = _v[@"height"]; - return RCTBridgingToDouble(p); -} -inline JS::NativeStatusBarManagerIOS::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto HEIGHT = i.HEIGHT.get(); - d[@"HEIGHT"] = @(HEIGHT); - auto DEFAULT_BACKGROUND_COLOR = i.DEFAULT_BACKGROUND_COLOR; - d[@"DEFAULT_BACKGROUND_COLOR"] = DEFAULT_BACKGROUND_COLOR.hasValue() ? @((double)DEFAULT_BACKGROUND_COLOR.value()) : nil; - return d; -}) {} -inline JS::NativeStatusBarManagerIOS::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeToastAndroid::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto SHORT = i.SHORT.get(); - d[@"SHORT"] = @(SHORT); - auto LONG = i.LONG.get(); - d[@"LONG"] = @(LONG); - auto TOP = i.TOP.get(); - d[@"TOP"] = @(TOP); - auto BOTTOM = i.BOTTOM.get(); - d[@"BOTTOM"] = @(BOTTOM); - auto CENTER = i.CENTER.get(); - d[@"CENTER"] = @(CENTER); - return d; -}) {} -inline JS::NativeToastAndroid::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline JS::NativeUIManager::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - return d; -}) {} -inline JS::NativeUIManager::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -inline id _Nullable JS::NativeWebSocketModule::SpecConnectOptions::headers() const -{ - id const p = _v[@"headers"]; - return p; -} diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 5ebd97a3d0298f..ee81537631cc14 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -21,6 +21,7 @@ export type ResolvedAssetSource = {| import type {PackagerAsset} from '@react-native/assets/registry'; const PixelRatio = require('../Utilities/PixelRatio'); +const {pickScale} = require('./AssetUtils'); const Platform = require('../Utilities/Platform'); const invariant = require('invariant'); @@ -35,7 +36,7 @@ const { * Returns a path like 'assets/AwesomeModule/icon@2x.png' */ function getScaledAssetPath(asset): string { - const scale = AssetSourceResolver.pickScale(asset.scales, PixelRatio.get()); + const scale = pickScale(asset.scales, PixelRatio.get()); const scaleSuffix = scale === 1 ? '' : '@' + scale + 'x'; const assetDir = getBasePath(asset); return assetDir + '/' + asset.name + scaleSuffix + '.' + asset.type; @@ -45,7 +46,7 @@ function getScaledAssetPath(asset): string { * Returns a path like 'drawable-mdpi/icon.png' */ function getAssetPathInDrawableFolder(asset): string { - const scale = AssetSourceResolver.pickScale(asset.scales, PixelRatio.get()); + const scale = pickScale(asset.scales, PixelRatio.get()); const drawbleFolder = getAndroidResourceFolderName(asset, scale); const fileName = getAndroidResourceIdentifier(asset); return drawbleFolder + '/' + fileName + '.' + asset.type; @@ -154,23 +155,14 @@ class AssetSourceResolver { width: this.asset.width, height: this.asset.height, uri: source, - scale: AssetSourceResolver.pickScale(this.asset.scales, PixelRatio.get()), + scale: pickScale(this.asset.scales, PixelRatio.get()), }; } - static pickScale(scales: Array, deviceScale: number): number { - // Packager guarantees that `scales` array is sorted - for (let i = 0; i < scales.length; i++) { - if (scales[i] >= deviceScale) { - return scales[i]; - } - } - - // If nothing matches, device scale is larger than any available - // scales, so we return the biggest one. Unless the array is empty, - // in which case we default to 1 - return scales[scales.length - 1] || 1; - } + static pickScale: ( + scales: Array, + deviceScale?: number, + ) => number = pickScale; } module.exports = AssetSourceResolver; diff --git a/Libraries/Image/AssetUtils.js b/Libraries/Image/AssetUtils.js new file mode 100644 index 00000000000000..44c59ec5b85a0d --- /dev/null +++ b/Libraries/Image/AssetUtils.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import PixelRatio from '../Utilities/PixelRatio'; + +let cacheBreaker; +let warnIfCacheBreakerUnset = true; + +export function pickScale(scales: Array, deviceScale?: number): number { + if (deviceScale == null) { + deviceScale = PixelRatio.get(); + } + // Packager guarantees that `scales` array is sorted + for (let i = 0; i < scales.length; i++) { + if (scales[i] >= deviceScale) { + return scales[i]; + } + } + + // If nothing matches, device scale is larger than any available + // scales, so we return the biggest one. Unless the array is empty, + // in which case we default to 1 + return scales[scales.length - 1] || 1; +} + +export function setUrlCacheBreaker(appendage: string) { + cacheBreaker = appendage; +} + +export function getUrlCacheBreaker(): string { + if (cacheBreaker == null) { + if (__DEV__ && warnIfCacheBreakerUnset) { + warnIfCacheBreakerUnset = false; + console.warn( + 'AssetUtils.getUrlCacheBreaker: Cache breaker value is unset', + ); + } + return ''; + } + return cacheBreaker; +} diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 5e57732a855424..90b1a2652e7e0c 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -194,6 +194,16 @@ function getSizeWithHeaders( ); } +function prefetchWithMetadata( + url: string, + queryRootName: string, + rootTag?: ?number, + callback: ?Function, +): any { + // TODO: T79192300 Log queryRootName and rootTag + prefetch(url, callback); +} + function prefetch(url: string, callback: ?Function): any { const requestId = generateRequestId(); callback && callback(requestId); @@ -219,6 +229,7 @@ type ImageComponentStatics = $ReadOnly<{| getSize: typeof getSize, getSizeWithHeaders: typeof getSizeWithHeaders, prefetch: typeof prefetch, + prefetchWithMetadata: typeof prefetchWithMetadata, abortPrefetch: typeof abortPrefetch, queryCache: typeof queryCache, resolveAssetSource: typeof resolveAssetSource, @@ -358,6 +369,17 @@ Image.getSizeWithHeaders = getSizeWithHeaders; * comment and run Flow. */ Image.prefetch = prefetch; +/** + * Prefetches a remote image for later use by downloading it to the disk + * cache, and adds metadata for queryRootName and rootTag. + * + * See https://reactnative.dev/docs/image.html#prefetch + */ +/* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.prefetchWithMetadata = prefetchWithMetadata; + /** * Abort prefetch request. * diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index e5ff46e73827bf..48b9c398717802 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -59,6 +59,23 @@ function getSizeWithHeaders( ); } +function prefetchWithMetadata( + url: string, + queryRootName: string, + rootTag?: ?number, +): any { + if (NativeImageLoaderIOS.prefetchImageWithMetadata) { + // number params like rootTag cannot be nullable before TurboModules is available + return NativeImageLoaderIOS.prefetchImageWithMetadata( + url, + queryRootName, + rootTag ? rootTag : 0, + ); + } else { + return NativeImageLoaderIOS.prefetchImage(url); + } +} + function prefetch(url: string): any { return NativeImageLoaderIOS.prefetchImage(url); } @@ -73,6 +90,7 @@ type ImageComponentStatics = $ReadOnly<{| getSize: typeof getSize, getSizeWithHeaders: typeof getSizeWithHeaders, prefetch: typeof prefetch, + prefetchWithMetadata: typeof prefetchWithMetadata, queryCache: typeof queryCache, resolveAssetSource: typeof resolveAssetSource, propTypes: typeof DeprecatedImagePropType, @@ -181,6 +199,17 @@ Image.getSizeWithHeaders = getSizeWithHeaders; * comment and run Flow. */ Image.prefetch = prefetch; +/** + * Prefetches a remote image for later use by downloading it to the disk + * cache, and adds metadata for queryRootName and rootTag. + * + * See https://reactnative.dev/docs/image.html#prefetch + */ +/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an + * error found when Flow v0.89 was deployed. To see the error, delete this + * comment and run Flow. */ +Image.prefetchWithMetadata = prefetchWithMetadata; + /** * Performs cache interrogation. * diff --git a/Libraries/Image/ImageAnalyticsTagContext.js b/Libraries/Image/ImageAnalyticsTagContext.js index ea458bf0c28043..540ae6c02db72d 100644 --- a/Libraries/Image/ImageAnalyticsTagContext.js +++ b/Libraries/Image/ImageAnalyticsTagContext.js @@ -18,4 +18,8 @@ const Context: React.Context = React.createContext( null, ); +if (__DEV__) { + Context.displayName = 'ImageAnalyticsTagContext'; +} + export default Context; diff --git a/Libraries/Image/ImageViewNativeComponent.js b/Libraries/Image/ImageViewNativeComponent.js index 8a6c0b25aab2e4..b6ba39c8a16536 100644 --- a/Libraries/Image/ImageViewNativeComponent.js +++ b/Libraries/Image/ImageViewNativeComponent.js @@ -4,26 +4,24 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format * @flow strict-local + * @format */ 'use strict'; -const requireNativeComponent = require('../ReactNative/requireNativeComponent'); - -import type {DangerouslyImpreciseStyle} from '../StyleSheet/StyleSheet'; import type {ResolvedAssetSource} from './AssetSourceResolver'; -import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; import type {ImageProps} from './ImageProps'; import type {ViewProps} from '../Components/View/ViewPropTypes'; -import type {ImageStyleProp} from '../StyleSheet/StyleSheet'; -import type {ColorValue} from '../StyleSheet/StyleSheet'; - -import ImageViewViewConfig from './ImageViewViewConfig'; -const ReactNativeViewConfigRegistry = require('../Renderer/shims/ReactNativeViewConfigRegistry'); +import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry'; +import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; +import type { + ColorValue, + DangerouslyImpreciseStyle, + ImageStyleProp, +} from '../StyleSheet/StyleSheet'; -type NativeProps = $ReadOnly<{| +type Props = $ReadOnly<{ ...ImageProps, ...ViewProps, @@ -38,19 +36,66 @@ type NativeProps = $ReadOnly<{| headers?: ?string, defaultSrc?: ?string, loadingIndicatorSrc?: ?string, -|}>; - -let ImageViewNativeComponent; -if (global.RN$Bridgeless) { - ReactNativeViewConfigRegistry.register('RCTImageView', () => { - return ImageViewViewConfig; - }); - ImageViewNativeComponent = 'RCTImageView'; -} else { - ImageViewNativeComponent = requireNativeComponent( - 'RCTImageView', - ); -} - -// flowlint-next-line unclear-type:off -export default ((ImageViewNativeComponent: any): HostComponent); +}>; + +const ImageViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTImageView', + () => ({ + uiViewClassName: 'RCTImageView', + bubblingEventTypes: {}, + directEventTypes: { + topLoadStart: { + registrationName: 'onLoadStart', + }, + topProgress: { + registrationName: 'onProgress', + }, + topError: { + registrationName: 'onError', + }, + topPartialLoad: { + registrationName: 'onPartialLoad', + }, + topLoad: { + registrationName: 'onLoad', + }, + topLoadEnd: { + registrationName: 'onLoadEnd', + }, + }, + validAttributes: { + blurRadius: true, + capInsets: { + diff: require('../Utilities/differ/insetsDiffer'), + }, + defaultSource: { + process: require('./resolveAssetSource'), + }, + defaultSrc: true, + fadeDuration: true, + headers: true, + internal_analyticTag: true, + loadingIndicatorSrc: true, + onError: true, + onLoad: true, + onLoadEnd: true, + onLoadStart: true, + onPartialLoad: true, + onProgress: true, + overlayColor: { + process: require('../StyleSheet/processColor'), + }, + progressiveRenderingEnabled: true, + resizeMethod: true, + resizeMode: true, + shouldNotifyLoadEvents: true, + source: true, + src: true, + tintColor: { + process: require('../StyleSheet/processColor'), + }, + }, + }), +); + +export default ImageViewNativeComponent; diff --git a/Libraries/Image/ImageViewViewConfig.js b/Libraries/Image/ImageViewViewConfig.js deleted file mode 100644 index 5870038e97d584..00000000000000 --- a/Libraries/Image/ImageViewViewConfig.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import ReactNativeViewViewConfig from '../Components/View/ReactNativeViewViewConfig'; -import type {ReactNativeBaseComponentViewConfig} from '../Renderer/shims/ReactNativeTypes'; - -const ImageViewViewConfig = { - uiViewClassName: 'RCTImageView', - bubblingEventTypes: {}, - directEventTypes: { - topLoadStart: { - registrationName: 'onLoadStart', - }, - topProgress: { - registrationName: 'onProgress', - }, - topError: { - registrationName: 'onError', - }, - topPartialLoad: { - registrationName: 'onPartialLoad', - }, - topLoad: { - registrationName: 'onLoad', - }, - topLoadEnd: { - registrationName: 'onLoadEnd', - }, - }, - validAttributes: { - ...ReactNativeViewViewConfig.validAttributes, - blurRadius: true, - // flowlint-next-line unclear-type:off - capInsets: {diff: (require('../Utilities/differ/insetsDiffer'): any)}, - defaultSource: { - process: require('./resolveAssetSource'), - }, - defaultSrc: true, - fadeDuration: true, - headers: true, - loadingIndicatorSrc: true, - onError: true, - onLoad: true, - onLoadEnd: true, - onLoadStart: true, - onPartialLoad: true, - onProgress: true, - overlayColor: {process: require('../StyleSheet/processColor')}, - progressiveRenderingEnabled: true, - resizeMethod: true, - resizeMode: true, - shouldNotifyLoadEvents: true, - source: true, - src: true, - tintColor: {process: require('../StyleSheet/processColor')}, - }, -}; - -module.exports = (ImageViewViewConfig: ReactNativeBaseComponentViewConfig<>); diff --git a/Libraries/Image/NativeImageLoaderIOS.js b/Libraries/Image/NativeImageLoaderIOS.js index 842294d0af2a75..d0cf74846cfc45 100644 --- a/Libraries/Image/NativeImageLoaderIOS.js +++ b/Libraries/Image/NativeImageLoaderIOS.js @@ -26,6 +26,11 @@ export interface Spec extends TurboModule { ... }>; +prefetchImage: (uri: string) => Promise; + +prefetchImageWithMetadata?: ( + uri: string, + queryRootName: string, + rootTag: number, + ) => Promise; +queryCache: (uris: Array) => Promise; } diff --git a/Libraries/Image/NativeImageStoreAndroid.js b/Libraries/Image/NativeImageStoreAndroid.js new file mode 100644 index 00000000000000..8ab6dc7c1a2315 --- /dev/null +++ b/Libraries/Image/NativeImageStoreAndroid.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {||}; + +getBase64ForTag: ( + uri: string, + successCallback: (base64ImageData: string) => void, + errorCallback: (error: string) => void, + ) => void; +} + +export default (TurboModuleRegistry.getEnforcing( + 'ImageStoreManager', +): Spec); diff --git a/Libraries/Image/NativeImageStore.js b/Libraries/Image/NativeImageStoreIOS.js similarity index 75% rename from Libraries/Image/NativeImageStore.js rename to Libraries/Image/NativeImageStoreIOS.js index 38603b6aaab2cf..d94f1ef4f35095 100644 --- a/Libraries/Image/NativeImageStore.js +++ b/Libraries/Image/NativeImageStoreIOS.js @@ -15,21 +15,11 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => {||}; - // Common +getBase64ForTag: ( uri: string, successCallback: (base64ImageData: string) => void, - - /** - * On Android, the failure callback is called with a string. - * On iOS, the failure callback is called with an error object. - * - * TODO(T47527939) Unify this inconsistency - */ - errorCallback: (error: {|message: string|} | string) => void, + errorCallback: (error: {|message: string|}) => void, ) => void; - - // iOS-only +hasImageForTag: (uri: string, callback: (hasImage: boolean) => void) => void; +removeImageForTag: (uri: string) => void; +addImageFromBase64: ( diff --git a/Libraries/Image/RCTAnimatedImage.m b/Libraries/Image/RCTAnimatedImage.m index 978fc2e905d7c3..85bf09e05d37c2 100644 --- a/Libraries/Image/RCTAnimatedImage.m +++ b/Libraries/Image/RCTAnimatedImage.m @@ -87,9 +87,12 @@ - (NSUInteger)imageLoopCountWithSource:(CGImageSourceRef)source NSNumber *gifLoopCount = gifProperties[(__bridge NSString *)kCGImagePropertyGIFLoopCount]; if (gifLoopCount != nil) { loopCount = gifLoopCount.unsignedIntegerValue; - // A loop count of 1 means it should repeat twice, 2 means, thrice, etc. - if (loopCount != 0) { - loopCount++; + if (@available(iOS 14, *)) { + } else { + // A loop count of 1 means it should animate twice, 2 means, thrice, etc. + if (loopCount != 0) { + loopCount++; + } } } } diff --git a/Libraries/Image/RCTImageBlurUtils.m b/Libraries/Image/RCTImageBlurUtils.m index 72e60af696214b..3ba8c64eac85d6 100644 --- a/Libraries/Image/RCTImageBlurUtils.m +++ b/Libraries/Image/RCTImageBlurUtils.m @@ -34,12 +34,13 @@ buffer1.rowBytes = buffer2.rowBytes = CGImageGetBytesPerRow(imageRef); size_t bytes = buffer1.rowBytes * buffer1.height; buffer1.data = malloc(bytes); + if (!buffer1.data) { + return inputImage; + } 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(); + if (!buffer2.data) { + free(buffer1.data); + return inputImage; } // A description of how to compute the box kernel width from the Gaussian @@ -49,13 +50,18 @@ boxSize |= 1; // Ensure boxSize is odd //create temp buffer - void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, - NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); + vImage_Error tempBufferSize = vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, + NULL, kvImageGetTempBufferSize | kvImageEdgeExtend); + if (tempBufferSize < 0) { + free(buffer1.data); + free(buffer2.data); + return inputImage; + } + void *tempBuffer = malloc(tempBufferSize); 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(); + free(buffer1.data); + free(buffer2.data); + return inputImage; } //copy image data diff --git a/Libraries/Image/RCTImageEditingManager.mm b/Libraries/Image/RCTImageEditingManager.mm index 650362d81d412d..47b2f60f849762 100644 --- a/Libraries/Image/RCTImageEditingManager.mm +++ b/Libraries/Image/RCTImageEditingManager.mm @@ -26,7 +26,7 @@ @implementation RCTImageEditingManager RCT_EXPORT_MODULE() -@synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; /** * Crops an image and adds the result to the image store. @@ -53,11 +53,11 @@ @implementation RCTImageEditingManager @"height": @(cropData.size().height()), }] }; - + // We must keep a copy of cropData so that we can access data from it at a later time JS::NativeImageEditor::Options cropDataCopy = cropData; - [[_bridge moduleForName:@"ImageLoader" lazilyLoadIfNecessary:YES] + [[_moduleRegistry moduleForName:"ImageLoader"] loadImageWithURLRequest:imageRequest callback:^(NSError *error, UIImage *image) { if (error) { errorCallback(@[RCTJSErrorFromNSError(error)]); @@ -80,7 +80,7 @@ @implementation RCTImageEditingManager } // Store image - [self->_bridge.imageStoreManager storeImage:croppedImage withBlock:^(NSString *croppedImageTag) { + [[self->_moduleRegistry moduleForName:"ImageStoreManager"] storeImage:croppedImage withBlock:^(NSString *croppedImageTag) { if (!croppedImageTag) { NSString *errorMessage = @"Error storing cropped image in RCTImageStoreManager"; RCTLogWarn(@"%@", errorMessage); diff --git a/Libraries/Image/RCTImageLoader.h b/Libraries/Image/RCTImageLoader.h index ca9f8bd9928836..b7040e1a4c77d0 100644 --- a/Libraries/Image/RCTImageLoader.h +++ b/Libraries/Image/RCTImageLoader.h @@ -15,8 +15,9 @@ #import #import #import +#import -@interface RCTImageLoader : NSObject +@interface RCTImageLoader : NSObject - (instancetype)init; - (instancetype)initWithRedirectDelegate:(id)redirectDelegate NS_DESIGNATED_INITIALIZER; - (instancetype)initWithRedirectDelegate:(id)redirectDelegate diff --git a/Libraries/Image/RCTImageLoader.mm b/Libraries/Image/RCTImageLoader.mm index 635f89d22deb7a..757b17f8d1309a 100644 --- a/Libraries/Image/RCTImageLoader.mm +++ b/Libraries/Image/RCTImageLoader.mm @@ -38,6 +38,18 @@ void RCTEnableImageLoadingPerfInstrumentation(BOOL enabled) imagePerfInstrumentationEnabled = enabled; } +static BOOL (^getImagePerfInstrumentationForFabricEnabled)() = (^BOOL () { + return NO; +}); + +BOOL RCTGetImageLoadingPerfInstrumentationForFabricEnabled() { + return getImagePerfInstrumentationForFabricEnabled(); +} + +void RCTSetImageLoadingPerfInstrumentationForFabricEnabledBlock(BOOL (^getMobileConfigEnabled)()) { + getImagePerfInstrumentationForFabricEnabled = getMobileConfigEnabled; +} + static NSInteger RCTImageBytesForImage(UIImage *image) { NSInteger singleImageBytes = image.size.width * image.size.height * image.scale * image.scale * 4; @@ -92,14 +104,15 @@ @implementation RCTImageLoader NSMutableArray *_pendingDecodes; NSInteger _scheduledDecodes; NSUInteger _activeBytes; + std::mutex _loadersMutex; __weak id _redirectDelegate; } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; @synthesize maxConcurrentLoadingTasks = _maxConcurrentLoadingTasks; @synthesize maxConcurrentDecodingTasks = _maxConcurrentDecodingTasks; @synthesize maxConcurrentDecodingBytes = _maxConcurrentDecodingBytes; -@synthesize turboModuleRegistry = _turboModuleRegistry; RCT_EXPORT_MODULE() @@ -172,26 +185,29 @@ - (void)setImageCache:(id)cache } if (!_loaders) { - // Get loaders, sorted in reverse priority order (highest priority first) - - if (_loadersProvider) { - _loaders = _loadersProvider(); - } else { - RCTAssert(_bridge, @"Trying to find RCTImageURLLoaders and bridge not set."); - _loaders = [_bridge modulesConformingToProtocol:@protocol(RCTImageURLLoader)]; - } + std::unique_lock guard(_loadersMutex); + if (!_loaders) { - _loaders = [_loaders sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { - float priorityA = [a respondsToSelector:@selector(loaderPriority)] ? [a loaderPriority] : 0; - float priorityB = [b respondsToSelector:@selector(loaderPriority)] ? [b loaderPriority] : 0; - if (priorityA > priorityB) { - return NSOrderedAscending; - } else if (priorityA < priorityB) { - return NSOrderedDescending; + // Get loaders, sorted in reverse priority order (highest priority first) + if (_loadersProvider) { + _loaders = _loadersProvider(); } else { - return NSOrderedSame; + RCTAssert(_bridge, @"Trying to find RCTImageURLLoaders and bridge not set."); + _loaders = [_bridge modulesConformingToProtocol:@protocol(RCTImageURLLoader)]; } - }]; + + _loaders = [_loaders sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { + float priorityA = [a respondsToSelector:@selector(loaderPriority)] ? [a loaderPriority] : 0; + float priorityB = [b respondsToSelector:@selector(loaderPriority)] ? [b loaderPriority] : 0; + if (priorityA > priorityB) { + return NSOrderedAscending; + } else if (priorityA < priorityB) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + } } if (RCT_DEBUG) { @@ -247,7 +263,7 @@ - (void)setImageCache:(id)cache _decoders = [_bridge modulesConformingToProtocol:@protocol(RCTImageDataDecoder)]; } - _decoders = [[_bridge modulesConformingToProtocol:@protocol(RCTImageDataDecoder)] sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { + _decoders = [_decoders sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { float priorityA = [a respondsToSelector:@selector(decoderPriority)] ? [a decoderPriority] : 0; float priorityB = [b respondsToSelector:@selector(decoderPriority)] ? [b decoderPriority] : 0; if (priorityA > priorityB) { @@ -375,7 +391,9 @@ - (nullable RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLReques attribution:{} progressBlock:progressBlock partialLoadBlock:partialLoadBlock - completionBlock:completionBlock]; + completionBlock:^(NSError *error, UIImage *image, id metadata) { + completionBlock(error, image); + }]; return ^{ [request cancel]; }; @@ -457,7 +475,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req attribution:(const ImageURLLoaderAttribution &)attribution progressBlock:(RCTImageLoaderProgressBlock)progressHandler partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadHandler - completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response))completionBlock + completionBlock:(void (^)(NSError *error, id imageOrData, id imageMetadata, BOOL cacheResult, NSURLResponse *response))completionBlock { { NSMutableURLRequest *mutableRequest = [request mutableCopy]; @@ -491,7 +509,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req __block NSLock *cancelLoadLock = [NSLock new]; NSString *requestId = [NSString stringWithFormat:@"%@-%llu",[[NSUUID UUID] UUIDString], monotonicTimeGetCurrentNanoseconds()]; - void (^completionHandler)(NSError *, id, NSURLResponse *) = ^(NSError *error, id imageOrData, NSURLResponse *response) { + void (^completionHandler)(NSError *, id, id, NSURLResponse *) = ^(NSError *error, id imageOrData, id imageMetadata, NSURLResponse *response) { [cancelLoadLock lock]; cancelLoad = nil; [cancelLoadLock unlock]; @@ -503,11 +521,11 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req // expecting it, and may do expensive post-processing in the callback dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (!std::atomic_load(cancelled.get())) { - completionBlock(error, imageOrData, cacheResult, response); + completionBlock(error, imageOrData, imageMetadata, cacheResult, response); } }); } else if (!std::atomic_load(cancelled.get())) { - completionBlock(error, imageOrData, cacheResult, response); + completionBlock(error, imageOrData, imageMetadata, cacheResult, response); } }; @@ -524,8 +542,8 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req attribution:attributionCopy progressHandler:progressHandler partialLoadHandler:partialLoadHandler - completionHandler:^(NSError *error, UIImage *image) { - completionHandler(error, image, nil); + completionHandler:^(NSError *error, UIImage *image, id metadata) { + completionHandler(error, image, metadata, nil); }]; } RCTImageLoaderCancellationBlock cb = [loadHandler loadImageForURL:request.URL @@ -535,7 +553,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req progressHandler:progressHandler partialLoadHandler:partialLoadHandler completionHandler:^(NSError *error, UIImage *image) { - completionHandler(error, image, nil); + completionHandler(error, image, nil, nil); }]; return [[RCTImageURLLoaderRequest alloc] initWithRequestId:nil imageURL:request.URL cancellationBlock:cb]; } @@ -564,8 +582,8 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req attribution:attributionCopy progressHandler:progressHandler partialLoadHandler:partialLoadHandler - completionHandler:^(NSError *error, UIImage *image) { - completionHandler(error, image, nil); + completionHandler:^(NSError *error, UIImage *image, id metadata) { + completionHandler(error, image, metadata, nil); }]; cancelLoadLocal = loaderRequest.cancellationBlock; } else { @@ -576,7 +594,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req progressHandler:progressHandler partialLoadHandler:partialLoadHandler completionHandler:^(NSError *error, UIImage *image) { - completionHandler(error, image, nil); + completionHandler(error, image, nil, nil); }]; } [cancelLoadLock lock]; @@ -592,12 +610,14 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req } if (image) { - completionHandler(nil, image, nil); + completionHandler(nil, image, nil, nil); } else { // Use networking module to load image dispatch_block_t cancelLoadLocal = [strongSelf _loadURLRequest:request progressBlock:progressHandler - completionBlock:completionHandler]; + completionBlock:^(NSError *error, id imageOrData, NSURLResponse *response) { + completionHandler(error, imageOrData, nil, response); + }]; [cancelLoadLock lock]; cancelLoad = cancelLoadLocal; [cancelLoadLock unlock]; @@ -624,20 +644,14 @@ - (RCTImageLoaderCancellationBlock)_loadURLRequest:(NSURLRequest *)request progressBlock:(RCTImageLoaderProgressBlock)progressHandler completionBlock:(void (^)(NSError *error, id imageOrData, NSURLResponse *response))completionHandler { - // Check if networking module is available - if (RCT_DEBUG && ![_bridge respondsToSelector:@selector(networking)] - && ![_turboModuleRegistry moduleForName:"RCTNetworking"]) { + RCTNetworking *networking = [_moduleRegistry moduleForName:"Networking"]; + if (RCT_DEBUG && !networking) { RCTLogError(@"No suitable image URL loader found for %@. You may need to " " import the RCTNetwork library in order to load images.", request.URL.absoluteString); return NULL; } - RCTNetworking *networking = [_bridge networking]; - if (!networking) { - networking = [_turboModuleRegistry moduleForName:"RCTNetworking"]; - } - // Check if networking module can load image if (RCT_DEBUG && ![networking canHandleRequest:request]) { RCTLogError(@"No suitable image URL loader found for %@", request.URL.absoluteString); @@ -746,7 +760,7 @@ - (RCTImageURLLoaderRequest *)loadImageWithURLRequest:(NSURLRequest *)imageURLRe attribution:(const ImageURLLoaderAttribution &)attribution progressBlock:(RCTImageLoaderProgressBlock)progressBlock partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock - completionBlock:(RCTImageLoaderCompletionBlock)completionBlock + completionBlock:(RCTImageLoaderCompletionBlockWithMetadata)completionBlock { auto cancelled = std::make_shared>(0); __block dispatch_block_t cancelLoad = nil; @@ -766,7 +780,7 @@ - (RCTImageURLLoaderRequest *)loadImageWithURLRequest:(NSURLRequest *)imageURLRe }; __weak RCTImageLoader *weakSelf = self; - void (^completionHandler)(NSError *, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response) { + void (^completionHandler)(NSError *, id, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, id imageMetadata, BOOL cacheResult, NSURLResponse *response) { __typeof(self) strongSelf = weakSelf; if (std::atomic_load(cancelled.get()) || !strongSelf) { return; @@ -776,7 +790,7 @@ - (RCTImageURLLoaderRequest *)loadImageWithURLRequest:(NSURLRequest *)imageURLRe [cancelLoadLock lock]; cancelLoad = nil; [cancelLoadLock unlock]; - completionBlock(error, imageOrData); + completionBlock(error, imageOrData, imageMetadata); return; } @@ -793,7 +807,7 @@ - (RCTImageURLLoaderRequest *)loadImageWithURLRequest:(NSURLRequest *)imageURLRe [cancelLoadLock lock]; cancelLoad = nil; [cancelLoadLock unlock]; - completionBlock(error_, image); + completionBlock(error_, image, nil); }; dispatch_block_t cancelLoadLocal = [strongSelf decodeImageData:imageOrData size:size @@ -819,17 +833,12 @@ - (RCTImageURLLoaderRequest *)loadImageWithURLRequest:(NSURLRequest *)imageURLRe return [[RCTImageURLLoaderRequest alloc] initWithRequestId:loaderRequest.requestId imageURL:imageURLRequest.URL cancellationBlock:cancellationBlock]; } -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest -{ - if (!loaderRequest) { - return; - } - - // This delegate method is Fabric-only - id loadHandler = [self imageURLLoaderForURL:loaderRequest.imageURL]; - if ([loadHandler respondsToSelector:@selector(trackURLImageContentDidSetForRequest:)]) { - [(id)loadHandler trackURLImageContentDidSetForRequest:loaderRequest]; +- (BOOL)shouldEnablePerfLoggingForRequestUrl:(NSURL *)url { + id loadHandler = [self imageURLLoaderForURL:url]; + if ([loadHandler respondsToSelector:@selector(shouldEnablePerfLogging)]) { + return [(id)loadHandler shouldEnablePerfLogging]; } + return NO; } - (void)trackURLImageVisibilityForRequest:(RCTImageURLLoaderRequest *)loaderRequest imageView:(UIView *)imageView @@ -979,7 +988,7 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)data - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)imageURLRequest block:(void(^)(NSError *error, CGSize size))callback { - void (^completion)(NSError *, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response) { + void (^completion)(NSError *, id, id, BOOL, NSURLResponse *) = ^(NSError *error, id imageOrData, id imageMetadata, BOOL cacheResult, NSURLResponse *response) { CGSize size; if ([imageOrData isKindOfClass:[NSData class]]) { NSDictionary *meta = RCTGetImageMetadata(imageOrData); @@ -1181,11 +1190,30 @@ - (void)cancelRequest:(id)requestToken RCT_EXPORT_METHOD(prefetchImage:(NSString *)uri resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self prefetchImageWithMetadata:uri queryRootName:nil rootTag:0 resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(prefetchImageWithMetadata:(NSString *)uri + queryRootName:(NSString *)queryRootName + rootTag:(double)rootTag + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) { NSURLRequest *request = [RCTConvert NSURLRequest:uri]; [self loadImageWithURLRequest:request - priority:RCTImageLoaderPriorityPrefetch - callback:^(NSError *error, UIImage *image) { + size:CGSizeZero + scale:1 + clipped:YES + resizeMode:RCTResizeModeStretch + priority:RCTImageLoaderPriorityPrefetch + attribution:{ + .queryRootName = queryRootName ? [queryRootName UTF8String] : "", + .surfaceId = (int)rootTag, + } + progressBlock:nil + partialLoadBlock:nil + completionBlock:^(NSError *error, UIImage *image, id completionMetadata) { if (error) { reject(@"E_PREFETCH_FAILURE", nil, error); return; diff --git a/Libraries/Image/RCTImageLoaderLoggable.h b/Libraries/Image/RCTImageLoaderLoggable.h new file mode 100644 index 00000000000000..3b78c482bb5fa7 --- /dev/null +++ b/Libraries/Image/RCTImageLoaderLoggable.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * The image loader (i.e. RCTImageLoader) implement this to declare whether image performance should be logged. + */ +@protocol RCTImageLoaderLoggableProtocol + +/** + * Image instrumentation - declares whether its caller should log images + */ +- (BOOL)shouldEnablePerfLoggingForRequestUrl:(NSURL *)url; + +@end + +/** + * Image handlers in the image loader implement this to declare whether image performance should be logged. + */ +@protocol RCTImageLoaderLoggable + +/** + * Image instrumentation - declares whether its caller should log images + */ +- (BOOL)shouldEnablePerfLogging; + +@end diff --git a/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h b/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h index a862667623cb3a..25dc6c04882cd8 100644 --- a/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h +++ b/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h @@ -15,7 +15,10 @@ RCT_EXTERN BOOL RCTImageLoadingPerfInstrumentationEnabled(void); RCT_EXTERN void RCTEnableImageLoadingInstrumentation(BOOL enabled); RCT_EXTERN void RCTEnableImageLoadingPerfInstrumentation(BOOL enabled); -@protocol RCTImageLoaderWithAttributionProtocol +RCT_EXTERN BOOL RCTGetImageLoadingPerfInstrumentationForFabricEnabled(); +RCT_EXTERN void RCTSetImageLoadingPerfInstrumentationForFabricEnabledBlock(BOOL (^getEnabled)()); + +@protocol RCTImageLoaderWithAttributionProtocol // TODO (T61325135): Remove C++ checks #ifdef __cplusplus @@ -32,14 +35,9 @@ RCT_EXTERN void RCTEnableImageLoadingPerfInstrumentation(BOOL enabled); attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution progressBlock:(RCTImageLoaderProgressBlock)progressBlock partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock - completionBlock:(RCTImageLoaderCompletionBlock)completionBlock; + completionBlock:(RCTImageLoaderCompletionBlockWithMetadata)completionBlock; #endif -/** - * Image instrumentation - notify that the image content (UIImage) has been set on the native view. - */ -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest; - /** * Image instrumentation - start tracking the on-screen visibility of the native image view. */ diff --git a/Libraries/Image/RCTImageStoreManager.mm b/Libraries/Image/RCTImageStoreManager.mm index 907ecbbb6b0871..7eb3b1e91cc3d5 100644 --- a/Libraries/Image/RCTImageStoreManager.mm +++ b/Libraries/Image/RCTImageStoreManager.mm @@ -22,7 +22,7 @@ static NSString *const RCTImageStoreURLScheme = @"rct-image-store"; -@interface RCTImageStoreManager() +@interface RCTImageStoreManager() @end @implementation RCTImageStoreManager @@ -236,7 +236,7 @@ - (void)getImageForTag:(NSString *)imageTag withBlock:(void (^)(UIImage *image)) - (std::shared_ptr)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } @end diff --git a/Libraries/Image/RCTImageURLLoader.h b/Libraries/Image/RCTImageURLLoader.h index 866ae9ada61f09..e49ed1118f326f 100644 --- a/Libraries/Image/RCTImageURLLoader.h +++ b/Libraries/Image/RCTImageURLLoader.h @@ -15,6 +15,9 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^RCTImageLoaderProgressBlock)(int64_t progress, int64_t total); typedef void (^RCTImageLoaderPartialLoadBlock)(UIImage *image); typedef void (^RCTImageLoaderCompletionBlock)(NSError * _Nullable error, UIImage * _Nullable image); +// Metadata is passed as a id in an additional parameter because there are forks of RN without this parameter, +// and the complexity of RCTImageLoader would make using protocols here difficult to typecheck. +typedef void (^RCTImageLoaderCompletionBlockWithMetadata)(NSError * _Nullable error, UIImage * _Nullable image, id _Nullable metadata); typedef dispatch_block_t RCTImageLoaderCancellationBlock; /** diff --git a/Libraries/Image/RCTImageURLLoaderWithAttribution.h b/Libraries/Image/RCTImageURLLoaderWithAttribution.h index e5e8ca8484473b..118bed138057e9 100644 --- a/Libraries/Image/RCTImageURLLoaderWithAttribution.h +++ b/Libraries/Image/RCTImageURLLoaderWithAttribution.h @@ -7,6 +7,7 @@ #import #import +#import // TODO (T61325135): Remove C++ checks #ifdef __cplusplus @@ -16,6 +17,7 @@ namespace react { struct ImageURLLoaderAttribution { int32_t nativeViewTag = 0; int32_t surfaceId = 0; + std::string queryRootName; NSString *analyticTag; }; @@ -38,7 +40,7 @@ struct ImageURLLoaderAttribution { * Same as the RCTImageURLLoader interface, but allows passing in optional `attribution` information. * This is useful for per-app logging and other instrumentation. */ -@protocol RCTImageURLLoaderWithAttribution +@protocol RCTImageURLLoaderWithAttribution // TODO (T61325135): Remove C++ checks #ifdef __cplusplus @@ -55,14 +57,9 @@ struct ImageURLLoaderAttribution { attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution progressHandler:(RCTImageLoaderProgressBlock)progressHandler partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler - completionHandler:(RCTImageLoaderCompletionBlock)completionHandler; + completionHandler:(RCTImageLoaderCompletionBlockWithMetadata)completionHandler; #endif -/** - * Image instrumentation - notify that the image content (UIImage) has been set on the native view. - */ -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest; - /** * Image instrumentation - start tracking the on-screen visibility of the native image view. */ diff --git a/Libraries/Image/RCTImageView.mm b/Libraries/Image/RCTImageView.mm index c0b23f78f5ee0e..15609120223668 100644 --- a/Libraries/Image/RCTImageView.mm +++ b/Libraries/Image/RCTImageView.mm @@ -9,7 +9,6 @@ #import #import -#import #import #import #import @@ -332,7 +331,7 @@ - (void)reloadImage imageScale = source.scale; } - RCTImageLoaderCompletionBlock completionHandler = ^(NSError *error, UIImage *loadedImage) { + RCTImageLoaderCompletionBlockWithMetadata completionHandler = ^(NSError *error, UIImage *loadedImage, id metadata) { [weakSelf imageLoaderLoadedImage:loadedImage error:error forImageSource:source partial:NO]; }; diff --git a/Libraries/Image/React-RCTImage.podspec b/Libraries/Image/React-RCTImage.podspec index d0de0bd722e4e1..2678065c862b1e 100644 --- a/Libraries/Image/React-RCTImage.podspec +++ b/Libraries/Image/React-RCTImage.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/image" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/Image/__tests__/AssetUtils-test.js b/Libraries/Image/__tests__/AssetUtils-test.js new file mode 100644 index 00000000000000..c62e32d02c5b69 --- /dev/null +++ b/Libraries/Image/__tests__/AssetUtils-test.js @@ -0,0 +1,40 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @emails oncall+react_native + */ + +'use strict'; + +import {getUrlCacheBreaker, setUrlCacheBreaker} from '../AssetUtils'; + +describe('AssetUtils', () => { + afterEach(() => { + global.__DEV__ = true; + jest.clearAllMocks(); + }); + + it('should return empty string and warn once if no cacheBreaker set (DEV)', () => { + const mockWarn = jest.spyOn(console, 'warn'); + global.__DEV__ = true; + expect(getUrlCacheBreaker()).toEqual(''); + expect(getUrlCacheBreaker()).toEqual(''); + expect(mockWarn).toHaveBeenCalledTimes(1); + }); + + it('should return empty string if no cacheBreaker set in prod', () => { + const mockWarn = jest.spyOn(console, 'warn'); + global.__DEV__ = false; + expect(getUrlCacheBreaker()).toEqual(''); + expect(mockWarn).not.toHaveBeenCalled(); + }); + + it('should return set cacheBreaker value', () => { + setUrlCacheBreaker('my-cache-breaker-value'); + expect(getUrlCacheBreaker()).toEqual('my-cache-breaker-value'); + }); +}); diff --git a/Libraries/Image/resolveAssetSource.js b/Libraries/Image/resolveAssetSource.js index 71df2005163baa..fe8e543e1ff91e 100644 --- a/Libraries/Image/resolveAssetSource.js +++ b/Libraries/Image/resolveAssetSource.js @@ -14,6 +14,7 @@ const AssetRegistry = require('@react-native/assets/registry'); const AssetSourceResolver = require('./AssetSourceResolver'); +const {pickScale} = require('./AssetUtils'); import type {ResolvedAssetSource} from './AssetSourceResolver'; @@ -105,5 +106,5 @@ function resolveAssetSource(source: any): ?ResolvedAssetSource { } module.exports = resolveAssetSource; -module.exports.pickScale = AssetSourceResolver.pickScale; +module.exports.pickScale = pickScale; module.exports.setCustomSourceTransformer = setCustomSourceTransformer; diff --git a/Libraries/Inspector/Inspector.js b/Libraries/Inspector/Inspector.js index 2394a3dded98a1..470897d223bbca 100644 --- a/Libraries/Inspector/Inspector.js +++ b/Libraries/Inspector/Inspector.js @@ -14,10 +14,10 @@ const Dimensions = require('../Utilities/Dimensions'); const InspectorOverlay = require('./InspectorOverlay'); const InspectorPanel = require('./InspectorPanel'); const Platform = require('../Utilities/Platform'); +const PressabilityDebug = require('../Pressability/PressabilityDebug'); const React = require('react'); const ReactNative = require('../Renderer/shims/ReactNative'); const StyleSheet = require('../StyleSheet/StyleSheet'); -const Touchable = require('../Components/Touchable/Touchable'); const View = require('../Components/View/View'); const invariant = require('invariant'); @@ -279,7 +279,7 @@ class Inspector extends React.Component< } setTouchTargeting(val: boolean) { - Touchable.TOUCH_TARGET_DEBUG = val; + PressabilityDebug.setEnabled(val); this.props.onRequestRerenderApp(inspectedView => { this.setState({inspectedView}); }); @@ -318,7 +318,7 @@ class Inspector extends React.Component< hierarchy={this.state.hierarchy} selection={this.state.selection} setSelection={this.setSelection.bind(this)} - touchTargeting={Touchable.TOUCH_TARGET_DEBUG} + touchTargeting={PressabilityDebug.isEnabled()} setTouchTargeting={this.setTouchTargeting.bind(this)} networking={this.state.networking} setNetworking={this.setNetworking.bind(this)} diff --git a/Libraries/Inspector/PerformanceOverlay.js b/Libraries/Inspector/PerformanceOverlay.js index a7307bda9174a6..128abb43099330 100644 --- a/Libraries/Inspector/PerformanceOverlay.js +++ b/Libraries/Inspector/PerformanceOverlay.js @@ -22,7 +22,7 @@ class PerformanceOverlay extends React.Component<{...}> { const items = []; for (const key in perfLogs) { - if (perfLogs[key].totalTime) { + if (perfLogs[key]?.totalTime) { const unit = key === 'BundleSize' ? 'b' : 'ms'; items.push( diff --git a/Libraries/Interaction/InteractionManager.js b/Libraries/Interaction/InteractionManager.js index 8aec6727e33c8d..c2bf262a4014a7 100644 --- a/Libraries/Interaction/InteractionManager.js +++ b/Libraries/Interaction/InteractionManager.js @@ -21,7 +21,10 @@ import EventEmitter from '../vendor/emitter/EventEmitter'; export type Handle = number; import type {Task} from './TaskQueue'; -const _emitter = new EventEmitter(); +const _emitter = new EventEmitter<{ + interactionComplete: [], + interactionStart: [], +}>(); const DEBUG_DELAY: 0 = 0; const DEBUG: false = false; diff --git a/Libraries/Interaction/PanResponder.js b/Libraries/Interaction/PanResponder.js index 1aaf9fce9ecaee..4106597cb6d40c 100644 --- a/Libraries/Interaction/PanResponder.js +++ b/Libraries/Interaction/PanResponder.js @@ -121,7 +121,7 @@ const currentCentroidY = TouchHistoryMath.currentCentroidY; * ### Working Example * * To see it in action, try the - * [PanResponder example in RNTester](https://github.com/facebook/react-native/blob/master/RNTester/js/PanResponderExample.js) + * [PanResponder example in RNTester](https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js) */ export type GestureState = {| diff --git a/Libraries/Interaction/TaskQueue.js b/Libraries/Interaction/TaskQueue.js index 965953f64fb8d0..3fad71ae0a0d7c 100644 --- a/Libraries/Interaction/TaskQueue.js +++ b/Libraries/Interaction/TaskQueue.js @@ -156,6 +156,7 @@ class TaskQueue { // happens once it is fully processed. this._queueStack.push({tasks: [], popable: false}); const stackIdx = this._queueStack.length - 1; + const stackItem = this._queueStack[stackIdx]; DEBUG && infoLog('TaskQueue: push new queue: ', {stackIdx}); DEBUG && infoLog('TaskQueue: exec gen task ' + task.name); task @@ -166,7 +167,7 @@ class TaskQueue { stackIdx, queueStackSize: this._queueStack.length, }); - this._queueStack[stackIdx].popable = true; + stackItem.popable = true; this.hasTasksToProcess() && this._onMoreTasks(); }) .catch(ex => { diff --git a/Libraries/Interaction/__tests__/TaskQueue-test.js b/Libraries/Interaction/__tests__/TaskQueue-test.js index 5055fa2dde853b..aeed06ca0aeae6 100644 --- a/Libraries/Interaction/__tests__/TaskQueue-test.js +++ b/Libraries/Interaction/__tests__/TaskQueue-test.js @@ -150,4 +150,20 @@ describe('TaskQueue', () => { expect(task1).not.toBeCalled(); expect(taskQueue.hasTasksToProcess()).toBe(false); }); + + it('should not crash when task is cancelled between being started and resolved', () => { + const task1 = jest.fn(() => { + return new Promise(resolve => { + setTimeout(() => { + resolve(); + }, 1); + }); + }); + + taskQueue.enqueue({gen: task1, name: 'gen1'}); + taskQueue.processNext(); + taskQueue.cancelTasks([task1]); + + jest.runAllTimers(); + }); }); diff --git a/Libraries/Linking/Linking.js b/Libraries/Linking/Linking.js index 1ce5a8ae0795d0..5dd517f4db361a 100644 --- a/Libraries/Linking/Linking.js +++ b/Libraries/Linking/Linking.js @@ -13,8 +13,14 @@ import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import InteractionManager from '../Interaction/InteractionManager'; import Platform from '../Utilities/Platform'; -import NativeLinking from './NativeLinking'; +import NativeLinkingManager from './NativeLinkingManager'; +import NativeIntentAndroid from './NativeIntentAndroid'; import invariant from 'invariant'; +import nullthrows from 'nullthrows'; + +type LinkingEventDefinitions = { + url: [{url: string}], +}; /** * `Linking` gives you a general interface to interact with both incoming @@ -22,9 +28,9 @@ import invariant from 'invariant'; * * See https://reactnative.dev/docs/linking.html */ -class Linking extends NativeEventEmitter { +class Linking extends NativeEventEmitter { constructor() { - super(NativeLinking); + super(Platform.OS === 'ios' ? nullthrows(NativeLinkingManager) : undefined); } /** @@ -33,8 +39,12 @@ class Linking extends NativeEventEmitter { * * See https://reactnative.dev/docs/linking.html#addeventlistener */ - addEventListener(type: string, handler: T) { - this.addListener(type, handler); + addEventListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): void { + this.addListener(eventType, listener); } /** @@ -42,8 +52,11 @@ class Linking extends NativeEventEmitter { * * See https://reactnative.dev/docs/linking.html#removeeventlistener */ - removeEventListener(type: string, handler: T) { - this.removeListener(type, handler); + removeEventListener>( + eventType: K, + listener: (...$ElementType) => mixed, + ): void { + this.removeListener(eventType, listener); } /** @@ -53,7 +66,11 @@ class Linking extends NativeEventEmitter { */ openURL(url: string): Promise { this._validateURL(url); - return NativeLinking.openURL(url); + if (Platform.OS === 'android') { + return nullthrows(NativeIntentAndroid).openURL(url); + } else { + return nullthrows(NativeLinkingManager).openURL(url); + } } /** @@ -63,7 +80,11 @@ class Linking extends NativeEventEmitter { */ canOpenURL(url: string): Promise { this._validateURL(url); - return NativeLinking.canOpenURL(url); + if (Platform.OS === 'android') { + return nullthrows(NativeIntentAndroid).canOpenURL(url); + } else { + return nullthrows(NativeLinkingManager).canOpenURL(url); + } } /** @@ -72,7 +93,11 @@ class Linking extends NativeEventEmitter { * See https://reactnative.dev/docs/linking.html#opensettings */ openSettings(): Promise { - return NativeLinking.openSettings(); + if (Platform.OS === 'android') { + return nullthrows(NativeIntentAndroid).openSettings(); + } else { + return nullthrows(NativeLinkingManager).openSettings(); + } } /** @@ -84,9 +109,9 @@ class Linking extends NativeEventEmitter { getInitialURL(): Promise { return Platform.OS === 'android' ? InteractionManager.runAfterInteractions().then(() => - NativeLinking.getInitialURL(), + nullthrows(NativeIntentAndroid).getInitialURL(), ) - : NativeLinking.getInitialURL(); + : nullthrows(NativeLinkingManager).getInitialURL(); } /* @@ -105,9 +130,10 @@ class Linking extends NativeEventEmitter { }>, ): Promise { if (Platform.OS === 'android') { - return NativeLinking.sendIntent(action, extras); + return nullthrows(NativeIntentAndroid).sendIntent(action, extras); + } else { + return new Promise((resolve, reject) => reject(new Error('Unsupported'))); } - return new Promise((resolve, reject) => reject(new Error('Unsupported'))); } _validateURL(url: string) { diff --git a/Libraries/Linking/NativeLinking.js b/Libraries/Linking/NativeIntentAndroid.js similarity index 68% rename from Libraries/Linking/NativeLinking.js rename to Libraries/Linking/NativeIntentAndroid.js index 942aa4f01b8b9b..b5d61e975d4def 100644 --- a/Libraries/Linking/NativeLinking.js +++ b/Libraries/Linking/NativeIntentAndroid.js @@ -12,16 +12,12 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; -import Platform from '../Utilities/Platform'; export interface Spec extends TurboModule { - // Common interface +getInitialURL: () => Promise; +canOpenURL: (url: string) => Promise; +openURL: (url: string) => Promise; +openSettings: () => Promise; - - // Android only +sendIntent: ( action: string, extras: ?Array<{ @@ -30,12 +26,6 @@ export interface Spec extends TurboModule { ... }>, ) => Promise; - - // Events - +addListener: (eventName: string) => void; - +removeListeners: (count: number) => void; } -export default ((Platform.OS === 'android' - ? TurboModuleRegistry.getEnforcing('IntentAndroid') - : TurboModuleRegistry.getEnforcing('LinkingManager')): Spec); +export default (TurboModuleRegistry.get('IntentAndroid'): ?Spec); diff --git a/Libraries/Linking/NativeLinkingManager.js b/Libraries/Linking/NativeLinkingManager.js new file mode 100644 index 00000000000000..95a93817c32233 --- /dev/null +++ b/Libraries/Linking/NativeLinkingManager.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + // Common interface + +getInitialURL: () => Promise; + +canOpenURL: (url: string) => Promise; + +openURL: (url: string) => Promise; + +openSettings: () => Promise; + + // Events + +addListener: (eventName: string) => void; + +removeListeners: (count: number) => void; +} + +export default (TurboModuleRegistry.get('LinkingManager'): ?Spec); diff --git a/Libraries/LinkingIOS/RCTLinkingManager.mm b/Libraries/LinkingIOS/RCTLinkingManager.mm index b1171f6ecae8ce..2d96001cb520d8 100644 --- a/Libraries/LinkingIOS/RCTLinkingManager.mm +++ b/Libraries/LinkingIOS/RCTLinkingManager.mm @@ -9,7 +9,6 @@ #import #import -#import #import #import @@ -25,7 +24,7 @@ static void postNotificationWithURL(NSURL *URL, id sender) userInfo:payload]; } -@interface RCTLinkingManager() +@interface RCTLinkingManager() @end @implementation RCTLinkingManager @@ -188,7 +187,7 @@ - (void)handleOpenURLNotification:(NSNotification *)notification - (std::shared_ptr)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } @end diff --git a/Libraries/LinkingIOS/React-RCTLinking.podspec b/Libraries/LinkingIOS/React-RCTLinking.podspec index 5f07abebc676a3..fe2c5d33079dec 100644 --- a/Libraries/LinkingIOS/React-RCTLinking.podspec +++ b/Libraries/LinkingIOS/React-RCTLinking.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/linking" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index d72228d33ceaa2..ed836c3dfde3d5 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -19,8 +19,8 @@ const StyleSheet = require('../StyleSheet/StyleSheet'); const invariant = require('invariant'); +import typeof ScrollViewNativeComponent from '../Components/ScrollView/ScrollViewNativeComponent'; import {type ScrollResponderType} from '../Components/ScrollView/ScrollView'; -import type {ScrollViewNativeComponentType} from '../Components/ScrollView/ScrollViewNativeComponentType.js'; import type {ViewStyleProp} from '../StyleSheet/StyleSheet'; import type { ViewToken, @@ -373,7 +373,7 @@ class FlatList extends React.PureComponent, void> { */ getNativeScrollRef(): | ?React.ElementRef - | ?React.ElementRef { + | ?React.ElementRef { if (this._listRef) { return this._listRef.getScrollRef(); } @@ -511,9 +511,12 @@ class FlatList extends React.PureComponent, void> { 'array with 1-%s columns; instead, received a single item.', numColumns, ); - return items - .map((it, kk) => keyExtractor(it, index * numColumns + kk)) - .join(':'); + return ( + items + // $FlowFixMe[incompatible-call] + .map((it, kk) => keyExtractor(it, index * numColumns + kk)) + .join(':') + ); } else { // $FlowFixMe Can't call keyExtractor with an array return keyExtractor(items, index); @@ -575,6 +578,7 @@ class FlatList extends React.PureComponent, void> { // $FlowFixMe Component isn't valid return ; } else if (renderItem) { + // $FlowFixMe[incompatible-call] return renderItem(props); } else { return null; diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 2249d54c4aaa94..78939ed26af49a 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1061,6 +1061,7 @@ class VirtualizedList extends React.PureComponent { onScroll: this._onScroll, onScrollBeginDrag: this._onScrollBeginDrag, onScrollEndDrag: this._onScrollEndDrag, + onMomentumScrollBegin: this._onMomentumScrollBegin, onMomentumScrollEnd: this._onMomentumScrollEnd, scrollEventThrottle: this.props.scrollEventThrottle, // TODO: Android support invertStickyHeaders: @@ -1662,6 +1663,9 @@ class VirtualizedList extends React.PureComponent { }; _onScrollEndDrag = (e): void => { + this._nestedChildLists.forEach(childList => { + childList.ref && childList.ref._onScrollEndDrag(e); + }); const {velocity} = e.nativeEvent; if (velocity) { this._scrollMetrics.velocity = this._selectOffset(velocity); @@ -1670,7 +1674,17 @@ class VirtualizedList extends React.PureComponent { this.props.onScrollEndDrag && this.props.onScrollEndDrag(e); }; + _onMomentumScrollBegin = (e): void => { + this._nestedChildLists.forEach(childList => { + childList.ref && childList.ref._onMomentumScrollBegin(e); + }); + this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); + }; + _onMomentumScrollEnd = (e): void => { + this._nestedChildLists.forEach(childList => { + childList.ref && childList.ref._onMomentumScrollEnd(e); + }); this._scrollMetrics.velocity = 0; this._computeBlankness(); this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); diff --git a/Libraries/Lists/VirtualizedListContext.js b/Libraries/Lists/VirtualizedListContext.js index 130315a1b08d57..eddb578ed714c1 100644 --- a/Libraries/Lists/VirtualizedListContext.js +++ b/Libraries/Lists/VirtualizedListContext.js @@ -69,6 +69,9 @@ type Context = $ReadOnly<{ export const VirtualizedListContext: React.Context = React.createContext( null, ); +if (__DEV__) { + VirtualizedListContext.displayName = 'VirtualizedListContext'; +} /** * Resets the context. Intended for use by portal-like components (e.g. Modal). diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index 9c9d3e69bd8d1d..d783999955c23e 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -36,6 +36,7 @@ exports[`FlatList renders all the bells and whistles 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onRefresh={[MockFunction]} onScroll={[Function]} @@ -138,6 +139,7 @@ exports[`FlatList renders empty list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -166,6 +168,7 @@ exports[`FlatList renders null list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -207,6 +210,7 @@ exports[`FlatList renders simple list (multiple columns) 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -284,6 +288,7 @@ exports[`FlatList renders simple list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -351,6 +356,7 @@ exports[`FlatList renders simple list using ListItemComponent (multiple columns) onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -428,6 +434,7 @@ exports[`FlatList renders simple list using ListItemComponent 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} diff --git a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap index 49c4debe34392c..9cbbcbd2bec220 100644 --- a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap @@ -27,6 +27,7 @@ exports[`SectionList rendering empty section headers is fine 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -90,6 +91,7 @@ exports[`SectionList renders a footer when there is no data 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -145,6 +147,7 @@ exports[`SectionList renders a footer when there is no data and no header 1`] = onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -231,6 +234,7 @@ exports[`SectionList renders all the bells and whistles 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onRefresh={[MockFunction]} onScroll={[Function]} @@ -423,6 +427,7 @@ exports[`SectionList renders empty list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap index 86faf0fa8aa0cb..c666835c3fd638 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap @@ -22,6 +22,7 @@ exports[`VirtualizedList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -58,6 +59,7 @@ exports[`VirtualizedList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -111,6 +113,7 @@ exports[`VirtualizedList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -185,6 +188,7 @@ exports[`VirtualizedList handles separators correctly 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -266,6 +270,7 @@ exports[`VirtualizedList handles separators correctly 2`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -347,6 +352,7 @@ exports[`VirtualizedList handles separators correctly 3`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -441,6 +447,7 @@ exports[`VirtualizedList renders all the bells and whistles 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onRefresh={[MockFunction]} onScroll={[Function]} @@ -622,6 +629,7 @@ exports[`VirtualizedList renders empty list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -652,6 +660,7 @@ exports[`VirtualizedList renders empty list with empty component 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -698,6 +707,7 @@ exports[`VirtualizedList renders list with empty component 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -733,6 +743,7 @@ exports[`VirtualizedList renders null list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -772,6 +783,7 @@ exports[`VirtualizedList renders simple list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -837,6 +849,7 @@ exports[`VirtualizedList renders simple list using ListItemComponent 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -894,6 +907,7 @@ exports[`VirtualizedList test getItem functionality where data is not an Array 1 onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -937,6 +951,7 @@ exports[`VirtualizedList warns if both renderItem or ListItemComponent are speci onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap index 23e1317571b8ef..e53b506b0a4413 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap @@ -27,6 +27,7 @@ exports[`VirtualizedSectionList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -72,6 +73,7 @@ exports[`VirtualizedSectionList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -138,6 +140,7 @@ exports[`VirtualizedSectionList handles nested lists 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -242,6 +245,7 @@ exports[`VirtualizedSectionList handles separators correctly 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -381,6 +385,7 @@ exports[`VirtualizedSectionList handles separators correctly 2`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -520,6 +525,7 @@ exports[`VirtualizedSectionList handles separators correctly 3`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -672,6 +678,7 @@ exports[`VirtualizedSectionList renders all the bells and whistles 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onRefresh={[MockFunction]} onScroll={[Function]} @@ -893,6 +900,7 @@ exports[`VirtualizedSectionList renders empty list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -923,6 +931,7 @@ exports[`VirtualizedSectionList renders empty list with empty component 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -974,6 +983,7 @@ exports[`VirtualizedSectionList renders list with empty component 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -1017,6 +1027,7 @@ exports[`VirtualizedSectionList renders null list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} @@ -1061,6 +1072,7 @@ exports[`VirtualizedSectionList renders simple list 1`] = ` onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} + onMomentumScrollBegin={[Function]} onMomentumScrollEnd={[Function]} onScroll={[Function]} onScrollBeginDrag={[Function]} diff --git a/Libraries/Modal/Modal.js b/Libraries/Modal/Modal.js index 89523ad5d9bf61..9d1810741c239a 100644 --- a/Libraries/Modal/Modal.js +++ b/Libraries/Modal/Modal.js @@ -12,6 +12,9 @@ const AppContainer = require('../ReactNative/AppContainer'); const I18nManager = require('../ReactNative/I18nManager'); +import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; +import NativeModalManager from './NativeModalManager'; +const Platform = require('../Utilities/Platform'); const React = require('react'); const ScrollView = require('../Components/ScrollView/ScrollView'); const StyleSheet = require('../StyleSheet/StyleSheet'); @@ -26,6 +29,15 @@ import type {DirectEventHandler} from '../Types/CodegenTypes'; import {type EventSubscription} from '../vendor/emitter/EventEmitter'; import RCTModalHostView from './RCTModalHostViewNativeComponent'; +type ModalEventDefinitions = { + modalDismissed: [{modalID: number}], +}; + +const ModalEventEmitter = + Platform.OS === 'ios' && NativeModalManager != null + ? new NativeEventEmitter(NativeModalManager) + : null; + /** * The Modal component is a simple way to present content above an enclosing view. * @@ -161,9 +173,22 @@ class Modal extends React.Component { this._identifier = uniqueModalIdentifier++; } + componentDidMount() { + if (ModalEventEmitter) { + this._eventSubscription = ModalEventEmitter.addListener( + 'modalDismissed', + event => { + if (event.modalID === this._identifier && this.props.onDismiss) { + this.props.onDismiss(); + } + }, + ); + } + } + componentWillUnmount() { - if (this.props.onDismiss != null) { - this.props.onDismiss(); + if (this._eventSubscription) { + this._eventSubscription.remove(); } } diff --git a/Libraries/Modal/RCTModalHostViewNativeComponent.js b/Libraries/Modal/RCTModalHostViewNativeComponent.js index 62bd8a8daf144a..7d8151eae25df0 100644 --- a/Libraries/Modal/RCTModalHostViewNativeComponent.js +++ b/Libraries/Modal/RCTModalHostViewNativeComponent.js @@ -15,6 +15,7 @@ import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; import type { WithDefault, DirectEventHandler, + BubblingEventHandler, Int32, } from '../Types/CodegenTypes'; @@ -86,6 +87,14 @@ type NativeProps = $ReadOnly<{| */ onShow?: ?DirectEventHandler, + /** + * The `onDismiss` prop allows passing a function that will be called once + * the modal has been dismissed. + * + * See https://reactnative.dev/docs/modal.html#ondismiss + */ + onDismiss?: ?BubblingEventHandler, + /** * Deprecated. Use the `animationType` prop instead. */ diff --git a/Libraries/NativeAnimation/Drivers/RCTEventAnimation.h b/Libraries/NativeAnimation/Drivers/RCTEventAnimation.h index cd06b1697add18..c63c1f4c643c08 100644 --- a/Libraries/NativeAnimation/Drivers/RCTEventAnimation.h +++ b/Libraries/NativeAnimation/Drivers/RCTEventAnimation.h @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#import +#import #import "RCTValueAnimatedNode.h" diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.h b/Libraries/NativeAnimation/RCTNativeAnimatedModule.h index fde319b0eaef98..13b40fd8ae22c2 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.h +++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.h @@ -6,7 +6,7 @@ */ #import -#import +#import #import #import #import diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm b/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm index 35adf39289aa07..5d72181502cbb2 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm +++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm @@ -46,8 +46,9 @@ - (instancetype)init - (void)invalidate { + [super invalidate]; [_nodesManager stopAnimationLoop]; - [self.bridge.eventDispatcher removeDispatchObserver:self]; + [[self.moduleRegistry moduleForName:"EventDispatcher"] removeDispatchObserver:self]; [self.bridge.uiManager.observerCoordinator removeObserver:self]; [self.bridge.surfacePresenter removeObserver:self]; } @@ -64,11 +65,16 @@ - (void)setBridge:(RCTBridge *)bridge { [super setBridge:bridge]; _nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithBridge:self.bridge surfacePresenter:bridge.surfacePresenter]; - [bridge.eventDispatcher addDispatchObserver:self]; [bridge.uiManager.observerCoordinator addObserver:self]; [bridge.surfacePresenter addObserver:self]; } +- (void)setModuleRegistry:(RCTModuleRegistry *)moduleRegistry +{ + [super setModuleRegistry:moduleRegistry]; + [[moduleRegistry moduleForName:"EventDispatcher"] addDispatchObserver:self]; +} + /* * This selector should only be invoked in bridgeless mode, which is not compatible with this non turbo module. */ diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h index a3e350842683f4..be7445686931bd 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h @@ -9,6 +9,7 @@ #import #import #import +#import @protocol RCTValueAnimatedNodeObserver; diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h index 71f40200c2328f..2da04a1277eb1f 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h +++ b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h @@ -6,7 +6,7 @@ */ #import -#import +#import #import #import #import diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm index 6fc594872f874b..e491139a93fe05 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +++ b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm @@ -47,8 +47,9 @@ - (instancetype)init - (void)invalidate { + [super invalidate]; [_nodesManager stopAnimationLoop]; - [self.bridge.eventDispatcher removeDispatchObserver:self]; + [[self.moduleRegistry moduleForName:"EventDispatcher"] removeDispatchObserver:self]; [self.bridge.uiManager.observerCoordinator removeObserver:self]; [_surfacePresenter removeObserver:self]; } @@ -66,11 +67,16 @@ - (void)setBridge:(RCTBridge *)bridge [super setBridge:bridge]; _surfacePresenter = bridge.surfacePresenter; _nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithBridge:self.bridge surfacePresenter:_surfacePresenter]; - [bridge.eventDispatcher addDispatchObserver:self]; [bridge.uiManager.observerCoordinator addObserver:self]; [_surfacePresenter addObserver:self]; } +- (void)setModuleRegistry:(RCTModuleRegistry *)moduleRegistry +{ + [super setModuleRegistry:moduleRegistry]; + [[moduleRegistry moduleForName:"EventDispatcher"] addDispatchObserver:self]; +} + /* * In bridgeless mode, `setBridge` is never called during initializtion. Instead this selector is invoked via * BridgelessTurboModuleSetup. diff --git a/Libraries/NativeAnimation/React-RCTAnimation.podspec b/Libraries/NativeAnimation/React-RCTAnimation.podspec index 01f605c9822f46..547534b755b562 100644 --- a/Libraries/NativeAnimation/React-RCTAnimation.podspec +++ b/Libraries/NativeAnimation/React-RCTAnimation.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "{Drivers/*,Nodes/*,*}.{m,mm}" diff --git a/Libraries/NativeComponent/NativeComponentRegistry.js b/Libraries/NativeComponent/NativeComponentRegistry.js new file mode 100644 index 00000000000000..242cee6ddbdba6 --- /dev/null +++ b/Libraries/NativeComponent/NativeComponentRegistry.js @@ -0,0 +1,125 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import {createViewConfig} from './ViewConfig'; +import UIManager from '../ReactNative/UIManager'; +import type { + HostComponent, + PartialViewConfig, +} from '../Renderer/shims/ReactNativeTypes'; +import ReactNativeViewConfigRegistry from '../Renderer/shims/ReactNativeViewConfigRegistry'; +import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; +import verifyComponentAttributeEquivalence from '../Utilities/verifyComponentAttributeEquivalence'; +import invariant from 'invariant'; +import * as React from 'react'; + +let getRuntimeConfig; + +/** + * Configures a function that is called to determine whether a given component + * should be registered using reflection of the native component at runtime. + * + * The provider should return null if the native component is unavailable in + * the current environment. + */ +export function setRuntimeConfigProvider( + runtimeConfigProvider: ( + name: string, + ) => ?{ + native: boolean, + verify: boolean, + }, +): void { + invariant( + getRuntimeConfig == null, + 'NativeComponentRegistry.setRuntimeConfigProvider() called more than once.', + ); + getRuntimeConfig = runtimeConfigProvider; +} + +/** + * Gets a `NativeComponent` that can be rendered by React Native. + * + * The supplied `viewConfigProvider` may or may not be invoked and utilized, + * depending on how `setRuntimeConfigProvider` is configured. + */ +export function get( + name: string, + viewConfigProvider: () => PartialViewConfig, +): HostComponent { + ReactNativeViewConfigRegistry.register(name, () => { + const {native, verify} = getRuntimeConfig?.(name) ?? { + native: true, + verify: false, + }; + + const viewConfig = native + ? getNativeComponentAttributes(name) + : createViewConfig(viewConfigProvider()); + + if (verify) { + if (native) { + verifyComponentAttributeEquivalence( + viewConfig, + createViewConfig(viewConfigProvider()), + ); + } else { + verifyComponentAttributeEquivalence( + getNativeComponentAttributes(name), + viewConfig, + ); + } + } + + return viewConfig; + }); + + // $FlowFixMe[incompatible-return] `NativeComponent` is actually string! + return name; +} + +/** + * Same as `NativeComponentRegistry.get(...)`, except this will check either + * the `setRuntimeConfigProvider` configuration or use native reflection (slow) + * to determine whether this native component is available. + * + * If the native component is not available, a stub component is returned. Note + * that the return value of this is not `HostComponent` because the returned + * component instance is not guaranteed to have native methods. + */ +export function getWithFallback_DEPRECATED( + name: string, + viewConfigProvider: () => PartialViewConfig, +): React.AbstractComponent { + if (getRuntimeConfig == null) { + // If `setRuntimeConfigProvider` is not configured, use native reflection. + if (hasNativeViewConfig(name)) { + return get(name, viewConfigProvider); + } + } else { + // If there is no runtime config, then the native component is unavailable. + if (getRuntimeConfig(name) != null) { + return get(name, viewConfigProvider); + } + } + + const FallbackNativeComponent = function(props: Config): React.Node { + return null; + }; + FallbackNativeComponent.displayName = `Fallback(${name})`; + return FallbackNativeComponent; +} + +function hasNativeViewConfig(name: string): boolean { + invariant(getRuntimeConfig == null, 'Unexpected invocation!'); + return UIManager.getViewManagerConfig(name) != null; +} diff --git a/Libraries/NativeComponent/ViewConfig.js b/Libraries/NativeComponent/ViewConfig.js new file mode 100644 index 00000000000000..d04535a4096736 --- /dev/null +++ b/Libraries/NativeComponent/ViewConfig.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import ReactNativeViewViewConfig from '../Components/View/ReactNativeViewViewConfig'; +import type { + PartialViewConfig, + ViewConfig, +} from '../Renderer/shims/ReactNativeTypes'; + +/** + * Creates a complete `ViewConfig` from a `PartialViewConfig`. + */ +export function createViewConfig( + partialViewConfig: PartialViewConfig, +): ViewConfig { + return { + uiViewClassName: partialViewConfig.uiViewClassName, + Commands: {}, + bubblingEventTypes: composeIndexers( + ReactNativeViewViewConfig.bubblingEventTypes, + partialViewConfig.bubblingEventTypes, + ), + directEventTypes: composeIndexers( + ReactNativeViewViewConfig.directEventTypes, + partialViewConfig.directEventTypes, + ), + validAttributes: composeIndexers( + // $FlowFixMe[incompatible-call] `style` property confuses Flow. + ReactNativeViewViewConfig.validAttributes, + // $FlowFixMe[incompatible-call] `style` property confuses Flow. + partialViewConfig.validAttributes, + ), + }; +} + +function composeIndexers( + maybeA: ?{+[string]: T}, + maybeB: ?{+[string]: T}, +): {+[string]: T} { + return maybeA == null || maybeB == null + ? maybeA ?? maybeB ?? {} + : {...maybeA, ...maybeB}; +} diff --git a/Libraries/Network/RCTHTTPRequestHandler.mm b/Libraries/Network/RCTHTTPRequestHandler.mm index 274f3810f25980..6b1f240daa45c9 100644 --- a/Libraries/Network/RCTHTTPRequestHandler.mm +++ b/Libraries/Network/RCTHTTPRequestHandler.mm @@ -25,7 +25,7 @@ @implementation RCTHTTPRequestHandler std::mutex _mutex; } -@synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; @synthesize methodQueue = _methodQueue; RCT_EXPORT_MODULE() @@ -74,7 +74,7 @@ - (NSURLSessionDataTask *)sendRequest:(NSURLRequest *)request NSOperationQueue *callbackQueue = [NSOperationQueue new]; callbackQueue.maxConcurrentOperationCount = 1; - callbackQueue.underlyingQueue = [[_bridge networking] methodQueue]; + callbackQueue.underlyingQueue = [[_moduleRegistry moduleForName:"Networking"] methodQueue]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; // Set allowsCellularAccess to NO ONLY if key ReactNetworkForceWifiOnly exists AND its value is YES if (useWifiOnly) { diff --git a/Libraries/Network/RCTNetworking.android.js b/Libraries/Network/RCTNetworking.android.js index 12864c9c9af7da..87334689cae811 100644 --- a/Libraries/Network/RCTNetworking.android.js +++ b/Libraries/Network/RCTNetworking.android.js @@ -38,7 +38,8 @@ function generateRequestId(): number { * This class is a wrapper around the native RCTNetworking module. It adds a necessary unique * requestId to each network request that can be used to abort that request later on. */ -class RCTNetworking extends NativeEventEmitter { +// FIXME: use typed events +class RCTNetworking extends NativeEventEmitter<$FlowFixMe> { constructor() { super(NativeNetworkingAndroid); } diff --git a/Libraries/Network/RCTNetworking.ios.js b/Libraries/Network/RCTNetworking.ios.js index 92ef33394316a3..125f5cf3ecc259 100644 --- a/Libraries/Network/RCTNetworking.ios.js +++ b/Libraries/Network/RCTNetworking.ios.js @@ -16,9 +16,17 @@ import type {NativeResponseType} from './XMLHttpRequest'; import convertRequestBody from './convertRequestBody'; import type {RequestBody} from './convertRequestBody'; -class RCTNetworking extends NativeEventEmitter { +// FIXME: use typed events +class RCTNetworking extends NativeEventEmitter<$FlowFixMe> { constructor() { - super(NativeNetworkingIOS); + const disableCallsIntoModule = + typeof global.__disableRCTNetworkingExtraneousModuleCalls === 'function' + ? global.__disableRCTNetworkingExtraneousModuleCalls() + : false; + + super(NativeNetworkingIOS, { + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: disableCallsIntoModule, + }); } sendRequest( diff --git a/Libraries/Network/RCTNetworking.mm b/Libraries/Network/RCTNetworking.mm index b857c43a9086e4..0f9c3d61c0b104 100644 --- a/Libraries/Network/RCTNetworking.mm +++ b/Libraries/Network/RCTNetworking.mm @@ -11,7 +11,6 @@ #import #import #import -#import #import #import #import @@ -158,9 +157,19 @@ @implementation RCTNetworking RCT_EXPORT_MODULE() ++ (BOOL)requiresMainQueueSetup +{ + return YES; +} + +- (instancetype)init +{ + return [super initWithDisabledObservation]; +} + - (instancetype)initWithHandlersProvider:(NSArray> * (^)(void))getHandlers { - if (self = [super init]) { + if (self = [super initWithDisabledObservation]) { _handlersProvider = getHandlers; } return self; @@ -168,6 +177,8 @@ - (instancetype)initWithHandlersProvider:(NSArray> * (^ - (void)invalidate { + [super invalidate]; + for (NSNumber *requestID in _tasksByRequestID) { [_tasksByRequestID[requestID] cancel]; } @@ -680,7 +691,7 @@ - (RCTNetworkTask *)networkTaskWithRequest:(NSURLRequest *)request completionBlo @"timeout": @(query.timeout()), @"withCredentials": @(query.withCredentials()), }; - + // TODO: buildRequest returns a cancellation block, but there's currently // no way to invoke it, if, for example the request is cancelled while // loading a large file to build the request body diff --git a/Libraries/Network/React-RCTNetwork.podspec b/Libraries/Network/React-RCTNetwork.podspec index e21afd21a309d7..09b7c6f0e7129e 100644 --- a/Libraries/Network/React-RCTNetwork.podspec +++ b/Libraries/Network/React-RCTNetwork.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/Network/__tests__/XMLHttpRequest-test.js b/Libraries/Network/__tests__/XMLHttpRequest-test.js index c36977f1bc7945..a708bdf844f315 100644 --- a/Libraries/Network/__tests__/XMLHttpRequest-test.js +++ b/Libraries/Network/__tests__/XMLHttpRequest-test.js @@ -10,12 +10,13 @@ 'use strict'; +import createPerformanceLogger from '../../Utilities/createPerformanceLogger'; + jest.unmock('../../Utilities/Platform'); jest.mock('../../Utilities/GlobalPerformanceLogger'); const Platform = require('../../Utilities/Platform'); const GlobalPerformanceLogger = require('../../Utilities/GlobalPerformanceLogger'); -const createPerformanceLogger = require('../../Utilities/createPerformanceLogger'); let requestId = 1; function setRequestId(id) { diff --git a/Libraries/Network/fetch.js b/Libraries/Network/fetch.js index 65a02b9ee4d428..6ebb79c2ca51aa 100644 --- a/Libraries/Network/fetch.js +++ b/Libraries/Network/fetch.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 */ diff --git a/Libraries/Performance/Systrace.js b/Libraries/Performance/Systrace.js index 048c3d404271ad..6089016521b862 100644 --- a/Libraries/Performance/Systrace.js +++ b/Libraries/Performance/Systrace.js @@ -209,11 +209,9 @@ const Systrace = { }; if (__DEV__) { - // This is needed, because require callis in polyfills are not processed as - // other files. Therefore, calls to `require('moduleId')` are not replaced - // with numeric IDs - // TODO(davidaurelio) Scan polyfills for dependencies, too (t9759686) - (require: $FlowFixMe).Systrace = Systrace; + // The metro require polyfill can not have dependencies (true for all polyfills). + // Ensure that `Systrace` is available in polyfill by exposing it globally. + global[(global.__METRO_GLOBAL_PREFIX__ || '') + '__SYSTRACE'] = Systrace; } module.exports = Systrace; diff --git a/Libraries/Pressability/Pressability.js b/Libraries/Pressability/Pressability.js index 31d32166804bed..17dae80c59ccaf 100644 --- a/Libraries/Pressability/Pressability.js +++ b/Libraries/Pressability/Pressability.js @@ -276,8 +276,7 @@ const isPressInSignal = signal => const isTerminalSignal = signal => signal === 'RESPONDER_TERMINATED' || signal === 'RESPONDER_RELEASE'; -const DEFAULT_LONG_PRESS_DELAY_MS = 370; // 500 - 130 -const DEFAULT_PRESS_DELAY_MS = 130; +const DEFAULT_LONG_PRESS_DELAY_MS = 500; const DEFAULT_PRESS_RECT_OFFSETS = { bottom: 30, left: 20, @@ -472,12 +471,7 @@ export default class Pressability { this._touchState = 'NOT_RESPONDER'; this._receiveSignal('RESPONDER_GRANT', event); - const delayPressIn = normalizeDelay( - this._config.delayPressIn, - 0, - DEFAULT_PRESS_DELAY_MS, - ); - + const delayPressIn = normalizeDelay(this._config.delayPressIn); if (delayPressIn > 0) { this._pressDelayTimeout = setTimeout(() => { this._receiveSignal('DELAY', event); @@ -489,7 +483,7 @@ export default class Pressability { const delayLongPress = normalizeDelay( this._config.delayLongPress, 10, - DEFAULT_LONG_PRESS_DELAY_MS, + DEFAULT_LONG_PRESS_DELAY_MS - delayPressIn, ); this._longPressDelayTimeout = setTimeout(() => { this._handleLongPress(event); @@ -497,8 +491,9 @@ export default class Pressability { }, onResponderMove: (event: PressEvent): void => { - if (this._config.onPressMove != null) { - this._config.onPressMove(event); + const {onPressMove} = this._config; + if (onPressMove != null) { + onPressMove(event); } // Region may not have finished being measured, yet. @@ -661,10 +656,10 @@ export default class Pressability { prevState === 'NOT_RESPONDER' && nextState === 'RESPONDER_INACTIVE_PRESS_IN'; - const isActivationTransiton = + const isActivationTransition = !isActivationSignal(prevState) && isActivationSignal(nextState); - if (isInitialTransition || isActivationTransiton) { + if (isInitialTransition || isActivationTransition) { this._measureResponderRegion(); } @@ -685,6 +680,11 @@ export default class Pressability { } if (isPressInSignal(prevState) && signal === 'RESPONDER_RELEASE') { + // If we never activated (due to delays), activate and deactivate now. + if (!isNextActive && !isPrevActive) { + this._activate(event); + this._deactivate(event); + } const {onLongPress, onPress, android_disableSound} = this._config; if (onPress != null) { const isPressCanceledByLongPress = @@ -692,11 +692,6 @@ export default class Pressability { prevState === 'RESPONDER_ACTIVE_LONG_PRESS_IN' && this._shouldLongPressCancelPress(); if (!isPressCanceledByLongPress) { - // If we never activated (due to delays), activate and deactivate now. - if (!isNextActive && !isPrevActive) { - this._activate(event); - this._deactivate(event); - } if (Platform.OS === 'android' && android_disableSound !== true) { SoundManager.playTouchSound(); } @@ -710,11 +705,8 @@ export default class Pressability { _activate(event: PressEvent): void { const {onPressIn} = this._config; - const touch = getTouchFromPressEvent(event); - this._touchActivatePosition = { - pageX: touch.pageX, - pageY: touch.pageY, - }; + const {pageX, pageY} = getTouchFromPressEvent(event); + this._touchActivatePosition = {pageX, pageY}; this._touchActivateTime = Date.now(); if (onPressIn != null) { onPressIn(event); diff --git a/Libraries/Pressability/PressabilityDebug.js b/Libraries/Pressability/PressabilityDebug.js index dd8ecdd2d172e0..9b693dfd43e124 100644 --- a/Libraries/Pressability/PressabilityDebug.js +++ b/Libraries/Pressability/PressabilityDebug.js @@ -13,7 +13,6 @@ import normalizeColor from '../StyleSheet/normalizeColor'; import type {ColorValue} from '../StyleSheet/StyleSheet'; -import Touchable from '../Components/Touchable/Touchable'; import View from '../Components/View/View'; import * as React from 'react'; @@ -73,9 +72,17 @@ export function PressabilityDebugView({color, hitSlop}: Props): React.Node { return null; } +let isDebugEnabled = false; + export function isEnabled(): boolean { if (__DEV__) { - return Touchable.TOUCH_TARGET_DEBUG; + return isDebugEnabled; } return false; } + +export function setEnabled(value: boolean): void { + if (__DEV__) { + isDebugEnabled = value; + } +} diff --git a/Libraries/Pressability/__tests__/Pressability-test.js b/Libraries/Pressability/__tests__/Pressability-test.js index 52c35d00c1faae..b0be50280ee149 100644 --- a/Libraries/Pressability/__tests__/Pressability-test.js +++ b/Libraries/Pressability/__tests__/Pressability-test.js @@ -355,7 +355,7 @@ describe('Pressability', () => { expect(config.onLongPress).toBeCalled(); }); - it('is called if pressed for 370ms after the press delay', () => { + it('is called if pressed for 500ms after press started', () => { const {config, handlers} = createMockPressability({ delayPressIn: 100, }); @@ -364,7 +364,7 @@ describe('Pressability', () => { handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); handlers.onResponderMove(createMockPressEvent('onResponderMove')); - jest.advanceTimersByTime(469); + jest.advanceTimersByTime(499); expect(config.onLongPress).not.toBeCalled(); jest.advanceTimersByTime(1); expect(config.onLongPress).toBeCalled(); @@ -393,7 +393,7 @@ describe('Pressability', () => { handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); handlers.onResponderMove(createMockPressEvent('onResponderMove')); - jest.advanceTimersByTime(139); + jest.advanceTimersByTime(9); expect(config.onLongPress).not.toBeCalled(); jest.advanceTimersByTime(1); expect(config.onLongPress).toBeCalled(); @@ -460,7 +460,13 @@ describe('Pressability', () => { const {config, handlers} = createMockPressability(); handlers.onStartShouldSetResponder(); - handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); + handlers.onResponderGrant( + createMockPressEvent({ + registrationName: 'onResponderGrant', + pageX: 0, + pageY: 0, + }), + ); handlers.onResponderMove( createMockPressEvent({ registrationName: 'onResponderMove', @@ -475,7 +481,13 @@ describe('Pressability', () => { // Subsequent long touch gesture should not carry over previous state. handlers.onStartShouldSetResponder(); - handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); + handlers.onResponderGrant( + createMockPressEvent({ + registrationName: 'onResponderGrant', + pageX: 7, + pageY: 8, + }), + ); handlers.onResponderMove( // NOTE: Delta from (0, 0) is ~10.6 > 10, but should not matter. createMockPressEvent({ @@ -522,7 +534,7 @@ describe('Pressability', () => { expect(config.onPressIn).toBeCalled(); }); - it('is called after the default delay by default', () => { + it('is called immediately by default', () => { const {config, handlers} = createMockPressability({ delayPressIn: null, }); @@ -531,24 +543,6 @@ describe('Pressability', () => { handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); handlers.onResponderMove(createMockPressEvent('onResponderMove')); - jest.advanceTimersByTime(129); - expect(config.onPressIn).not.toBeCalled(); - jest.advanceTimersByTime(1); - expect(config.onPressIn).toBeCalled(); - }); - - it('falls back to the default delay if `delayPressIn` is omitted', () => { - const {config, handlers} = createMockPressability({ - delayPressIn: null, - }); - - handlers.onStartShouldSetResponder(); - handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); - handlers.onResponderMove(createMockPressEvent('onResponderMove')); - - jest.advanceTimersByTime(129); - expect(config.onPressIn).not.toBeCalled(); - jest.advanceTimersByTime(1); expect(config.onPressIn).toBeCalled(); }); @@ -582,7 +576,9 @@ describe('Pressability', () => { describe('onPressOut', () => { it('is called after `onResponderRelease` before `delayPressIn`', () => { - const {config, handlers} = createMockPressability(); + const {config, handlers} = createMockPressability({ + delayPressIn: Number.EPSILON, + }); handlers.onStartShouldSetResponder(); handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); @@ -596,7 +592,9 @@ describe('Pressability', () => { }); it('is called after `onResponderRelease` after `delayPressIn`', () => { - const {config, handlers} = createMockPressability(); + const {config, handlers} = createMockPressability({ + delayPressIn: Number.EPSILON, + }); handlers.onStartShouldSetResponder(); handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); @@ -611,7 +609,9 @@ describe('Pressability', () => { }); it('is not called after `onResponderTerminate` before `delayPressIn`', () => { - const {config, handlers} = createMockPressability(); + const {config, handlers} = createMockPressability({ + delayPressIn: Number.EPSILON, + }); handlers.onStartShouldSetResponder(); handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); @@ -716,7 +716,9 @@ describe('Pressability', () => { handlers.onResponderMove( createMockPressEvent({ registrationName: 'onResponderMove', + // $FlowFixMe[unsafe-addition] pageX: mockRegion.width + mockSlop.right / 2, + // $FlowFixMe[unsafe-addition] pageY: mockRegion.height + mockSlop.bottom / 2, }), ); @@ -750,7 +752,9 @@ describe('Pressability', () => { handlers.onResponderMove( createMockPressEvent({ registrationName: 'onResponderMove', + // $FlowFixMe[unsafe-addition] pageX: mockRegion.width + mockSlop.right / 2, + // $FlowFixMe[unsafe-addition] pageY: mockRegion.height + mockSlop.bottom / 2, }), ); @@ -870,9 +874,11 @@ describe('Pressability', () => { config.onStartShouldSetResponder_DEPRECATED, ); + // $FlowFixMe[prop-missing] onStartShouldSetResponder_DEPRECATED.mockReturnValue(false); expect(handlers.onStartShouldSetResponder()).toBe(false); + // $FlowFixMe[prop-missing] onStartShouldSetResponder_DEPRECATED.mockReturnValue(true); expect(handlers.onStartShouldSetResponder()).toBe(true); }); diff --git a/Libraries/Pressability/usePressability.js b/Libraries/Pressability/usePressability.js index 3538524239387b..9ed4cc22197437 100644 --- a/Libraries/Pressability/usePressability.js +++ b/Libraries/Pressability/usePressability.js @@ -16,11 +16,16 @@ import Pressability, { } from './Pressability'; import {useEffect, useRef} from 'react'; +/** + * Creates a persistent instance of `Pressability` that automatically configures + * itself and resets. Accepts null `config` to support lazy initialization. Once + * initialized, will not un-initialize until the component has been unmounted. + */ export default function usePressability( - config: PressabilityConfig, -): EventHandlers { + config: ?PressabilityConfig, +): ?EventHandlers { const pressabilityRef = useRef(null); - if (pressabilityRef.current == null) { + if (config != null && pressabilityRef.current == null) { pressabilityRef.current = new Pressability(config); } const pressability = pressabilityRef.current; @@ -28,16 +33,20 @@ export default function usePressability( // On the initial mount, this is a no-op. On updates, `pressability` will be // re-configured to use the new configuration. useEffect(() => { - pressability.configure(config); + if (config != null && pressability != null) { + pressability.configure(config); + } }, [config, pressability]); // On unmount, reset pending state and timers inside `pressability`. This is // a separate effect because we do not want to reset when `config` changes. useEffect(() => { - return () => { - pressability.reset(); - }; + if (pressability != null) { + return () => { + pressability.reset(); + }; + } }, [pressability]); - return pressability.getEventHandlers(); + return pressability == null ? null : pressability.getEventHandlers(); } diff --git a/Libraries/Promise.js b/Libraries/Promise.js index 836c2978a73065..fc06e9f35db06d 100644 --- a/Libraries/Promise.js +++ b/Libraries/Promise.js @@ -16,42 +16,9 @@ require('promise/setimmediate/done'); require('promise/setimmediate/finally'); if (__DEV__) { - require('promise/setimmediate/rejection-tracking').enable({ - allRejections: true, - onUnhandled: (id, rejection = {}) => { - let message: string; - let stack: ?string; - - const stringValue = Object.prototype.toString.call(rejection); - if (stringValue === '[object Error]') { - message = Error.prototype.toString.call(rejection); - const error: Error = (rejection: $FlowFixMe); - stack = error.stack; - } else { - try { - message = require('pretty-format')(rejection); - } catch { - message = - typeof rejection === 'string' - ? rejection - : JSON.stringify((rejection: $FlowFixMe)); - } - } - - const warning = - `Possible Unhandled Promise Rejection (id: ${id}):\n` + - `${message ?? ''}\n` + - (stack == null ? '' : stack); - console.warn(warning); - }, - onHandled: id => { - const warning = - `Promise Rejection Handled (id: ${id})\n` + - 'This means you can ignore any previous messages of the form ' + - `"Possible Unhandled Promise Rejection (id: ${id}):"`; - console.warn(warning); - }, - }); + require('promise/setimmediate/rejection-tracking').enable( + require('./promiseRejectionTrackingOptions').default, + ); } module.exports = Promise; diff --git a/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js b/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js index 2e2044262eefaa..1eec7bde81481b 100644 --- a/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +++ b/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js @@ -32,7 +32,7 @@ type Notification = {| |}; export interface Spec extends TurboModule { - +getConstants: () => {...}; + +getConstants: () => {||}; +onFinishRemoteNotification: ( notificationId: string, /** diff --git a/Libraries/PushNotificationIOS/PushNotificationIOS.js b/Libraries/PushNotificationIOS/PushNotificationIOS.js index 99d2d92c975a5b..85ebf4b4ffcde4 100644 --- a/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -14,7 +14,31 @@ import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import NativePushNotificationManagerIOS from './NativePushNotificationManagerIOS'; import invariant from 'invariant'; -const PushNotificationEmitter = new NativeEventEmitter( +type NativePushNotificationIOSEventDefinitions = { + remoteNotificationReceived: [ + { + notificationId: string, + remote: boolean, + ... + }, + ], + remoteNotificationsRegistered: [ + { + deviceToken?: ?string, + ... + }, + ], + remoteNotificationRegistrationError: [ + { + message: string, + code: number, + details: {...}, + }, + ], + localNotificationReceived: [{...}], +}; + +const PushNotificationEmitter = new NativeEventEmitter( NativePushNotificationManagerIOS, ); diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.h b/Libraries/PushNotificationIOS/RCTPushNotificationManager.h index c4281361e6d673..e486252c704b4a 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.h +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.h @@ -13,7 +13,7 @@ extern NSString *const RCTRemoteNotificationReceived; typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result); -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC +#if !TARGET_OS_UIKITFORMAC + (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings; + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; + (void)didReceiveRemoteNotification:(NSDictionary *)notification; diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm b/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm index 95eec384e9a9a6..aa075bb6bfa1e6 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm @@ -12,7 +12,6 @@ #import #import #import -#import #import #import "RCTPushNotificationPlugins.h" @@ -25,7 +24,7 @@ static NSString *const kErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS"; -#if !TARGET_OS_TV +#if !TARGET_OS_UIKITFORMAC @implementation RCTConvert (NSCalendarUnit) RCT_ENUM_CONVERTER(NSCalendarUnit, @@ -79,11 +78,11 @@ + (UILocalNotification *)UILocalNotification:(id)json #else @interface RCTPushNotificationManager () @end -#endif //TARGET_OS_TV / TARGET_OS_UIKITFORMAC +#endif // TARGET_OS_UIKITFORMAC @implementation RCTPushNotificationManager -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC +#if !TARGET_OS_UIKITFORMAC static NSDictionary *RCTFormatLocalNotification(UILocalNotification *notification) { @@ -128,7 +127,7 @@ @implementation RCTPushNotificationManager return formattedNotification; } -#endif //TARGET_OS_TV / TARGET_OS_UIKITFORMAC +#endif // TARGET_OS_UIKITFORMAC RCT_EXPORT_MODULE() @@ -137,7 +136,7 @@ - (dispatch_queue_t)methodQueue return dispatch_get_main_queue(); } -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC +#if !TARGET_OS_UIKITFORMAC - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self @@ -472,7 +471,7 @@ - (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification }]; } -#else //TARGET_OS_TV / TARGET_OS_UIKITFORMAC +#else // TARGET_OS_UIKITFORMAC RCT_EXPORT_METHOD(onFinishRemoteNotification:(NSString *)notificationId fetchResult:(NSString *)fetchResult) { @@ -557,7 +556,7 @@ - (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification return @[]; } -#endif //TARGET_OS_TV / TARGET_OS_UIKITFORMAC +#endif // TARGET_OS_UIKITFORMAC - (std::shared_ptr)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { diff --git a/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec b/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec index a2c915316eb7a0..f1f734adabd1a4 100644 --- a/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +++ b/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/pushnotificationios" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/RCTRequired/RCTRequired.podspec b/Libraries/RCTRequired/RCTRequired.podspec index 3c55234fbd3e50..45d537db606814 100644 --- a/Libraries/RCTRequired/RCTRequired.podspec +++ b/Libraries/RCTRequired/RCTRequired.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.source = source s.source_files = "**/*.{c,h,m,mm,cpp}" s.header_dir = "RCTRequired" diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index 99abee3e0d792e..389b2f5240f295 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -18,9 +18,9 @@ const SceneTracker = require('../Utilities/SceneTracker'); const infoLog = require('../Utilities/infoLog'); const invariant = require('invariant'); const renderApplication = require('./renderApplication'); -const createPerformanceLogger = require('../Utilities/createPerformanceLogger'); import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger'; +import createPerformanceLogger from '../Utilities/createPerformanceLogger'; import NativeHeadlessJsTaskSupport from './NativeHeadlessJsTaskSupport'; import HeadlessJsTaskError from './HeadlessJsTaskError'; diff --git a/Libraries/ReactNative/DummyUIManager.js b/Libraries/ReactNative/DummyUIManager.js index 1947640e0a8d54..0d380f0a276f86 100644 --- a/Libraries/ReactNative/DummyUIManager.js +++ b/Libraries/ReactNative/DummyUIManager.js @@ -20,6 +20,9 @@ module.exports = { } return null; }, + hasViewManagerConfig: (viewManagerName: string): boolean => { + return viewManagerName === 'RCTVirtualText'; + }, getConstants: (): {...} => ({}), getConstantsForViewManager: (viewManagerName: string) => {}, getDefaultEventTypes: (): Array<$FlowFixMe> => [], diff --git a/Libraries/ReactNative/FabricUIManager.js b/Libraries/ReactNative/FabricUIManager.js index 2b88069742229e..7d133837ab6774 100644 --- a/Libraries/ReactNative/FabricUIManager.js +++ b/Libraries/ReactNative/FabricUIManager.js @@ -57,6 +57,7 @@ export type Spec = {| // $FlowFixMe errorCallback: (error: Object) => void, ) => void, + +sendAccessibilityEvent: (node: Node, eventType: string) => void, |}; const FabricUIManager: ?Spec = global.nativeFabricUIManager; diff --git a/Libraries/ReactNative/PaperUIManager.js b/Libraries/ReactNative/PaperUIManager.js index 776fa431e8298c..92f59e0a20863b 100644 --- a/Libraries/ReactNative/PaperUIManager.js +++ b/Libraries/ReactNative/PaperUIManager.js @@ -32,52 +32,73 @@ function getConstants(): Object { return NativeUIManagerConstants; } +function getViewManagerConfig(viewManagerName: string): any { + if ( + viewManagerConfigs[viewManagerName] === undefined && + NativeUIManager.getConstantsForViewManager + ) { + try { + viewManagerConfigs[ + viewManagerName + ] = NativeUIManager.getConstantsForViewManager(viewManagerName); + } catch (e) { + viewManagerConfigs[viewManagerName] = null; + } + } + + const config = viewManagerConfigs[viewManagerName]; + if (config) { + return config; + } + + // If we're in the Chrome Debugger, let's not even try calling the sync + // method. + if (!global.nativeCallSyncHook) { + return config; + } + + if ( + NativeUIManager.lazilyLoadView && + !triedLoadingConfig.has(viewManagerName) + ) { + const result = NativeUIManager.lazilyLoadView(viewManagerName); + triedLoadingConfig.add(viewManagerName); + if (result != null && result.viewConfig != null) { + getConstants()[viewManagerName] = result.viewConfig; + lazifyViewManagerConfig(viewManagerName); + } + } + + return viewManagerConfigs[viewManagerName]; +} + /* $FlowFixMe(>=0.123.0 site=react_native_fb) This comment suppresses an error * found when Flow v0.123.0 was deployed. To see the error, delete this comment * and run Flow. */ const UIManagerJS = { ...NativeUIManager, + createView( + reactTag: ?number, + viewName: string, + rootTag: number, + props: Object, + ): void { + if (Platform.OS === 'ios' && viewManagerConfigs[viewName] === undefined) { + // This is necessary to force the initialization of native viewManager + // classes in iOS when using static ViewConfigs + getViewManagerConfig(viewName); + } + + NativeUIManager.createView(reactTag, viewName, rootTag, props); + }, getConstants(): Object { return getConstants(); }, - getViewManagerConfig: function(viewManagerName: string): any { - if ( - viewManagerConfigs[viewManagerName] === undefined && - NativeUIManager.getConstantsForViewManager - ) { - try { - viewManagerConfigs[ - viewManagerName - ] = NativeUIManager.getConstantsForViewManager(viewManagerName); - } catch (e) { - viewManagerConfigs[viewManagerName] = null; - } - } - - const config = viewManagerConfigs[viewManagerName]; - if (config) { - return config; - } - - // If we're in the Chrome Debugger, let's not even try calling the sync - // method. - if (!global.nativeCallSyncHook) { - return config; - } - - if ( - NativeUIManager.lazilyLoadView && - !triedLoadingConfig.has(viewManagerName) - ) { - const result = NativeUIManager.lazilyLoadView(viewManagerName); - triedLoadingConfig.add(viewManagerName); - if (result.viewConfig) { - getConstants()[viewManagerName] = result.viewConfig; - lazifyViewManagerConfig(viewManagerName); - } - } - - return viewManagerConfigs[viewManagerName]; + getViewManagerConfig(viewManagerName: string): any { + return getViewManagerConfig(viewManagerName); + }, + hasViewManagerConfig(viewManagerName: string): boolean { + return getViewManagerConfig(viewManagerName) != null; }, }; diff --git a/Libraries/ReactNative/RootTag.js b/Libraries/ReactNative/RootTag.js index 24b151544d43b2..e36cafd5744e33 100644 --- a/Libraries/ReactNative/RootTag.js +++ b/Libraries/ReactNative/RootTag.js @@ -19,6 +19,10 @@ export const RootTagContext: React$Context = React.createContext Object; + +hasViewManagerConfig: (viewManagerName: string) => boolean; +createView: ( reactTag: ?number, viewName: string, @@ -34,6 +36,8 @@ interface UIManagerJSInterface extends Spec { const UIManager: UIManagerJSInterface = global.RN$Bridgeless === true ? require('./DummyUIManager') // No UIManager in bridgeless mode - : require('./PaperUIManager'); + : UIManagerInjection.unstable_UIManager == null + ? require('./PaperUIManager') + : UIManagerInjection.unstable_UIManager; module.exports = UIManager; diff --git a/Libraries/ReactNative/UIManagerInjection.js b/Libraries/ReactNative/UIManagerInjection.js new file mode 100644 index 00000000000000..2df06b2ecc6361 --- /dev/null +++ b/Libraries/ReactNative/UIManagerInjection.js @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +export default { + unstable_UIManager: (null: ?any), +}; diff --git a/Libraries/ReactNative/UIManagerProperties.js b/Libraries/ReactNative/UIManagerProperties.js index 77e67267e57b19..f8f9f6b7ea82bc 100644 --- a/Libraries/ReactNative/UIManagerProperties.js +++ b/Libraries/ReactNative/UIManagerProperties.js @@ -57,6 +57,7 @@ module.exports = [ 'AccessibilityEventTypes', 'UIView', 'getViewManagerConfig', + 'hasViewManagerConfig', 'blur', 'focus', 'genericBubblingEventTypes', diff --git a/Libraries/ReactNative/getNativeComponentAttributes.js b/Libraries/ReactNative/getNativeComponentAttributes.js index 2ec8950379d766..732e9b6745cfe7 100644 --- a/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/Libraries/ReactNative/getNativeComponentAttributes.js @@ -38,7 +38,6 @@ function getNativeComponentAttributes(uiViewClassName: string): any { while (baseModuleName) { const baseModule = UIManager.getViewManagerConfig(baseModuleName); if (!baseModule) { - console.warn('Base module "%s" does not exist', baseModuleName); baseModuleName = null; } else { bubblingEventTypes = { @@ -155,7 +154,8 @@ function getDifferForType( case 'UIEdgeInsets': return insetsDiffer; // Android Types - // (not yet implemented) + case 'Point': + return pointsDiffer; } return null; } diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index a757414252dffb..8b39b288f64ff3 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -50,6 +50,8 @@ function renderApplication( ); performanceLogger.startTimespan('renderApplication_React_render'); + performanceLogger.setExtra('usedReactFabric', fabric ? '1' : '0'); + if (fabric) { require('../Renderer/shims/ReactFabric').render(renderable, rootTag); } else { diff --git a/Libraries/ReactPrivate/ReactNativePrivateInterface.js b/Libraries/ReactPrivate/ReactNativePrivateInterface.js index d67720d28fe1a7..6155b271799e1c 100644 --- a/Libraries/ReactPrivate/ReactNativePrivateInterface.js +++ b/Libraries/ReactPrivate/ReactNativePrivateInterface.js @@ -18,7 +18,9 @@ import typeof UIManager from '../ReactNative/UIManager'; import typeof deepDiffer from '../Utilities/differ/deepDiffer'; import typeof deepFreezeAndThrowOnMutationInDev from '../Utilities/deepFreezeAndThrowOnMutationInDev'; import typeof flattenStyle from '../StyleSheet/flattenStyle'; +import {type DangerouslyImpreciseStyleProp} from '../StyleSheet/StyleSheet'; import typeof ReactFiberErrorDialog from '../Core/ReactFiberErrorDialog'; +import typeof legacySendAccessibilityEvent from '../Components/AccessibilityInfo/legacySendAccessibilityEvent'; // flowlint unsafe-getters-setters:off module.exports = { @@ -52,10 +54,13 @@ module.exports = { > { return require('../Utilities/deepFreezeAndThrowOnMutationInDev'); }, - get flattenStyle(): flattenStyle { + get flattenStyle(): flattenStyle { return require('../StyleSheet/flattenStyle'); }, get ReactFiberErrorDialog(): ReactFiberErrorDialog { return require('../Core/ReactFiberErrorDialog'); }, + get legacySendAccessibilityEvent(): legacySendAccessibilityEvent { + return require('../Components/AccessibilityInfo/legacySendAccessibilityEvent'); + }, }; diff --git a/Libraries/Reliability/UserFlow.js b/Libraries/Reliability/UserFlow.js new file mode 100644 index 00000000000000..54d0acf04d1c0d --- /dev/null +++ b/Libraries/Reliability/UserFlow.js @@ -0,0 +1,151 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict + */ + +'use strict'; + +const AUTO_INSTANCE_KEY = -1; + +export type FlowId = { + markerId: number, + instanceKey: number, +}; + +export type PointData = $Shape<{ + string: ?{[string]: string, ...}, + int: ?{[string]: number, ...}, + double: ?{[string]: number, ...}, + bool: ?{[string]: boolean, ...}, + string_array: ?{[string]: $ReadOnlyArray, ...}, + int_array: ?{[string]: $ReadOnlyArray, ...}, + double_array: ?{[string]: $ReadOnlyArray, ...}, + bool_array: ?{[string]: $ReadOnlyArray, ...}, +}>; + +/** + * API for tracking reliability of your user interactions + * + * Example: + * const flowId = UserFlow.newFlowId(QuickLogItentifiersExample.EXAMPLE_EVENT); + * ... + * UserFlow.start(flowId, {triggerSource: "user_click", cancelOnBackground: true}); + * ... + * UserFlow.addAnnotation(flowId, "cached", "true"); + * ... + * UserFlow.addPoint(flowId, "reload"); + * ... + * UserFlow.endSuccess(flowId); + */ +const UserFlow = { + /** + * Creates FlowId from markerId and instanceKey. + * You will pass FlowId in every other method of UserFlow API. + * + * By default, instanceKey will generate unique instance every time you call userFlowGetId with markerId only. + */ + newFlowId(markerId: number, instanceKey: number = AUTO_INSTANCE_KEY): FlowId { + var resolvedInstanceKey = instanceKey; + if (instanceKey === AUTO_INSTANCE_KEY) { + if (global.nativeUserFlowNextInstanceKey) { + resolvedInstanceKey = global.nativeUserFlowNextInstanceKey(markerId); + } else { + // There is no JSI methods installed, API won't do anything + resolvedInstanceKey = 0; + } + } + return { + markerId: markerId, + instanceKey: resolvedInstanceKey, + }; + }, + + /** + * Starts new flow. + * Example: + * UserFlow.start(flowId, {triggerSource: 'user_click', cancelOnBackground: true}) + * + * Specify triggerSource as a place where your flow has started. + * Specify if flow should be automatically cancelled if applicaton goes to background. + * It is recommended to use true for cancelOnBackground - this reduces amount of lost flows due to instrumentation mistakes. + * Only if you know that your flow should survive app backgrounding - use false. This includes cases of tracking cross application interactions. + * + */ + start( + flowId: FlowId, + options: {triggerSource: string, cancelOnBackground: boolean}, + ): void { + if (global.nativeUserFlowStart) { + global.nativeUserFlowStart( + flowId.markerId, + flowId.instanceKey, + options.triggerSource, + options.cancelOnBackground, + ); + } + }, + + addAnnotation( + flowId: FlowId, + annotationName: string, + annotationValue: string | boolean, + ): void { + if (global.nativeUserFlowAddAnnotation) { + global.nativeUserFlowAddAnnotation( + flowId.markerId, + flowId.instanceKey, + annotationName, + annotationValue, + ); + } + }, + + addPoint(flowId: FlowId, pointName: string, data: ?PointData = null): void { + if (global.nativeUserFlowAddPoint) { + global.nativeUserFlowAddPoint( + flowId.markerId, + flowId.instanceKey, + pointName, + data, + ); + } + }, + + endSuccess(flowId: FlowId): void { + if (global.nativeUserFlowEndSuccess) { + global.nativeUserFlowEndSuccess(flowId.markerId, flowId.instanceKey); + } + }, + + endFailure( + flowId: FlowId, + errorName: string, + debugInfo: ?string = null, + ): void { + if (global.nativeUserFlowEndFail) { + global.nativeUserFlowEndFail( + flowId.markerId, + flowId.instanceKey, + errorName, + debugInfo, + ); + } + }, + + endCancel(flowId: FlowId, cancelReason: string): void { + if (global.nativeUserFlowEndCancel) { + global.nativeUserFlowEndCancel( + flowId.markerId, + flowId.instanceKey, + cancelReason, + ); + } + }, +}; + +module.exports = UserFlow; diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index b9cc9777d2b91f..974273dc6854dd 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -e67a6b16030ebc30257a69a7fb36a9ed67f29b39 \ No newline at end of file +c3e20f18fe37993ddcbf11dccb55663b4c0d02fd \ No newline at end of file diff --git a/Libraries/Renderer/implementations/ReactFabric-dev.fb.js b/Libraries/Renderer/implementations/ReactFabric-dev.fb.js index 292bfa73b098a9..4d07117f346fb9 100644 --- a/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -139,7 +139,7 @@ var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; ) { // If document doesn't exist we know for sure we will crash in this method // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebookincubator/create-react-app/issues/3482 + // errors: https://github.com/facebook/create-react-app/issues/3482 // So we preemptively throw with a better message instead. if (!(typeof document !== "undefined")) { throw Error( @@ -263,7 +263,7 @@ var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; error = new Error( "A cross-origin error was thrown. React doesn't have access to " + "the actual error object in development. " + - "See https://fb.me/react-crossorigin-error for more information." + "See https://reactjs.org/link/crossorigin-error for more information." ); } @@ -806,13 +806,6 @@ addEventPoolingTo(SyntheticEvent); */ function getPooledWarningPropertyDefinition(propName, getVal) { - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; - function set(val) { var action = isFunction ? "setting the method" : "setting the property"; warn(action, "This is effectively a no-op"); @@ -834,13 +827,20 @@ function getPooledWarningPropertyDefinition(propName, getVal) { "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", + "See https://reactjs.org/link/event-pooling for more information.", action, propName, result ); } } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; } function createOrGetPooledEvent( @@ -1239,9 +1239,8 @@ var DehydratedFragment = 18; var SuspenseListComponent = 19; var FundamentalComponent = 20; var ScopeComponent = 21; -var Block = 22; -var OffscreenComponent = 23; -var LegacyHiddenComponent = 24; +var OffscreenComponent = 22; +var LegacyHiddenComponent = 23; /** * Instance of element that should respond to touch/move types of interactions, @@ -2548,8 +2547,6 @@ var REACT_SUSPENSE_TYPE = 0xead1; var REACT_SUSPENSE_LIST_TYPE = 0xead8; var REACT_MEMO_TYPE = 0xead3; var REACT_LAZY_TYPE = 0xead4; -var REACT_BLOCK_TYPE = 0xead9; -var REACT_SERVER_BLOCK_TYPE = 0xeada; var REACT_FUNDAMENTAL_TYPE = 0xead5; var REACT_SCOPE_TYPE = 0xead7; var REACT_OPAQUE_ID_TYPE = 0xeae0; @@ -2571,8 +2568,6 @@ if (typeof Symbol === "function" && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); - REACT_SERVER_BLOCK_TYPE = symbolFor("react.server.block"); REACT_FUNDAMENTAL_TYPE = symbolFor("react.fundamental"); REACT_SCOPE_TYPE = symbolFor("react.scope"); REACT_OPAQUE_ID_TYPE = symbolFor("react.opaque.id"); @@ -2670,9 +2665,6 @@ function getComponentName(type) { case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); - case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; @@ -2690,9 +2682,14 @@ function getComponentName(type) { return null; } +// The rest of the flags are static for better dead code elimination. +var enableProfilerTimer = true; +var warnAboutStringRefs = false; +var enableNewReconciler = false; + // Don't change these two values. They're used by React Dev Tools. -var NoEffect = - /* */ +var NoFlags = + /* */ 0; var PerformedWork = /* */ @@ -2727,40 +2724,32 @@ var Snapshot = 256; var Passive = /* */ - 512; // TODO (effects) Remove this bit once the new reconciler is synced to the old. - -var PassiveUnmountPendingDev = - /* */ - 8192; + 512; var Hydrating = /* */ 1024; var HydratingAndUpdate = /* */ - 1028; // Passive & Update & Callback & Ref & Snapshot - -var LifecycleEffectMask = - /* */ - 932; // Union of all host effects + 1028; +var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ - 2047; // These are not really side effects, but we still reuse this field. + 4095; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ - 2048; + 4096; var ShouldCapture = /* */ - 4096; + 8192; // TODO (effects) Remove this bit once the new reconciler is synced to the old. + +var PassiveUnmountPendingDev = + /* */ + 16384; var ForceUpdateForLegacySuspense = /* */ - 16384; // Static tags describe aspects of a fiber that are not specific to a render, - -// The rest of the flags are static for better dead code elimination. -var enableProfilerTimer = true; -var warnAboutStringRefs = false; -var enableNewReconciler = false; + 32768; // Static tags describe aspects of a fiber that are not specific to a render, var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -2775,7 +2764,7 @@ function getNearestMountedFiber(fiber) { do { node = nextNode; - if ((node.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { // This is an insertion or in-progress hydration. The nearest possible // mounted fiber is the parent but we need to continue to figure out // if that one is still mounted. @@ -3741,7 +3730,8 @@ var _nativeFabricUIManage = nativeFabricUIManager, registerEventHandler = _nativeFabricUIManage.registerEventHandler, fabricMeasure = _nativeFabricUIManage.measure, fabricMeasureInWindow = _nativeFabricUIManage.measureInWindow, - fabricMeasureLayout = _nativeFabricUIManage.measureLayout; + fabricMeasureLayout = _nativeFabricUIManage.measureLayout, + sendAccessibilityEvent = _nativeFabricUIManage.sendAccessibilityEvent; var getViewConfigForType = ReactNativePrivateInterface.ReactNativeViewConfigRegistry.get; // Counter for uniquely identifying views. // % 10 === 1 means it is a rootTag. @@ -3761,82 +3751,80 @@ if (registerEventHandler) { * This is used for refs on host components. */ -var ReactFabricHostComponent = - /*#__PURE__*/ - (function() { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; - } - - var _proto = ReactFabricHostComponent.prototype; - - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; +var ReactFabricHostComponent = /*#__PURE__*/ (function() { + function ReactFabricHostComponent( + tag, + viewConfig, + props, + internalInstanceHandle + ) { + this._nativeTag = tag; + this.viewConfig = viewConfig; + this.currentProps = props; + this._internalInstanceHandle = internalInstanceHandle; + } - _proto.measure = function measure(callback) { - fabricMeasure( - this._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + var _proto = ReactFabricHostComponent.prototype; - _proto.measureInWindow = function measureInWindow(callback) { - fabricMeasureInWindow( - this._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - if ( - typeof relativeToNativeNode === "number" || - !(relativeToNativeNode instanceof ReactFabricHostComponent) - ) { - { - error( - "Warning: ref.measureLayout must be called with a ref to a native component." - ); - } + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; - return; - } + _proto.measure = function measure(callback) { + fabricMeasure( + this._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - fabricMeasureLayout( - this._internalInstanceHandle.stateNode.node, - relativeToNativeNode._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; + _proto.measureInWindow = function measureInWindow(callback) { + fabricMeasureInWindow( + this._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - _proto.setNativeProps = function setNativeProps(nativeProps) { + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ + { + if ( + typeof relativeToNativeNode === "number" || + !(relativeToNativeNode instanceof ReactFabricHostComponent) + ) { { - error("Warning: setNativeProps is not currently supported in Fabric"); + error( + "Warning: ref.measureLayout must be called with a ref to a native component." + ); } return; - }; + } + + fabricMeasureLayout( + this._internalInstanceHandle.stateNode.node, + relativeToNativeNode._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + }; + + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + error("Warning: setNativeProps is not currently supported in Fabric"); + } + + return; + }; - return ReactFabricHostComponent; - })(); // eslint-disable-next-line no-unused-expressions + return ReactFabricHostComponent; +})(); // eslint-disable-next-line no-unused-expressions function appendInitialChild(parentInstance, child) { appendChildNode(parentInstance.node, child.node); } @@ -4232,9 +4220,6 @@ function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { // Memo may contain any component type so we recursively resolve it. return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); - case REACT_BLOCK_TYPE: - return describeFunctionComponentFrame(type._render, source, ownerFn); - case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; @@ -4575,7 +4560,7 @@ function processChildContext(fiber, type, parentContext) { checkPropTypes(childContextTypes, childContext, "child context", name); } - return Object.assign({}, parentContext, {}, childContext); + return Object.assign({}, parentContext, childContext); } } @@ -4702,7 +4687,7 @@ function injectInternals(internals) { error( "The installed version of React DevTools is too old and will not work " + "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" + "https://reactjs.org/link/react-devtools" ); } // DevTools exists, even though it doesn't support Fiber. @@ -4743,7 +4728,7 @@ function onScheduleRoot(root, children) { function onCommitRoot(root, priorityLevel) { if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { try { - var didError = (root.current.effectTag & DidCapture) === DidCapture; + var didError = (root.current.flags & DidCapture) === DidCapture; if (enableProfilerTimer) { injectedHook.onCommitFiberRoot( @@ -4796,7 +4781,7 @@ var Scheduler_now = Scheduler.unstable_now; ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } @@ -4812,18 +4797,16 @@ var IdlePriority = 95; // NoPriority is the absence of priority. Also React-only var NoPriority = 90; var initialTimeMs = Scheduler_now(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. -var SyncLanePriority = 17; -var SyncBatchedLanePriority = 16; -var InputDiscreteHydrationLanePriority = 15; -var InputDiscreteLanePriority = 14; -var InputContinuousHydrationLanePriority = 13; -var InputContinuousLanePriority = 12; -var DefaultHydrationLanePriority = 11; -var DefaultLanePriority = 10; -var TransitionShortHydrationLanePriority = 9; -var TransitionShortLanePriority = 8; -var TransitionLongHydrationLanePriority = 7; -var TransitionLongLanePriority = 6; +var SyncLanePriority = 15; +var SyncBatchedLanePriority = 14; +var InputDiscreteHydrationLanePriority = 13; +var InputDiscreteLanePriority = 12; +var InputContinuousHydrationLanePriority = 11; +var InputContinuousLanePriority = 10; +var DefaultHydrationLanePriority = 9; +var DefaultLanePriority = 8; +var TransitionHydrationPriority = 7; +var TransitionPriority = 6; var RetryLanePriority = 5; var SelectiveHydrationLanePriority = 4; var IdleHydrationLanePriority = 3; @@ -4861,21 +4844,18 @@ var DefaultHydrationLane = var DefaultLanes = /* */ 3584; -var TransitionShortHydrationLane = - /* */ +var TransitionHydrationLane = + /* */ 4096; -var TransitionShortLanes = - /* */ - 122880; -var TransitionLongHydrationLane = - /* */ - 131072; -var TransitionLongLanes = - /* */ - 3932160; +var TransitionLanes = + /* */ + 4186112; var RetryLanes = /* */ 62914560; +var SomeRetryLane = + /* */ + 33554432; var SelectiveHydrationLane = /* */ 67108864; @@ -4892,7 +4872,6 @@ var OffscreenLane = /* */ 1073741824; var NoTimestamp = -1; -function setCurrentUpdateLanePriority(newLanePriority) {} // "Registers" used to "return" multiple values // Used by getHighestPriorityLanes and getNextLanes: var return_highestLanePriority = DefaultLanePriority; @@ -4944,28 +4923,16 @@ function getHighestPriorityLanes(lanes) { return defaultLanes; } - if ((lanes & TransitionShortHydrationLane) !== NoLanes) { - return_highestLanePriority = TransitionShortHydrationLanePriority; - return TransitionShortHydrationLane; - } - - var transitionShortLanes = TransitionShortLanes & lanes; - - if (transitionShortLanes !== NoLanes) { - return_highestLanePriority = TransitionShortLanePriority; - return transitionShortLanes; + if ((lanes & TransitionHydrationLane) !== NoLanes) { + return_highestLanePriority = TransitionHydrationPriority; + return TransitionHydrationLane; } - if ((lanes & TransitionLongHydrationLane) !== NoLanes) { - return_highestLanePriority = TransitionLongHydrationLanePriority; - return TransitionLongHydrationLane; - } + var transitionLanes = TransitionLanes & lanes; - var transitionLongLanes = TransitionLongLanes & lanes; - - if (transitionLongLanes !== NoLanes) { - return_highestLanePriority = TransitionLongLanePriority; - return transitionLongLanes; + if (transitionLanes !== NoLanes) { + return_highestLanePriority = TransitionPriority; + return transitionLanes; } var retryLanes = RetryLanes & lanes; @@ -5039,10 +5006,8 @@ function lanePriorityToSchedulerPriority(lanePriority) { case DefaultHydrationLanePriority: case DefaultLanePriority: - case TransitionShortHydrationLanePriority: - case TransitionShortLanePriority: - case TransitionLongHydrationLanePriority: - case TransitionLongLanePriority: + case TransitionHydrationPriority: + case TransitionPriority: case SelectiveHydrationLanePriority: case RetryLanePriority: return NormalPriority; @@ -5200,8 +5165,22 @@ function computeExpirationTime(lane, currentTime) { if (priority >= InputContinuousLanePriority) { // User interactions should expire slightly more quickly. - return currentTime + 1000; - } else if (priority >= TransitionLongLanePriority) { + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. When + // we made it larger, a product metric in www regressed, suggesting there's + // a user interaction that's being starved by a series of synchronous + // updates. If that theory is correct, the proper solution is to fix the + // starvation. However, this scenario supports the idea that expiration + // times are an important safeguard when starvation does happen. + // + // Also note that, in the case of user input specifically, this will soon no + // longer be an issue because we plan to make user input synchronous by + // default (until you enter `startTransition`, of course.) + // + // If weren't planning to make these updates synchronous soon anyway, I + // would probably make this number a configurable parameter. + return currentTime + 250; + } else if (priority >= TransitionPriority) { return currentTime + 5000; } else { // Anything idle priority or lower should never expire. @@ -5267,6 +5246,9 @@ function includesNonIdleWork(lanes) { } function includesOnlyRetries(lanes) { return (lanes & RetryLanes) === lanes; +} +function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; } // To ensure consistency across multiple updates in the same event, this should // be a pure function, so that it always returns the same lane for given inputs. @@ -5309,9 +5291,7 @@ function findUpdateLane(lanePriority, wipLanes) { if (_lane3 === NoLane) { // If all the default lanes are already being worked on, look for a // lane in the transition range. - _lane3 = pickArbitraryLane( - (TransitionShortLanes | TransitionLongLanes) & ~wipLanes - ); + _lane3 = pickArbitraryLane(TransitionLanes & ~wipLanes); if (_lane3 === NoLane) { // All the transition lanes are taken, too. This should be very @@ -5324,9 +5304,8 @@ function findUpdateLane(lanePriority, wipLanes) { return _lane3; } - case TransitionShortLanePriority: // Should be handled by findTransitionLane instead + case TransitionPriority: // Should be handled by findTransitionLane instead - case TransitionLongLanePriority: case RetryLanePriority: // Should be handled by findRetryLane instead break; @@ -5349,54 +5328,24 @@ function findUpdateLane(lanePriority, wipLanes) { } // To ensure consistency across multiple updates in the same event, this should // be pure function, so that it always returns the same lane for given inputs. -function findTransitionLane(lanePriority, wipLanes, pendingLanes) { - if (lanePriority === TransitionShortLanePriority) { - // First look for lanes that are completely unclaimed, i.e. have no - // pending work. - var lane = pickArbitraryLane(TransitionShortLanes & ~pendingLanes); +function findTransitionLane(wipLanes, pendingLanes) { + // First look for lanes that are completely unclaimed, i.e. have no + // pending work. + var lane = pickArbitraryLane(TransitionLanes & ~pendingLanes); - if (lane === NoLane) { - // If all lanes have pending work, look for a lane that isn't currently - // being worked on. - lane = pickArbitraryLane(TransitionShortLanes & ~wipLanes); - - if (lane === NoLane) { - // If everything is being worked on, pick any lane. This has the - // effect of interrupting the current work-in-progress. - lane = pickArbitraryLane(TransitionShortLanes); - } - } - - return lane; - } - - if (lanePriority === TransitionLongLanePriority) { - // First look for lanes that are completely unclaimed, i.e. have no - // pending work. - var _lane4 = pickArbitraryLane(TransitionLongLanes & ~pendingLanes); - - if (_lane4 === NoLane) { - // If all lanes have pending work, look for a lane that isn't currently - // being worked on. - _lane4 = pickArbitraryLane(TransitionLongLanes & ~wipLanes); + if (lane === NoLane) { + // If all lanes have pending work, look for a lane that isn't currently + // being worked on. + lane = pickArbitraryLane(TransitionLanes & ~wipLanes); - if (_lane4 === NoLane) { - // If everything is being worked on, pick any lane. This has the - // effect of interrupting the current work-in-progress. - _lane4 = pickArbitraryLane(TransitionLongLanes); - } + if (lane === NoLane) { + // If everything is being worked on, pick any lane. This has the + // effect of interrupting the current work-in-progress. + lane = pickArbitraryLane(TransitionLanes); } - - return _lane4; } - { - throw Error( - "Invalid transition priority: " + - lanePriority + - ". This is a bug in React." - ); - } + return lane; } // To ensure consistency across multiple updates in the same event, this should // be pure function, so that it always returns the same lane for given inputs. @@ -5461,7 +5410,15 @@ function laneToLanes(lane) { return lane; } function createLaneMap(initial) { - return new Array(TotalLanes).fill(initial); + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; + + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } + + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But @@ -5502,9 +5459,6 @@ function markRootSuspended(root, suspendedLanes) { function markRootPinged(root, pingedLanes, eventTime) { root.pingedLanes |= root.suspendedLanes & pingedLanes; } -function markRootExpired(root, expiredLanes) { - root.expiredLanes |= expiredLanes & root.pendingLanes; -} function hasDiscreteLanes(lanes) { return (lanes & InputDiscreteLanes) !== NoLanes; } @@ -5588,7 +5542,7 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } @@ -5717,88 +5671,40 @@ function flushSyncCallbackQueueImpl() { isFlushingSyncQueue = true; var i = 0; - try { - var _isSync = true; - var queue = syncQueue; - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediatePriority$1, function() { - for (; i < queue.length; i++) { - var callback = queue[i]; - - do { - callback = callback(_isSync); - } while (callback !== null); - } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick - - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue - ); - throw error; - } finally { - isFlushingSyncQueue = false; + { + try { + var _isSync2 = true; + var _queue = syncQueue; + runWithPriority(ImmediatePriority$1, function() { + for (; i < _queue.length; i++) { + var callback = _queue[i]; + + do { + callback = callback(_isSync2); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick + + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue + ); + throw error; + } finally { + isFlushingSyncQueue = false; + } } } } -function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; - - switch (fiber.tag) { - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); - - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); - - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); - - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); - - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); - - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); - - case Block: - return describeFunctionComponentFrame(fiber.type._render, source, owner); - - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); - - default: - return ""; - } -} - -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; - - do { - info += describeFiber(node); - node = node.return; - } while (node); - - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} +// TODO: this is special because it gets imported during build. +var ReactVersion = "17.0.1-454c2211c"; var NoMode = 0; var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root @@ -5809,6 +5715,12 @@ var ConcurrentMode = 4; var ProfileMode = 8; var DebugTracingMode = 16; +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var NoTransition = 0; +function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; +} + /** * inlined Object.is polyfill to avoid requiring consumers ship their own * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is @@ -5861,6 +5773,55 @@ function shallowEqual(objA, objB) { return true; } +function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; + + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); + + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); + + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); + + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); + + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); + + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); + + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; + } +} + +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; + + do { + info += describeFiber(node); + node = node.return; + } while (node); + + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } +} + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; var current = null; var isRendering = false; @@ -6089,7 +6050,7 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + "\nPlease update the following components: %s", sortedNames @@ -6104,11 +6065,11 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* If you're updating state whenever props change, " + "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + "\nPlease update the following components: %s", _sortedNames ); @@ -6122,7 +6083,7 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "\nPlease update the following components: %s", _sortedNames2 @@ -6134,7 +6095,7 @@ var ReactStrictModeWarnings = { warn( "componentWillMount has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + @@ -6152,11 +6113,11 @@ var ReactStrictModeWarnings = { warn( "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* If you're updating state whenever props change, refactor your " + "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + "To rename all deprecated lifecycles to their new names, you can run " + @@ -6171,7 +6132,7 @@ var ReactStrictModeWarnings = { warn( "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + @@ -6244,7 +6205,7 @@ var ReactStrictModeWarnings = { "\n\nThe old API will be supported in all 16.x releases, but applications " + "using it should migrate to the new version." + "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://fb.me/react-legacy-context", + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", sortedNames ); } finally { @@ -6435,8 +6396,7 @@ function propagateContextChange( // Schedule a force update on the work-in-progress. var update = createUpdate( NoTimestamp, - pickArbitraryLane(renderLanes), - null + pickArbitraryLane(renderLanes) ); update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the // update to the current fiber, too, which means it will persist even if @@ -6622,11 +6582,10 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue = clone; } } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { var update = { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: UpdateState, payload: null, callback: null, @@ -6701,7 +6660,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: update.eventTime, lane: update.lane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, @@ -6793,8 +6751,8 @@ function getStateFromUpdate( } case CaptureUpdate: { - workInProgress.effectTag = - (workInProgress.effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; } // Intentional fallthrough @@ -6920,7 +6878,6 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { var clone = { eventTime: updateEventTime, lane: updateLane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, @@ -6944,21 +6901,13 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { // it. Using NoLane works because 0 is a subset of all bitmasks, so // this will never be skipped by the check above. lane: NoLane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, next: null }; newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reversible value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig(updateEventTime, update.suspenseConfig); // Process this update. + } // Process this update. newState = getStateFromUpdate( workInProgress, @@ -6971,7 +6920,7 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { var callback = update.callback; if (callback !== null) { - workInProgress.effectTag |= Callback; + workInProgress.flags |= Callback; var effects = queue.effects; if (effects === null) { @@ -7063,11 +7012,6 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -function requestCurrentSuspenseConfig() { - return ReactCurrentBatchConfig.suspense; -} - var fakeInternalInstance = {}; var isArray = Array.isArray; // React.Component uses a shared frozen object by default. // We'll use it to determine whether we need to initialize legacy refs. @@ -7192,9 +7136,8 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.payload = payload; if (callback !== undefined && callback !== null) { @@ -7211,9 +7154,8 @@ var classComponentUpdater = { enqueueReplaceState: function(inst, payload, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ReplaceState; update.payload = payload; @@ -7231,9 +7173,8 @@ var classComponentUpdater = { enqueueForceUpdate: function(inst, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ForceUpdate; if (callback !== undefined && callback !== null) { @@ -7693,7 +7634,7 @@ function constructClassInstance(workInProgress, ctor, props) { "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + "The above lifecycles should be removed. Learn more about this warning here:\n" + - "https://fb.me/react-unsafe-component-lifecycles", + "https://reactjs.org/link/unsafe-component-lifecycles", _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : "", @@ -7855,7 +7796,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -7917,7 +7858,7 @@ function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } return false; @@ -7963,13 +7904,13 @@ function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // If shouldComponentUpdate returned false, we should still update the // memoized state to indicate that this work can be reused. @@ -8057,7 +7998,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -8066,7 +8007,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -8113,11 +8054,11 @@ function updateClassInstance( } if (typeof instance.componentDidUpdate === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } else { // If an update was already in progress, we should schedule an Update @@ -8127,7 +8068,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -8136,7 +8077,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -8199,7 +8140,7 @@ var warnForMissingKey = function(child, returnFiber) {}; error( "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + "more information." ); }; @@ -8237,7 +8178,7 @@ function coerceRef(returnFiber, current, element) { "String refs are a source of potential bugs and should be avoided. " + "We recommend using useRef() or createRef() instead. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-string-ref", + "https://reactjs.org/link/strict-mode-string-ref", mixedRef ); } @@ -8256,7 +8197,7 @@ function coerceRef(returnFiber, current, element) { if (!(ownerFiber.tag === ClassComponent)) { throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); } @@ -8310,7 +8251,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + mixedRef + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } } @@ -8349,7 +8290,7 @@ function warnOnFunctionType(returnFiber) { "Or maybe you meant to call this function rather than return it." ); } -} // We avoid inlining this to avoid potential deopts from using try/catch. +} // This wrapper function exists because I expect to clone the code in each path // to be able to optimize each path individually by branching early. This needs // a compiler or we can do it manually. Helpers that don't need this branching // live outside of this function. @@ -8375,7 +8316,7 @@ function ChildReconciler(shouldTrackSideEffects) { } childToDelete.nextEffect = null; - childToDelete.effectTag = Deletion; + childToDelete.flags = Deletion; } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -8439,7 +8380,7 @@ function ChildReconciler(shouldTrackSideEffects) { if (oldIndex < lastPlacedIndex) { // This is a move. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } else { // This item can stay in place. @@ -8447,7 +8388,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } else { // This is an insertion. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } } @@ -8456,7 +8397,7 @@ function ChildReconciler(shouldTrackSideEffects) { // This is simpler for the single child case. We only need to do a // placement for inserting new children. if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.effectTag = Placement; + newFiber.flags = Placement; } return newFiber; @@ -9207,11 +9148,6 @@ function ChildReconciler(shouldTrackSideEffects) { break; } - case Block: - - // We intentionally fallthrough here if enableBlocksAPI is not on. - // eslint-disable-next-lined no-fallthrough - default: { if ( child.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -9219,17 +9155,17 @@ function ChildReconciler(shouldTrackSideEffects) { ) { deleteRemainingChildren(returnFiber, child.sibling); - var _existing3 = useFiber(child, element.props); + var _existing = useFiber(child, element.props); - _existing3.ref = coerceRef(returnFiber, child, element); - _existing3.return = returnFiber; + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; { - _existing3._debugSource = element._source; - _existing3._debugOwner = element._owner; + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; } - return _existing3; + return _existing; } break; @@ -9410,12 +9346,12 @@ function ChildReconciler(shouldTrackSideEffects) { // functions and classes // eslint-disable-next-lined no-fallthrough - case FunctionComponent: { - var Component = returnFiber.type; - + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { { throw Error( - (Component.displayName || Component.name || "Component") + + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." ); } @@ -9579,13 +9515,6 @@ function popSuspenseContext(fiber) { pop(suspenseStackCursor, fiber); } -// A non-null SuspenseState means that it is blocked for one reason or another. -// - A non-null dehydrated field means it's blocked pending hydration. -// - A non-null dehydrated field can use isSuspenseInstancePending or -// isSuspenseInstanceFallback to query the reason for being dehydrated. -// - A null dehydrated field means it's blocked by something suspending and -// we're currently showing a fallback instead. - function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { // If it was the primary children that just suspended, capture and render the // fallback. Otherwise, don't capture and bubble to the next boundary. @@ -9640,7 +9569,7 @@ function findFirstSuspended(row) { // keep track of whether it suspended or not. node.memoizedProps.revealOrder !== undefined ) { - var didSuspend = (node.effectTag & DidCapture) !== NoEffect; + var didSuspend = (node.flags & DidCapture) !== NoFlags; if (didSuspend) { return node; @@ -9670,7 +9599,7 @@ function findFirstSuspended(row) { return null; } -var NoEffect$1 = +var NoFlags$1 = /* */ 0; // Represents whether effect should fire. @@ -9894,7 +9823,7 @@ function warnOnHookMismatchInDev(currentHookName) { error( "React has detected a change in the order of Hooks called by %s. " + "This will lead to bugs and errors if not fixed. " + - "For more information, read the Rules of Hooks: https://fb.me/rules-of-hooks\n\n" + + "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + " Previous render Next render\n" + " ------------------------------------------------------\n" + "%s" + @@ -9910,7 +9839,7 @@ function warnOnHookMismatchInDev(currentHookName) { function throwInvalidHookError() { { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } } @@ -10080,7 +10009,7 @@ function renderWithHooks( } function bailoutHooks(current, workInProgress, lanes) { workInProgress.updateQueue = current.updateQueue; - workInProgress.effectTag &= ~(Passive | Update); + workInProgress.flags &= ~(Passive | Update); current.lanes = removeLanes(current.lanes, lanes); } function resetHooksAfterThrow() { @@ -10296,18 +10225,14 @@ function updateReducer(reducer, initialArg, init) { var update = first; do { - var suspenseConfig = update.suspenseConfig; var updateLane = update.lane; - var updateEventTime = update.eventTime; if (!isSubsetOfLanes(renderLanes, updateLane)) { // Priority is insufficient. Skip this update. If this is the first // skipped update, the previous update/state is the new base // update/state. var clone = { - eventTime: updateEventTime, lane: updateLane, - suspenseConfig: suspenseConfig, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, @@ -10332,26 +10257,17 @@ function updateReducer(reducer, initialArg, init) { // This update does have sufficient priority. if (newBaseQueueLast !== null) { var _clone = { - eventTime: updateEventTime, // This update is going to be committed so we never want uncommit // it. Using NoLane works because 0 is a subset of all bitmasks, so // this will never be skipped by the check above. lane: NoLane, - suspenseConfig: update.suspenseConfig, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }; newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reversible value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig); // Process this update. + } // Process this update. if (update.eagerReducer === reducer) { // If this update was processed eagerly, and its reducer matches the @@ -10578,8 +10494,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { if (!objectIs(snapshot, maybeNewSnapshot)) { setSnapshot(maybeNewSnapshot); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); markRootMutableRead(root, lane); } // If the source mutated between render and now, // there may be state updates already scheduled from the old source. @@ -10600,8 +10515,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { try { latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); markRootMutableRead(root, lane); } catch (error) { // A selector might throw after a source mutation. @@ -10750,16 +10664,14 @@ function pushEffect(tag, create, destroy, deps) { function mountRef(initialValue) { var hook = mountWorkInProgressHook(); - var ref = { - current: initialValue - }; { - Object.seal(ref); + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } - - hook.memoizedState = ref; - return ref; } function updateRef(initialValue) { @@ -10767,19 +10679,19 @@ function updateRef(initialValue) { return hook.memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, undefined, nextDeps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; var destroy = undefined; @@ -10792,15 +10704,15 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { - pushEffect(hookEffectTag, create, destroy, nextDeps); + pushEffect(hookFlags, create, destroy, nextDeps); return; } } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, destroy, nextDeps @@ -10960,128 +10872,124 @@ function updateMemo(nextCreate, deps) { return nextValue; } -function mountDeferredValue(value, config) { +function mountDeferredValue(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function updateDeferredValue(value, config) { +function updateDeferredValue(value) { var _updateState = updateState(), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function rerenderDeferredValue(value, config) { +function rerenderDeferredValue(value) { var _rerenderState = rerenderState(), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); - runWithPriority( - priorityLevel < UserBlockingPriority$1 - ? UserBlockingPriority$1 - : priorityLevel, - function() { - setPending(true); - } - ); // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. - runWithPriority( - priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, - function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + { + runWithPriority( + priorityLevel < UserBlockingPriority$1 + ? UserBlockingPriority$1 + : priorityLevel, + function() { + setPending(true); } - } - ); + ); + runWithPriority( + priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, + function() { + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; + + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig$1.transition = prevTransition; + } + } + ); + } } -function mountTransition(config) { +function mountTransition() { var _mountState2 = mountState(false), isPending = _mountState2[0], - setPending = _mountState2[1]; + setPending = _mountState2[1]; // The `start` method never changes. - var start = mountCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; return [start, isPending]; } -function updateTransition(config) { +function updateTransition() { var _updateState2 = updateState(), - isPending = _updateState2[0], - setPending = _updateState2[1]; + isPending = _updateState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } -function rerenderTransition(config) { +function rerenderTransition() { var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0], - setPending = _rerenderState2[1]; + isPending = _rerenderState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } @@ -11145,12 +11053,9 @@ function dispatchAction(fiber, queue, action) { } var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); var update = { - eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, action: action, eagerReducer: null, eagerState: null, @@ -11268,7 +11173,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + "You can only call Hooks at the top level of your React function. " + "For more information, see " + - "https://fb.me/rules-of-hooks" + "https://reactjs.org/link/rules-of-hooks" ); }; @@ -11352,15 +11257,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11449,15 +11354,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11546,15 +11451,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11643,15 +11548,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11751,17 +11656,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11863,17 +11768,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11975,17 +11880,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -12203,7 +12108,7 @@ function updateForwardRef( return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12268,7 +12173,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -12309,7 +12214,7 @@ function updateMemoComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; var newChild = createWorkInProgress(currentChild, nextProps); newChild.ref = workInProgress.ref; newChild.return = workInProgress; @@ -12392,10 +12297,7 @@ function updateSimpleMemoComponent( workInProgress, renderLanes ); - } else if ( - (current.effectTag & ForceUpdateForLegacySuspense) !== - NoEffect - ) { + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { // This is a special case that only exists for legacy mode. // See https://github.com/facebook/react/pull/19216. didReceiveUpdate = true; @@ -12504,7 +12406,7 @@ function updateMode(current, workInProgress, renderLanes) { function updateProfiler(current, workInProgress, renderLanes) { { - workInProgress.effectTag |= Update; // Reset effect durations for the next eventual effect phase. + workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, var stateNode = workInProgress.stateNode; @@ -12526,7 +12428,7 @@ function markRef(current, workInProgress) { (current !== null && current.ref !== ref) ) { // Schedule a Ref effect - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } } @@ -12601,7 +12503,7 @@ function updateFunctionComponent( return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12654,7 +12556,7 @@ function updateClassComponent( current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // In the initial pass we might need to construct the instance. constructClassInstance(workInProgress, Component, nextProps); @@ -12716,7 +12618,7 @@ function finishClassComponent( ) { // Refs should update even if shouldComponentUpdate returns false markRef(current, workInProgress); - var didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; if (!shouldUpdate && !didCaptureError) { // Context providers should defer to sCU for rendering @@ -12765,7 +12667,7 @@ function finishClassComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; if (current !== null && didCaptureError) { // If we're recovering from an error, reconcile without reusing any of @@ -12852,7 +12754,7 @@ function updateHostRoot(current, workInProgress, renderLanes) { // Conceptually this is similar to Placement in that a new subtree is // inserted into the React tree here. It just happens to not need DOM // mutations because it already exists. - node.effectTag = (node.effectTag & ~Placement) | Hydrating; + node.flags = (node.flags & ~Placement) | Hydrating; node = node.sibling; } } else { @@ -12875,7 +12777,7 @@ function updateHostComponent(current, workInProgress, renderLanes) { if (prevProps !== null && shouldSetTextContent()) { // If we're switching from a direct text child to a normal child, or to // empty, we need to schedule the text content to be reset. - workInProgress.effectTag |= ContentReset; + workInProgress.flags |= ContentReset; } markRef(current, workInProgress); @@ -12904,7 +12806,7 @@ function mountLazyComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -13038,7 +12940,7 @@ function mountIncompleteClassComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // Promote the fiber to a class and try rendering again. workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` @@ -13082,7 +12984,7 @@ function mountIndeterminateComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -13132,7 +13034,7 @@ function mountIndeterminateComponent( setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; { // Support for module components is deprecated and is removed behind a flag. @@ -13346,7 +13248,7 @@ function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { return { baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes) }; -} +} // TODO: Probably should inline this back function shouldRemainOnFallback( suspenseContext, @@ -13382,19 +13284,19 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { { if (shouldSuspend(workInProgress)) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } } var suspenseContext = suspenseStackCursor.current; var showFallback = false; - var didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { // Something in this boundary's subtree already suspended. Switch to // rendering the fallback children. showFallback = true; - workInProgress.effectTag &= ~DidCapture; + workInProgress.flags &= ~DidCapture; } else { // Attempting the main content if (current === null || current.memoizedState !== null) { @@ -13445,9 +13347,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { // But only if this has a fallback. if (nextProps.fallback !== undefined); + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + if (showFallback) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; var fallbackFragment = mountSuspenseFallbackChildren( workInProgress, nextPrimaryChildren, @@ -13460,11 +13363,41 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { ); workInProgress.memoizedState = SUSPENDED_MARKER; return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + + return _fallbackFragment; } else { - var _nextPrimaryChildren = nextProps.children; return mountSuspensePrimaryChildren( workInProgress, - _nextPrimaryChildren, + nextPrimaryChildren, renderLanes ); } @@ -13477,63 +13410,63 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { if (prevState !== null) { if (showFallback) { var _nextFallbackChildren2 = nextProps.fallback; - var _nextPrimaryChildren3 = nextProps.children; + var _nextPrimaryChildren2 = nextProps.children; var _fallbackChildFragment = updateSuspenseFallbackChildren( current, workInProgress, - _nextPrimaryChildren3, + _nextPrimaryChildren2, _nextFallbackChildren2, renderLanes ); - var _primaryChildFragment2 = workInProgress.child; + var _primaryChildFragment3 = workInProgress.child; var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = + _primaryChildFragment3.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes ); workInProgress.memoizedState = SUSPENDED_MARKER; return _fallbackChildFragment; } else { - var _nextPrimaryChildren4 = nextProps.children; + var _nextPrimaryChildren3 = nextProps.children; - var _primaryChildFragment3 = updateSuspensePrimaryChildren( + var _primaryChildFragment4 = updateSuspensePrimaryChildren( current, workInProgress, - _nextPrimaryChildren4, + _nextPrimaryChildren3, renderLanes ); workInProgress.memoizedState = null; - return _primaryChildFragment3; + return _primaryChildFragment4; } } else { // The current tree is not already showing a fallback. if (showFallback) { // Timed out. var _nextFallbackChildren3 = nextProps.fallback; - var _nextPrimaryChildren5 = nextProps.children; + var _nextPrimaryChildren4 = nextProps.children; var _fallbackChildFragment2 = updateSuspenseFallbackChildren( current, workInProgress, - _nextPrimaryChildren5, + _nextPrimaryChildren4, _nextFallbackChildren3, renderLanes ); - var _primaryChildFragment4 = workInProgress.child; + var _primaryChildFragment5 = workInProgress.child; var _prevOffscreenState = current.child.memoizedState; - _primaryChildFragment4.memoizedState = + _primaryChildFragment5.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); - _primaryChildFragment4.childLanes = getRemainingWorkInPrimaryTree( + _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes ); // Skip the primary children, and continue working on the @@ -13544,17 +13477,17 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { } else { // Still haven't timed out. Continue rendering the children, like we // normally do. - var _nextPrimaryChildren6 = nextProps.children; + var _nextPrimaryChildren5 = nextProps.children; - var _primaryChildFragment5 = updateSuspensePrimaryChildren( + var _primaryChildFragment6 = updateSuspensePrimaryChildren( current, workInProgress, - _nextPrimaryChildren6, + _nextPrimaryChildren5, renderLanes ); workInProgress.memoizedState = null; - return _primaryChildFragment5; + return _primaryChildFragment6; } } } @@ -13674,7 +13607,7 @@ function updateSuspensePrimaryChildren( if (currentFallbackChildFragment !== null) { // Delete the fallback child fragment currentFallbackChildFragment.nextEffect = null; - currentFallbackChildFragment.effectTag = Deletion; + currentFallbackChildFragment.flags = Deletion; workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment; } @@ -13765,7 +13698,7 @@ function updateSuspenseFallbackChildren( ); // Needs a placement effect because the parent (the Suspense boundary) already // mounted but this is a new fiber. - fallbackChildFragment.effectTag |= Placement; + fallbackChildFragment.flags |= Placement; } fallbackChildFragment.return = workInProgress; @@ -14028,7 +13961,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }; @@ -14039,7 +13971,6 @@ function initSuspenseListRenderState( renderState.renderingStartTime = 0; renderState.last = lastContentRow; renderState.tail = tail; - renderState.tailExpiration = 0; renderState.tailMode = tailMode; renderState.lastEffect = lastEffectBeforeRendering; } @@ -14071,10 +14002,10 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { suspenseContext, ForceSuspenseFallback ); - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } else { var didSuspendBefore = - current !== null && (current.effectTag & DidCapture) !== NoEffect; + current !== null && (current.flags & DidCapture) !== NoFlags; if (didSuspendBefore) { // If we previously forced a fallback, we need to schedule work @@ -14316,7 +14247,7 @@ function updateContextConsumer(current, workInProgress, renderLanes) { setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } @@ -14399,8 +14330,8 @@ function remountFiber(current, oldWorkInProgress, newWorkInProgress) { } current.nextEffect = null; - current.effectTag = Deletion; - newWorkInProgress.effectTag |= Placement; // Restart work from the new fiber. + current.flags = Deletion; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. return newWorkInProgress; } @@ -14485,7 +14416,7 @@ function beginWork(current, workInProgress, renderLanes) { ); if (hasChildWork) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, @@ -14549,7 +14480,7 @@ function beginWork(current, workInProgress, renderLanes) { } case SuspenseListComponent: { - var didSuspendBefore = (current.effectTag & DidCapture) !== NoEffect; + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; var _hasChildWork = includesSomeLane( renderLanes, @@ -14572,7 +14503,7 @@ function beginWork(current, workInProgress, renderLanes) { // them got retried so they'll still be blocked in the same way // as before. We can fast bail out. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } // If nothing suspended before and we're rendering the same children, // then the tail doesn't matter. Anything new that suspends will work // in the "together" mode, so we can continue from the state we had. @@ -14616,7 +14547,7 @@ function beginWork(current, workInProgress, renderLanes) { return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else { - if ((current.effectTag & ForceUpdateForLegacySuspense) !== NoEffect) { + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { // This is a special case that only exists for legacy mode. // See https://github.com/facebook/react/pull/19216. didReceiveUpdate = true; @@ -14814,10 +14745,6 @@ function beginWork(current, workInProgress, renderLanes) { break; } - case Block: { - break; - } - case OffscreenComponent: { return updateOffscreenComponent(current, workInProgress, renderLanes); } @@ -14839,11 +14766,11 @@ function beginWork(current, workInProgress, renderLanes) { function markUpdate(workInProgress) { // Tag the fiber with an update effect. This turns a Placement into // a PlacementAndUpdate. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } function markRef$1(workInProgress) { - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } var appendAllChildren; @@ -14888,7 +14815,7 @@ var updateHostText$1; appendInitialChild(parent, _instance); } else if (node.tag === HostPortal); else if (node.tag === SuspenseComponent) { - if ((node.effectTag & Update) !== NoEffect) { + if ((node.flags & Update) !== NoFlags) { // Need to toggle the visibility of the primary children. var newIsHidden = node.memoizedState !== null; @@ -14983,7 +14910,7 @@ var updateHostText$1; appendChildToContainerChildSet(containerChildSet, _instance3); } else if (node.tag === HostPortal); else if (node.tag === SuspenseComponent) { - if ((node.effectTag & Update) !== NoEffect) { + if ((node.flags & Update) !== NoFlags) { // Need to toggle the visibility of the primary children. var newIsHidden = node.memoizedState !== null; @@ -15264,7 +15191,7 @@ function completeWork(current, workInProgress, renderLanes) { // This handles the case of React rendering into a container with previous children. // It's also safe to do for updates too, because current.child would only be null // if the previous render was null (so the the container would already be empty). - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -15380,7 +15307,7 @@ function completeWork(current, workInProgress, renderLanes) { popSuspenseContext(workInProgress); var nextState = workInProgress.memoizedState; - if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + if ((workInProgress.flags & DidCapture) !== NoFlags) { // Something suspended. Re-render with the fallback children. workInProgress.lanes = renderLanes; // Do not reset the effect list. @@ -15443,7 +15370,7 @@ function completeWork(current, workInProgress, renderLanes) { // If this boundary just timed out, schedule an effect to attach a // retry listener to the promise. This flag is also used to hide the // primary children. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -15487,8 +15414,7 @@ function completeWork(current, workInProgress, renderLanes) { return null; } - var didSuspendAlready = - (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; var renderedTail = renderState.rendering; if (renderedTail === null) { @@ -15505,7 +15431,7 @@ function completeWork(current, workInProgress, renderLanes) { // findFirstSuspended. var cannotBeSuspended = renderHasNotSuspendedYet() && - (current === null || (current.effectTag & DidCapture) === NoEffect); + (current === null || (current.flags & DidCapture) === NoFlags); if (!cannotBeSuspended) { var row = workInProgress.child; @@ -15515,7 +15441,7 @@ function completeWork(current, workInProgress, renderLanes) { if (suspended !== null) { didSuspendAlready = true; - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to // its thennables. Instead, we'll transfer its thennables to the @@ -15533,7 +15459,7 @@ function completeWork(current, workInProgress, renderLanes) { if (newThennables !== null) { workInProgress.updateQueue = newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect list before doing the second pass since that's now invalid. @@ -15560,6 +15486,28 @@ function completeWork(current, workInProgress, renderLanes) { row = row.sibling; } } + + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + } } else { cutOffTailIfNeeded(renderState, false); } // Next we're going to render the tail. @@ -15569,7 +15517,7 @@ function completeWork(current, workInProgress, renderLanes) { var _suspended = findFirstSuspended(renderedTail); if (_suspended !== null) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. @@ -15577,7 +15525,7 @@ function completeWork(current, workInProgress, renderLanes) { if (_newThennables !== null) { workInProgress.updateQueue = _newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } cutOffTailIfNeeded(renderState, true); // This might have been modified. @@ -15601,27 +15549,31 @@ function completeWork(current, workInProgress, renderLanes) { return null; } } else if ( - // The time it took to render last row is greater than time until - // the expiration. + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. now() * 2 - renderState.renderingStartTime > - renderState.tailExpiration && + getRenderTargetTime() && renderLanes !== OffscreenLane ) { // We have now passed our CPU deadline and we'll just give up further // attempts to render the main content and only render fallbacks. // The assumption is that this is usually faster. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. If we can show - // them, then they really have the same priority as this render. - // So we'll pick it back up the very next render pass once we've had - // an opportunity to yield for paint. + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - workInProgress.lanes = renderLanes; + workInProgress.lanes = SomeRetryLane; { - markSpawnedWork(renderLanes); + markSpawnedWork(SomeRetryLane); } } } @@ -15649,18 +15601,7 @@ function completeWork(current, workInProgress, renderLanes) { if (renderState.tail !== null) { // We still have tail rows to render. - if (renderState.tailExpiration === 0) { - // Heuristic for how long we're willing to spend rendering rows - // until we just give up and show what we have so far. - var TAIL_EXPIRATION_TIMEOUT_MS = 500; - renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS; // TODO: This is meant to mimic the train model or JND but this - // is a per component value. It should really be since the start - // of the total render or last commit. Consider using something like - // globalMostRecentFallbackTime. That doesn't account for being - // suspended for part of the time or when it's a new render. - // It should probably use a global start time value instead. - } // Pop a row. - + // Pop a row. var next = renderState.tail; renderState.rendering = next; renderState.tail = next.sibling; @@ -15697,9 +15638,6 @@ function completeWork(current, workInProgress, renderLanes) { break; } - case Block: - break; - case OffscreenComponent: case LegacyHiddenComponent: { popRenderLanes(workInProgress); @@ -15714,7 +15652,7 @@ function completeWork(current, workInProgress, renderLanes) { prevIsHidden !== nextIsHidden && newProps.mode !== "unstable-defer-without-hiding" ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -15740,10 +15678,10 @@ function unwindWork(workInProgress, renderLanes) { popContext(workInProgress); } - var effectTag = workInProgress.effectTag; + var flags = workInProgress.flags; - if (effectTag & ShouldCapture) { - workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; if ((workInProgress.mode & ProfileMode) !== NoMode) { transferActualDuration(workInProgress); @@ -15759,15 +15697,15 @@ function unwindWork(workInProgress, renderLanes) { popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); resetWorkInProgressVersions(); - var _effectTag = workInProgress.effectTag; + var _flags = workInProgress.flags; - if (!((_effectTag & DidCapture) === NoEffect)) { + if (!((_flags & DidCapture) === NoFlags)) { throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); } - workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; return workInProgress; } @@ -15780,10 +15718,10 @@ function unwindWork(workInProgress, renderLanes) { case SuspenseComponent: { popSuspenseContext(workInProgress); - var _effectTag2 = workInProgress.effectTag; + var _flags2 = workInProgress.flags; - if (_effectTag2 & ShouldCapture) { - workInProgress.effectTag = (_effectTag2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. if ((workInProgress.mode & ProfileMode) !== NoMode) { transferActualDuration(workInProgress); @@ -15950,7 +15888,7 @@ function logCapturedError(boundary, errorInfo) { } else { errorBoundaryMessage = "Consider adding an error boundary to your tree to customize error handling behavior.\n" + - "Visit https://fb.me/react-error-boundaries to learn more about error boundaries."; + "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; } var combinedMessage = @@ -15984,7 +15922,7 @@ function logCapturedError(boundary, errorInfo) { var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane, null); // Unmount the root by rendering null. + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property // being called "element". @@ -16003,7 +15941,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { } function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane, null); + var update = createUpdate(NoTimestamp, lane); update.tag = CaptureUpdate; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; @@ -16101,7 +16039,7 @@ function throwException( rootRenderLanes ) { // The source fiber did not complete. - sourceFiber.effectTag |= Incomplete; // Its effect list is no longer valid. + sourceFiber.flags |= Incomplete; // Its effect list is no longer valid. sourceFiber.firstEffect = sourceFiber.lastEffect = null; @@ -16161,12 +16099,12 @@ function throwException( // should *not* suspend the commit. if ((_workInProgress.mode & BlockingMode) === NoMode) { - _workInProgress.effectTag |= DidCapture; - sourceFiber.effectTag |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + _workInProgress.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. // But we shouldn't call any lifecycle methods or callbacks. Remove // all lifecycle effect tags. - sourceFiber.effectTag &= ~(LifecycleEffectMask | Incomplete); + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); if (sourceFiber.tag === ClassComponent) { var currentSourceFiber = sourceFiber.alternate; @@ -16180,7 +16118,7 @@ function throwException( // When we try rendering again, we should not reuse the current fiber, // since it's known to be in an inconsistent state. Use a force update to // prevent a bail out. - var update = createUpdate(NoTimestamp, SyncLane, null); + var update = createUpdate(NoTimestamp, SyncLane); update.tag = ForceUpdate; enqueueUpdate(sourceFiber, update); } @@ -16215,8 +16153,8 @@ function throwException( // that we can show the initial loading state as quickly as possible. // // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. SuspenseConfig applies to - // this case. If none is defined, JND is used instead. + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. // // If we're already showing a fallback and it gets "retried", allowing us to show // another level, but there's still an inner boundary that would show a fallback, @@ -16232,7 +16170,7 @@ function throwException( // ensure that new initial loading states can commit as soon as possible. attachPingListener(root, wakeable, rootRenderLanes); - _workInProgress.effectTag |= ShouldCapture; + _workInProgress.flags |= ShouldCapture; _workInProgress.lanes = rootRenderLanes; return; } // This boundary already captured during this render. Continue to the next @@ -16261,7 +16199,7 @@ function throwException( switch (workInProgress.tag) { case HostRoot: { var _errorInfo = value; - workInProgress.effectTag |= ShouldCapture; + workInProgress.flags |= ShouldCapture; var lane = pickArbitraryLane(rootRenderLanes); workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); @@ -16278,13 +16216,13 @@ function throwException( var instance = workInProgress.stateNode; if ( - (workInProgress.effectTag & DidCapture) === NoEffect && + (workInProgress.flags & DidCapture) === NoFlags && (typeof ctor.getDerivedStateFromError === "function" || (instance !== null && typeof instance.componentDidCatch === "function" && !isAlreadyFailedLegacyErrorBoundary(instance))) ) { - workInProgress.effectTag |= ShouldCapture; + workInProgress.flags |= ShouldCapture; var _lane = pickArbitraryLane(rootRenderLanes); @@ -16347,7 +16285,9 @@ function safelyDetachRef(current) { if (ref !== null) { if (typeof ref === "function") { { - invokeGuardedCallback(null, ref, null, null); + { + invokeGuardedCallback(null, ref, null, null); + } if (hasCaughtError()) { var refError = clearCaughtError(); @@ -16375,13 +16315,12 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { return; } case ClassComponent: { - if (finishedWork.effectTag & Snapshot) { + if (finishedWork.flags & Snapshot) { if (current !== null) { var prevProps = current.memoizedProps; var prevState = current.memoizedState; @@ -16526,7 +16465,7 @@ function commitHookEffectListMount(tag, finishedWork) { " }\n" + " fetchData();\n" + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + - "Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching"; + "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; } else { addendum = " You returned: " + destroy; } @@ -16558,10 +16497,7 @@ function schedulePassiveEffects(finishedWork) { next = _effect.next, tag = _effect.tag; - if ( - (tag & Passive$1) !== NoEffect$1 && - (tag & HasEffect) !== NoEffect$1 - ) { + if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) { enqueuePendingPassiveHookEffectUnmount(finishedWork, effect); enqueuePendingPassiveHookEffectMount(finishedWork, effect); } @@ -16575,8 +16511,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // At this point layout effects have already been destroyed (during mutation phase). // This is done to prevent sibling component effects from interfering with each other, // e.g. a destroy function in one component should never override a ref set @@ -16592,7 +16527,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { case ClassComponent: { var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update) { + if (finishedWork.flags & Update) { if (current === null) { // We could update instance props and state here, // but instead we rely on them being set during last render. @@ -16750,7 +16685,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { // These effects should only be committed when components are first mounted, // aka when there is no current/alternate. - if (current === null && finishedWork.effectTag & Update) { + if (current === null && finishedWork.flags & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; commitMount(); @@ -16832,7 +16767,9 @@ function commitAttachRef(finishedWork) { } // Moved outside to ensure DCE works with this flag if (typeof ref === "function") { - ref(instanceToUse); + { + ref(instanceToUse); + } } else { { if (!ref.hasOwnProperty("current")) { @@ -16854,7 +16791,9 @@ function commitDetachRef(current) { if (currentRef !== null) { if (typeof currentRef === "function") { - currentRef(null); + { + currentRef(null); + } } else { currentRef.current = null; } @@ -16870,8 +16809,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { var updateQueue = current.updateQueue; if (updateQueue !== null) { @@ -16887,7 +16825,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { tag = _effect2.tag; if (destroy !== undefined) { - if ((tag & Passive$1) !== NoEffect$1) { + if ((tag & Passive$1) !== NoFlags$1) { enqueuePendingPassiveHookEffectUnmount(current, effect); } else { { @@ -17065,8 +17003,7 @@ function commitWork(current, finishedWork) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // Layout effects are destroyed during the mutation phase so that all // destroy functions for all fibers are called before any create functions. // This prevents sibling component effects from interfering with each other, @@ -17231,9 +17168,7 @@ var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root complet var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown -var workInProgressRootFatalError = null; -var workInProgressRootLatestSuspenseTimeout = NoTimestamp; -var workInProgressRootCanSuspendUsingConfig = null; // "Included" lanes refer to lanes that were worked on during this render. It's +var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's // slightly different than `renderLanes` because `renderLanes` can change as you // enter and exit an Offscreen tree. This value is the combination of all render // lanes for the entire render phase. @@ -17250,8 +17185,21 @@ var mostRecentlyUpdatedRoot = null; // The most recent time we committed a fallb // model where we don't commit new loading states in too quick succession. var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; -var DEFAULT_TIMEOUT_MS = 5000; +var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering +// more and prefer CPU suspense heuristics instead. + +var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU +// suspense heuristics and opt out of rendering more content. + +var RENDER_TIMEOUT_MS = 500; + +function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; +} + +function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; +} var nextEffect = null; var hasUncaughtError = false; var firstUncaughtError = null; @@ -17303,7 +17251,7 @@ function requestEventTime() { currentEventTime = now(); return currentEventTime; } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { // Special cases var mode = fiber.mode; @@ -17332,16 +17280,9 @@ function requestUpdateLane(fiber, suspenseConfig) { currentEventWipLanes = workInProgressRootIncludedLanes; } - if (suspenseConfig !== null) { - // Use the size of the timeout as a heuristic to prioritize shorter - // transitions over longer ones. - // TODO: This will coerce numbers larger than 31 bits to 0. - var timeoutMs = suspenseConfig.timeoutMs; - var transitionLanePriority = - timeoutMs === undefined || (timeoutMs | 0) < 10000 - ? TransitionShortLanePriority - : TransitionLongLanePriority; + var isTransition = requestCurrentTransition() !== NoTransition; + if (isTransition) { if (currentEventPendingLanes !== NoLanes) { currentEventPendingLanes = mostRecentlyUpdatedRoot !== null @@ -17349,11 +17290,7 @@ function requestUpdateLane(fiber, suspenseConfig) { : NoLanes; } - return findTransitionLane( - transitionLanePriority, - currentEventWipLanes, - currentEventPendingLanes - ); + return findTransitionLane(currentEventWipLanes, currentEventPendingLanes); } // TODO: Remove this dependency on the Scheduler priority. // To do that, we're replacing it with an update lane priority. @@ -17466,6 +17403,7 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { // scheduleCallbackForFiber to preserve the ability to schedule a callback // without immediately flushing it. We only do this for user-initiated // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); flushSyncCallbackQueue(); } } @@ -17512,7 +17450,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { { if ( alternate === null && - (sourceFiber.effectTag & (Placement | Hydrating)) !== NoEffect + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags ) { warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } @@ -17529,7 +17467,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { alternate.childLanes = mergeLanes(alternate.childLanes, lane); } else { { - if ((parent.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } } @@ -17615,7 +17553,7 @@ function ensureRootIsScheduled(root, currentTime) { } // This is the entry point for every concurrent task, i.e. anything that // goes through Scheduler. -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { // Since we know we're in a React event, we can clear the current // event time. The next update will compute a new event time. currentEventTime = NoTimestamp; @@ -17650,18 +17588,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if (lanes === NoLanes) { // Defensive coding. This is never expected to happen. return null; - } // TODO: We only check `didTimeout` defensively, to account for a Scheduler - // bug where `shouldYield` sometimes returns `true` even if `didTimeout` is - // true, which leads to an infinite loop. Once the bug in Scheduler is - // fixed, we can remove this, since we track expiration ourselves. - - if (didTimeout) { - // Something expired. Flush synchronously until there's no expired - // work left. - markRootExpired(root, lanes); // This will schedule a synchronous callback. - - ensureRootIsScheduled(root, now()); - return null; } var exitStatus = renderRootConcurrent(root, lanes); @@ -17711,7 +17637,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { var finishedWork = root.current.alternate; root.finishedWork = finishedWork; root.finishedLanes = lanes; - finishConcurrentRender(root, finishedWork, exitStatus, lanes); + finishConcurrentRender(root, exitStatus, lanes); } ensureRootIsScheduled(root, now()); @@ -17725,7 +17651,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { return null; } -function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { +function finishConcurrentRender(root, exitStatus, lanes) { switch (exitStatus) { case RootIncomplete: case RootFatalErrored: { @@ -17794,64 +17720,36 @@ function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { case RootSuspendedWithDelay: { markRootSuspended$1(root, lanes); - if ( - // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() - ) { - // We're suspended in a state that should be avoided. We'll try to - // avoid committing it for as long as the timeouts let us. - var _nextLanes = getNextLanes(root, NoLanes); - - if (_nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } - - var _suspendedLanes = root.suspendedLanes; - - if (!isSubsetOfLanes(_suspendedLanes, lanes)) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - // FIXME: What if the suspended lanes are Idle? Should not restart. - var _eventTime = requestEventTime(); - - markRootPinged(root, _suspendedLanes); - break; - } + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + break; + } + if (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; - var _msUntilTimeout; - - if (workInProgressRootLatestSuspenseTimeout !== NoTimestamp) { - // We have processed a suspense config whose expiration time we - // can use as the timeout. - _msUntilTimeout = workInProgressRootLatestSuspenseTimeout - now(); - } else if (mostRecentEventTime === NoTimestamp) { - // This should never normally happen because only new updates - // cause delayed states, so we should have processed something. - // However, this could also happen in an offscreen tree. - _msUntilTimeout = 0; - } else { - // If we didn't process a suspense config, compute a JND based on - // the amount of time elapsed since the most recent event time. - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now() - eventTimeMs; - _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; - } // Don't bother with a very short suspense time. + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. if (_msUntilTimeout > 10) { - // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. + // Instead of committing the fallback immediately, wait for more data + // to arrive. root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), _msUntilTimeout ); break; } - } // The work expired. Commit immediately. + } // Commit the placeholder. commitRoot(root); break; @@ -17859,33 +17757,6 @@ function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { case RootCompleted: { // The work completed. Ready to commit. - var _mostRecentEventTime = getMostRecentEventTime(root, lanes); - - if ( - // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() && - _mostRecentEventTime !== NoTimestamp && - workInProgressRootCanSuspendUsingConfig !== null - ) { - // If we have exceeded the minimum loading delay, which probably - // means we have shown a spinner already, we might have to suspend - // a bit longer to ensure that the spinner is shown for - // enough time. - var _msUntilTimeout2 = computeMsUntilSuspenseLoadingDelay( - _mostRecentEventTime, - workInProgressRootCanSuspendUsingConfig - ); - - if (_msUntilTimeout2 > 10) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout2 - ); - break; - } - } - commitRoot(root); break; } @@ -17998,6 +17869,7 @@ function batchedUpdates$1(fn, a) { if (executionContext === NoContext) { // Flush the immediate callbacks that were scheduled during this batch + resetRenderTimer(); flushSyncCallbackQueue(); } } @@ -18019,20 +17891,20 @@ function flushSync(fn, a) { executionContext |= BatchedContext; - try { - setCurrentUpdateLanePriority(SyncLanePriority); + { + try { + if (fn) { + return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); + } else { + return undefined; + } + } finally { + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - if (fn) { - return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); - } else { - return undefined; + flushSyncCallbackQueue(); } - } finally { - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - - flushSyncCallbackQueue(); } } function pushRenderLanes(fiber, lanes) { @@ -18075,8 +17947,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = RootIncomplete; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = NoTimestamp; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootSkippedLanes = NoLanes; workInProgressRootUpdatedLanes = NoLanes; workInProgressRootPingedLanes = NoLanes; @@ -18155,7 +18025,7 @@ function handleError(root, thrownValue) { } while (true); } -function pushDispatcher(root) { +function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher$2.current; ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; @@ -18190,27 +18060,6 @@ function popInteractions(prevInteractions) { function markCommitTimeOfFallback() { globalMostRecentFallbackTime = now(); } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - // Track the largest/latest timeout deadline in this batch. - // TODO: If there are two transitions in the same batch, shouldn't we - // choose the smaller one? Maybe this is because when an intermediate - // transition is superseded, we should ignore its suspense config, but - // we don't currently. - if (suspenseConfig !== null) { - // If `timeoutMs` is not specified, we default to 5 seconds. We have to - // resolve this default here because `suspenseConfig` is owned - // by userspace. - // TODO: Store this on the root instead (transition -> timeoutMs) - // TODO: Should this default to a JND instead? - var timeoutMs = suspenseConfig.timeoutMs | 0 || DEFAULT_TIMEOUT_MS; - var timeoutTime = eventTime + timeoutMs; - - if (timeoutTime > workInProgressRootLatestSuspenseTimeout) { - workInProgressRootLatestSuspenseTimeout = timeoutTime; - workInProgressRootCanSuspendUsingConfig = suspenseConfig; - } - } -} function markSkippedUpdateLanes(lane) { workInProgressRootSkippedLanes = mergeLanes( lane, @@ -18320,6 +18169,7 @@ function renderRootConcurrent(root, lanes) { // and prepare a fresh one. Otherwise we'll continue where we left off. if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + resetRenderTimer(); prepareFreshStack(root, lanes); startWorkOnPendingInteractions(root, lanes); } @@ -18403,7 +18253,7 @@ function completeUnitOfWork(unitOfWork) { var current = completedWork.alternate; var returnFiber = completedWork.return; // Check if the work completed or if something threw. - if ((completedWork.effectTag & Incomplete) === NoEffect) { + if ((completedWork.flags & Incomplete) === NoFlags) { setCurrentFiber(completedWork); var next = void 0; @@ -18428,7 +18278,7 @@ function completeUnitOfWork(unitOfWork) { if ( returnFiber !== null && // Do not append effects to parents if a sibling failed to complete - (returnFiber.effectTag & Incomplete) === NoEffect + (returnFiber.flags & Incomplete) === NoFlags ) { // Append all the effects of the subtree and this fiber onto the effect // list of the parent. The completion order of the children affects the @@ -18450,11 +18300,11 @@ function completeUnitOfWork(unitOfWork) { // reusing children we'll schedule this effect onto itself since we're // at the end. - var effectTag = completedWork.effectTag; // Skip both NoWork and PerformedWork tags when creating the effect + var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect // list. PerformedWork effect is read by React DevTools but shouldn't be // committed. - if (effectTag > PerformedWork) { + if (flags > PerformedWork) { if (returnFiber.lastEffect !== null) { returnFiber.lastEffect.nextEffect = completedWork; } else { @@ -18475,7 +18325,7 @@ function completeUnitOfWork(unitOfWork) { // back here again. // Since we're restarting, remove anything that is not a host effect // from the effect tag. - _next.effectTag &= HostEffectMask; + _next.flags &= HostEffectMask; workInProgress = _next; return; } @@ -18498,7 +18348,7 @@ function completeUnitOfWork(unitOfWork) { if (returnFiber !== null) { // Mark the parent fiber as incomplete and clear its effect list. returnFiber.firstEffect = returnFiber.lastEffect = null; - returnFiber.effectTag |= Incomplete; + returnFiber.flags |= Incomplete; } } @@ -18663,14 +18513,11 @@ function commitRootImpl(root, renderPriorityLevel) { workInProgressRoot = null; workInProgress = null; workInProgressRootRenderLanes = NoLanes; - } // This indicates that the last root we worked on is not the same one that - // we're committing now. This most commonly happens when a suspended root - // times out. - // Get the list of effects. + } // Get the list of effects. var firstEffect; - if (finishedWork.effectTag > PerformedWork) { + if (finishedWork.flags > PerformedWork) { // A fiber's effect list consists only of its children, not itself. So if // the root has an effect, we need to add it to the end of the list. The // resulting list is the set that would belong to the root's parent, if it @@ -18788,7 +18635,7 @@ function commitRootImpl(root, renderPriorityLevel) { popInteractions(prevInteractions); } - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + executionContext = prevExecutionContext; } else { // No effects. root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were @@ -18819,7 +18666,7 @@ function commitRootImpl(root, renderPriorityLevel) { var nextNextEffect = nextEffect.nextEffect; nextEffect.nextEffect = null; - if (nextEffect.effectTag & Deletion) { + if (nextEffect.flags & Deletion) { detachFiberAfterEffects(nextEffect); } @@ -18905,7 +18752,7 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { - if ((nextEffect.effectTag & Deletion) !== NoEffect) { + if ((nextEffect.flags & Deletion) !== NoFlags) { if (doesFiberContain(nextEffect, focusedInstanceHandle)) { shouldFireAfterActiveInstanceBlur = true; } @@ -18921,15 +18768,15 @@ function commitBeforeMutationEffects() { } } - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if ((effectTag & Snapshot) !== NoEffect) { + if ((flags & Snapshot) !== NoFlags) { setCurrentFiber(nextEffect); commitBeforeMutationLifeCycles(current, nextEffect); resetCurrentFiber(); } - if ((effectTag & Passive) !== NoEffect) { + if ((flags & Passive) !== NoFlags) { // If there are passive effects, schedule a callback to flush at // the earliest opportunity. if (!rootDoesHavePassiveEffects) { @@ -18949,9 +18796,9 @@ function commitMutationEffects(root, renderPriorityLevel) { // TODO: Should probably move the bulk of this function to commitWork. while (nextEffect !== null) { setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if (effectTag & Ref) { + if (flags & Ref) { var current = nextEffect.alternate; if (current !== null) { @@ -18962,23 +18809,22 @@ function commitMutationEffects(root, renderPriorityLevel) { // bitmap value, we remove the secondary effects from the effect tag and // switch on that value. - var primaryEffectTag = - effectTag & (Placement | Update | Deletion | Hydrating); + var primaryFlags = flags & (Placement | Update | Deletion | Hydrating); - switch (primaryEffectTag) { + switch (primaryFlags) { case Placement: { // inserted, before any life-cycles like componentDidMount gets called. // TODO: findDOMNode doesn't rely on this any more but isMounted does // and isMounted is deprecated anyway so we should be able to kill this. - nextEffect.effectTag &= ~Placement; + nextEffect.flags &= ~Placement; break; } case PlacementAndUpdate: { // inserted, before any life-cycles like componentDidMount gets called. - nextEffect.effectTag &= ~Placement; // Update + nextEffect.flags &= ~Placement; // Update var _current = nextEffect.alternate; commitWork(_current, nextEffect); @@ -18986,12 +18832,12 @@ function commitMutationEffects(root, renderPriorityLevel) { } case Hydrating: { - nextEffect.effectTag &= ~Hydrating; + nextEffect.flags &= ~Hydrating; break; } case HydratingAndUpdate: { - nextEffect.effectTag &= ~Hydrating; // Update + nextEffect.flags &= ~Hydrating; // Update var _current2 = nextEffect.alternate; commitWork(_current2, nextEffect); @@ -19018,15 +18864,15 @@ function commitMutationEffects(root, renderPriorityLevel) { function commitLayoutEffects(root, committedLanes) { while (nextEffect !== null) { setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if (effectTag & (Update | Callback)) { + if (flags & (Update | Callback)) { var current = nextEffect.alternate; commitLifeCycles(root, current, nextEffect); } { - if (effectTag & Ref) { + if (flags & Ref) { commitAttachRef(nextEffect); } } @@ -19045,12 +18891,8 @@ function flushPassiveEffects() { : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = NoPriority$1; - try { - setCurrentUpdateLanePriority( - schedulerPriorityToLanePriority(priorityLevel) - ); + { return runWithPriority(priorityLevel, flushPassiveEffectsImpl); - } finally { } } @@ -19071,11 +18913,11 @@ function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { pendingPassiveHookEffectsUnmount.push(effect, fiber); { - fiber.effectTag |= PassiveUnmountPendingDev; + fiber.flags |= PassiveUnmountPendingDev; var alternate = fiber.alternate; if (alternate !== null) { - alternate.effectTag |= PassiveUnmountPendingDev; + alternate.flags |= PassiveUnmountPendingDev; } } @@ -19131,11 +18973,11 @@ function flushPassiveEffectsImpl() { _effect.destroy = undefined; { - fiber.effectTag &= ~PassiveUnmountPendingDev; + fiber.flags &= ~PassiveUnmountPendingDev; var alternate = fiber.alternate; if (alternate !== null) { - alternate.effectTag &= ~PassiveUnmountPendingDev; + alternate.flags &= ~PassiveUnmountPendingDev; } } @@ -19198,7 +19040,7 @@ function flushPassiveEffectsImpl() { effect.nextEffect = null; - if (effect.effectTag & Deletion) { + if (effect.flags & Deletion) { detachFiberAfterEffects(effect); } @@ -19293,6 +19135,24 @@ function captureCommitPhaseError(sourceFiber, error) { markRootUpdated(root, SyncLane, eventTime); ensureRootIsScheduled(root, eventTime); schedulePendingInteractions(root, SyncLane); + } else { + // This component has already been unmounted. + // We can't schedule any follow up work for the root because the fiber is already unmounted, + // but we can still call the log-only boundary so the error isn't swallowed. + // + // TODO This is only a temporary bandaid for the old reconciler fork. + // We can delete this special case once the new fork is merged. + if ( + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance) + ) { + try { + instance.componentDidCatch(error, errorInfo); + } catch (errorToIgnore) { + // TODO Ignore this error? Rethrow it? + // This is kind of an edge case. + } + } } return; @@ -19407,33 +19267,6 @@ function jnd(timeElapsed) { : ceil(timeElapsed / 1960) * 1960; } -function computeMsUntilSuspenseLoadingDelay( - mostRecentEventTime, - suspenseConfig -) { - var busyMinDurationMs = suspenseConfig.busyMinDurationMs | 0; - - if (busyMinDurationMs <= 0) { - return 0; - } - - var busyDelayMs = suspenseConfig.busyDelayMs | 0; // Compute the time until this render pass would expire. - - var currentTimeMs = now(); - var eventTimeMs = mostRecentEventTime; - var timeElapsed = currentTimeMs - eventTimeMs; - - if (timeElapsed <= busyDelayMs) { - // If we haven't yet waited longer than the initial delay, we don't - // have to wait any additional time. - return 0; - } - - var msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed; // This is the value that is passed to `setTimeout`. - - return msUntilTimeout; -} - function checkForNestedUpdates() { if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { nestedUpdateCount = 0; @@ -19492,8 +19325,7 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block + tag !== SimpleMemoComponent ) { // Only warn for user-defined components, not internal ones like Suspense. return; @@ -19545,15 +19377,14 @@ function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block + tag !== SimpleMemoComponent ) { // Only warn for user-defined components, not internal ones like Suspense. return; } // If there are pending passive effects unmounts for this Fiber, // we can assume that they would have prevented this update. - if ((fiber.effectTag & PassiveUnmountPendingDev) !== NoEffect) { + if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) { return; } // We show the whole stack but dedupe on the top component's name because // the problematic code almost always lies inside that component. @@ -19686,7 +19517,7 @@ function warnAboutRenderPhaseUpdatesInDEV(fiber) { error( "Cannot update a component (`%s`) while rendering a " + "different component (`%s`). To locate the bad setState() call inside `%s`, " + - "follow the stack trace as described in https://fb.me/setstate-in-render", + "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", setStateComponentName, renderingComponentName, renderingComponentName @@ -19734,7 +19565,7 @@ function warnIfUnmockedScheduler(fiber) { "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" + "For more info, visit https://reactjs.org/link/mock-scheduler" ); } else { didWarnAboutUnmockedScheduler = true; @@ -19745,7 +19576,7 @@ function warnIfUnmockedScheduler(fiber) { "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" + "For more info, visit https://reactjs.org/link/mock-scheduler" ); } } @@ -19889,16 +19720,14 @@ function finishPendingInteractions(root, committedLanes) { }); } } // `act` testing API -// -// TODO: This is mostly a copy-paste from the legacy `act`, which does not have -// access to the same internals that we do here. Some trade offs in the -// implementation no longer make sense. - -var isFlushingAct = false; function shouldForceFlushFallbacksInDEV() { - return isFlushingAct; + // Never force flush in production. This function should get stripped out. + return actingUpdatesScopeDepth > 0; } +// so we can tell if any async act() calls try to run in parallel. + +var actingUpdatesScopeDepth = 0; function detachFiberAfterEffects(fiber) { fiber.sibling = null; @@ -20380,7 +20209,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.dependencies = null; this.mode = mode; // Effects - this.effectTag = NoEffect; + this.flags = NoFlags; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null; @@ -20510,7 +20339,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.type = current.type; // We already have an alternate. // Reset the effect tag. - workInProgress.effectTag = NoEffect; // The effect list is no longer valid. + workInProgress.flags = NoFlags; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -20584,7 +20413,7 @@ function resetWorkInProgress(workInProgress, renderLanes) { // avoid doing another reconciliation. // Reset the effect tag but keep any Placement tags, since that's something // that child fiber is setting, not the reconciliation. - workInProgress.effectTag &= Placement; // The effect list is no longer valid. + workInProgress.flags &= Placement; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -20748,10 +20577,6 @@ function createFiberFromTypeAndProps( fiberTag = LazyComponent; resolvedType = null; break getTag; - - case REACT_BLOCK_TYPE: - fiberTag = Block; - break getTag; } } @@ -20793,6 +20618,11 @@ function createFiberFromTypeAndProps( fiber.elementType = type; fiber.type = resolvedType; fiber.lanes = lanes; + + { + fiber._debugOwner = owner; + } + return fiber; } function createFiberFromElement(element, mode, lanes) { @@ -20945,7 +20775,7 @@ function assignFiberPropertiesInDEV(target, source) { target.memoizedState = source.memoizedState; target.dependencies = source.dependencies; target.mode = source.mode; - target.effectTag = source.effectTag; + target.flags = source.flags; target.nextEffect = source.nextEffect; target.firstEffect = source.firstEffect; target.lastEffect = source.lastEffect; @@ -21111,7 +20941,7 @@ function findHostInstanceWithWarning(component, methodName) { "%s was passed an instance of %s which is inside StrictMode. " + "Instead, add a ref directly to the element you want to reference. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node", + "https://reactjs.org/link/strict-mode-find-node", methodName, methodName, componentName @@ -21122,7 +20952,7 @@ function findHostInstanceWithWarning(component, methodName) { "%s was passed an instance of %s which renders StrictMode children. " + "Instead, add a ref directly to the element you want to reference. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node", + "https://reactjs.org/link/strict-mode-find-node", methodName, methodName, componentName @@ -21162,8 +20992,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(current$1, suspenseConfig); + var lane = requestUpdateLane(current$1); var context = getContextForSubtree(parentComponent); @@ -21187,7 +21016,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var update = createUpdate(eventTime, lane, suspenseConfig); // Caution: React DevTools currently depends on this property + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property // being called "element". update.payload = { @@ -21237,28 +21066,102 @@ function shouldSuspend(fiber) { return shouldSuspendImpl(fiber); } var overrideHookState = null; +var overrideHookStateDeletePath = null; +var overrideHookStateRenamePath = null; var overrideProps = null; +var overridePropsDeletePath = null; +var overridePropsRenamePath = null; var scheduleUpdate = null; var setSuspenseHandler = null; { - var copyWithSetImpl = function(obj, path, idx, value) { - if (idx >= path.length) { + var copyWithDeleteImpl = function(obj, path, index) { + var key = path[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === path.length) { + if (Array.isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } + + return updated; + } // $FlowFixMe number or string is fine here + + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; + + var copyWithDelete = function(obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; + + var copyWithRenameImpl = function(obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here + + updated[newKey] = updated[oldKey]; + + if (Array.isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } + + return updated; + }; + + var copyWithRename = function(obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); + + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); + + return; + } + } + } + + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; + + var copyWithSetImpl = function(obj, path, index, value) { + if (index >= path.length) { return value; } - var key = path[idx]; + var key = path[index]; var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); // $FlowFixMe number or string is fine here - updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); return updated; }; var copyWithSet = function(obj, path, value) { return copyWithSetImpl(obj, path, 0, value); - }; // Support DevTools editable values for useState and useReducer. + }; - overrideHookState = function(fiber, id, path, value) { + var findHook = function(fiber, id) { // For now, the "id" of stateful hooks is just the stateful hook index. // This may change in the future with e.g. nested hooks. var currentHook = fiber.memoizedState; @@ -21268,10 +21171,50 @@ var setSuspenseHandler = null; id--; } - if (currentHook !== null) { - var newState = copyWithSet(currentHook.memoizedState, path, value); - currentHook.memoizedState = newState; - currentHook.baseState = newState; // We aren't actually adding an update to the queue, + return currentHook; + }; // Support DevTools editable values for useState and useReducer. + + overrideHookState = function(fiber, id, path, value) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateDeletePath = function(fiber, id, path) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, // because there is no update we can add for useReducer hooks that won't trigger an error. // (There's no appropriate action type for DevTools overrides.) // As a result though, React will see the scheduled update as a noop and bailout. @@ -21292,6 +21235,26 @@ var setSuspenseHandler = null; scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; + overridePropsDeletePath = function(fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsRenamePath = function(fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + scheduleUpdate = function(fiber) { scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; @@ -21328,7 +21291,11 @@ function injectIntoDevTools(devToolsConfig) { rendererPackageName: devToolsConfig.rendererPackageName, rendererConfig: devToolsConfig.rendererConfig, overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, setSuspenseHandler: setSuspenseHandler, scheduleUpdate: scheduleUpdate, currentDispatcherRef: ReactCurrentDispatcher, @@ -21345,9 +21312,6 @@ function injectIntoDevTools(devToolsConfig) { }); } -// TODO: this is special because it gets imported during build. -var ReactVersion = "17.0.0-alpha.0"; - var instanceCache = new Map(); function getInstanceFromTag(tag) { @@ -21732,6 +21696,31 @@ function dispatchCommand(handle, command, args) { } } +function sendAccessibilityEvent(handle, eventType) { + if (handle._nativeTag == null) { + { + error( + "sendAccessibilityEvent was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } + + return; + } + + if (handle._internalInstanceHandle) { + nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ); + } else { + ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + ); + } +} + function render(element, containerTag, callback) { var root = roots.get(containerTag); @@ -21787,6 +21776,7 @@ exports.createPortal = createPortal$1; exports.dispatchCommand = dispatchCommand; exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; exports.findNodeHandle = findNodeHandle; +exports.sendAccessibilityEvent = sendAccessibilityEvent; exports.render = render; exports.stopSurface = stopSurface; exports.unmountComponentAtNode = unmountComponentAtNode; diff --git a/Libraries/Renderer/implementations/ReactFabric-dev.js b/Libraries/Renderer/implementations/ReactFabric-dev.js index 8e2baedcc4efc4..e08d68b542c96c 100644 --- a/Libraries/Renderer/implementations/ReactFabric-dev.js +++ b/Libraries/Renderer/implementations/ReactFabric-dev.js @@ -24,21 +24,7 @@ var Scheduler = require("scheduler"); var tracing = require("scheduler/tracing"); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Prevent newer renderers from RTE when used with older react package versions. -// Current owner and dispatcher used to share the same ref, -// but PR #14548 split them out to better support the react-debug-tools package. - -if (!ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher")) { - ReactSharedInternals.ReactCurrentDispatcher = { - current: null - }; -} - -if (!ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig")) { - ReactSharedInternals.ReactCurrentBatchConfig = { - suspense: null - }; -} + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // by calls to these methods by a Babel plugin. // @@ -80,19 +66,12 @@ function printWarning(level, format, args) { // When changing this logic, you might want to also // update consoleWithStackDev.www.js as well. { - var hasExistingStack = - args.length > 0 && - typeof args[args.length - 1] === "string" && - args[args.length - 1].indexOf("\n in") === 0; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - if (!hasExistingStack) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); - - if (stack !== "") { - format += "%s"; - args = args.concat([stack]); - } + if (stack !== "") { + format += "%s"; + args = args.concat([stack]); } var argsWithFormat = args.map(function(item) { @@ -104,161 +83,10 @@ function printWarning(level, format, args) { // eslint-disable-next-line react-internal/no-production-logging Function.prototype.apply.call(console[level], console, argsWithFormat); - - try { - // --- Welcome to debugging React --- - // This error was thrown as a convenience so that you can use this stack - // to find the callsite that caused this warning to fire. - var argIndex = 0; - var message = - "Warning: " + - format.replace(/%s/g, function() { - return args[argIndex++]; - }); - throw new Error(message); - } catch (x) {} - } -} - -var FunctionComponent = 0; -var ClassComponent = 1; -var IndeterminateComponent = 2; // Before we know whether it is function or class - -var HostRoot = 3; // Root of a host tree. Could be nested inside another node. - -var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. - -var HostComponent = 5; -var HostText = 6; -var Fragment = 7; -var Mode = 8; -var ContextConsumer = 9; -var ContextProvider = 10; -var ForwardRef = 11; -var Profiler = 12; -var SuspenseComponent = 13; -var MemoComponent = 14; -var SimpleMemoComponent = 15; -var LazyComponent = 16; -var IncompleteClassComponent = 17; -var DehydratedFragment = 18; -var SuspenseListComponent = 19; -var FundamentalComponent = 20; -var ScopeComponent = 21; -var Block = 22; - -function getParent(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); - - if (inst) { - return inst; - } - - return null; -} -/** - * Return the lowest common ancestor of A and B, or null if they are in - * different trees. - */ - -function getLowestCommonAncestor(instA, instB) { - var depthA = 0; - - for (var tempA = instA; tempA; tempA = getParent(tempA)) { - depthA++; - } - - var depthB = 0; - - for (var tempB = instB; tempB; tempB = getParent(tempB)) { - depthB++; - } // If A is deeper, crawl up. - - while (depthA - depthB > 0) { - instA = getParent(instA); - depthA--; - } // If B is deeper, crawl up. - - while (depthB - depthA > 0) { - instB = getParent(instB); - depthB--; - } // Walk in lockstep until we find a match. - - var depth = depthA; - - while (depth--) { - if (instA === instB || instA === instB.alternate) { - return instA; - } - - instA = getParent(instA); - instB = getParent(instB); - } - - return null; -} -/** - * Return if A is an ancestor of B. - */ - -function isAncestor(instA, instB) { - while (instB) { - if (instA === instB || instA === instB.alternate) { - return true; - } - - instB = getParent(instB); - } - - return false; -} -/** - * Return the parent instance of the passed-in instance. - */ - -function getParentInstance(inst) { - return getParent(inst); -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ - -function traverseTwoPhase(inst, fn, arg) { - var path = []; - - while (inst) { - path.push(inst); - inst = getParent(inst); - } - - var i; - - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } - - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); } } -var invokeGuardedCallbackImpl = function( - name, - func, - context, - a, - b, - c, - d, - e, - f -) { +function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -266,7 +94,9 @@ var invokeGuardedCallbackImpl = function( } catch (error) { this.onError(error); } -}; +} + +var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; { // In DEV mode, we swap out invokeGuardedCallback for a special version @@ -297,7 +127,7 @@ var invokeGuardedCallbackImpl = function( ) { var fakeNode = document.createElement("react"); - var invokeGuardedCallbackDev = function( + invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( name, func, context, @@ -310,7 +140,7 @@ var invokeGuardedCallbackImpl = function( ) { // If document doesn't exist we know for sure we will crash in this method // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebookincubator/create-react-app/issues/3482 + // errors: https://github.com/facebook/create-react-app/issues/3482 // So we preemptively throw with a better message instead. if (!(typeof document !== "undefined")) { throw Error( @@ -318,7 +148,8 @@ var invokeGuardedCallbackImpl = function( ); } - var evt = document.createEvent("Event"); // Keeps track of whether the user-provided callback threw an error. We + var evt = document.createEvent("Event"); + var didCall = false; // Keeps track of whether the user-provided callback threw an error. We // set this to true at the beginning, then set it to false right after // calling the function. If the function errors, `didError` will never be // set to false. This strategy works even if the browser is flaky and @@ -335,13 +166,9 @@ var invokeGuardedCallbackImpl = function( var windowEventDescriptor = Object.getOwnPropertyDescriptor( window, "event" - ); // Create an event handler for our fake event. We will synchronously - // dispatch our fake event using `dispatchEvent`. Inside the handler, we - // call the user-provided callback. - - var funcArgs = Array.prototype.slice.call(arguments, 3); + ); - function callCallback() { + function restoreAfterDispatch() { // We immediately remove the callback from event listeners so that // nested `invokeGuardedCallback` calls do not clash. Otherwise, a // nested call would trigger the fake event handlers of any call higher @@ -357,7 +184,15 @@ var invokeGuardedCallbackImpl = function( ) { window.event = windowEvent; } + } // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + var funcArgs = Array.prototype.slice.call(arguments, 3); + + function callCallback() { + didCall = true; + restoreAfterDispatch(); func.apply(context, funcArgs); didError = false; } // Create a global error event handler. We use this to capture the value @@ -412,7 +247,7 @@ var invokeGuardedCallbackImpl = function( Object.defineProperty(window, "event", windowEventDescriptor); } - if (didError) { + if (didCall && didError) { if (!didSetError) { // The callback errored, but the error event never fired. error = new Error( @@ -429,7 +264,7 @@ var invokeGuardedCallbackImpl = function( error = new Error( "A cross-origin error was thrown. React doesn't have access to " + "the actual error object in development. " + - "See https://fb.me/react-crossorigin-error for more information." + "See https://reactjs.org/link/crossorigin-error for more information." ); } @@ -437,9 +272,16 @@ var invokeGuardedCallbackImpl = function( } // Remove our event listeners window.removeEventListener("error", handleWindowError); - }; - invokeGuardedCallbackImpl = invokeGuardedCallbackDev; + if (!didCall) { + // Something went really wrong, and our event was not dispatched. + // https://github.com/facebook/react/issues/16734 + // https://github.com/facebook/react/issues/16585 + // Fall back to the production implementation. + restoreAfterDispatch(); + return invokeGuardedCallbackProd.apply(this, arguments); + } + }; } } @@ -708,293 +550,53 @@ function hasDispatches(event) { return !!event._dispatchListeners; } -function isInteractive(tag) { - return ( - tag === "button" || - tag === "input" || - tag === "select" || - tag === "textarea" - ); -} - -function shouldPreventMouseEvent(name, type, props) { - switch (name) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - return !!(props.disabled && isInteractive(type)); - - default: - return false; - } -} +var EVENT_POOL_SIZE = 10; /** - * @param {object} inst The instance, which is the source of events. - * @param {string} registrationName Name of listener (e.g. `onClick`). - * @return {?function} The stored callback. + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ */ -function getListener(inst, registrationName) { - var listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not - // live here; needs to be moved to a better place soon - - var stateNode = inst.stateNode; - - if (!stateNode) { - // Work in progress (ex: onload events in incremental mode). - return null; - } - - var props = getFiberCurrentPropsFromNode(stateNode); - - if (!props) { - // Work in progress. - return null; - } - - listener = props[registrationName]; - - if (shouldPreventMouseEvent(registrationName, inst.type, props)) { +var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: function() { return null; - } - - if (!(!listener || typeof listener === "function")) { - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } + }, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function(event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null +}; - return listener; +function functionThatReturnsTrue() { + return true; } +function functionThatReturnsFalse() { + return false; +} /** - * Accumulates items that must not be null or undefined into the first one. This - * is used to conserve memory by avoiding array allocations, and thus sacrifices - * API cleanness. Since `current` can be null before being passed in and not - * null after this function, make sure to assign it back to `current`: + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. * - * `a = accumulateInto(a, b);` + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. * - * This API should be sparingly used. Try `accumulate` for something cleaner. + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. * - * @return {*|array<*>} An accumulation of items. - */ - -function accumulateInto(current, next) { - if (!(next != null)) { - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - } - - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). - - if (Array.isArray(current)) { - if (Array.isArray(next)) { - current.push.apply(current, next); - return current; - } - - current.push(next); - return current; - } - - if (Array.isArray(next)) { - // A bit too dangerous to mutate `next`. - return [current].concat(next); - } - - return [current, next]; -} - -/** - * @param {array} arr an "accumulation" of items which is either an Array or - * a single item. Useful when paired with the `accumulate` module. This is a - * simple utility that allows us to reason about a collection of items, but - * handling the case when there is exactly one item (and we do not need to - * allocate an array). - * @param {function} cb Callback invoked with each element or a collection. - * @param {?} [scope] Scope used as `this` in a callback. - */ -function forEachAccumulated(arr, cb, scope) { - if (Array.isArray(arr)) { - arr.forEach(cb, scope); - } else if (arr) { - cb.call(scope, arr); - } -} - -/** - * Some event types have a notion of different registration names for different - * "phases" of propagation. This finds listeners by a given phase. - */ -function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); -} -/** - * A small set of propagation patterns, each of which will accept a small amount - * of information, and generate a set of "dispatch ready event objects" - which - * are sets of events that have already been annotated with a set of dispatched - * listener functions/ids. The API is designed this way to discourage these - * propagation strategies from actually executing the dispatches, since we - * always want to collect the entire set of dispatches before executing even a - * single one. - */ - -/** - * Tags a `SyntheticEvent` with dispatched listeners. Creating this function - * here, allows us to not have to bind or create functions for each event. - * Mutating the event's members allows us to not have to create a wrapping - * "dispatch" object that pairs the event with the listener. - */ - -function accumulateDirectionalDispatches(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); - } - } - - var listener = listenerAtPhase(inst, event, phase); - - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } -} -/** - * Collect dispatches (must be entirely collected before dispatching - see unit - * tests). Lazily allocate the array to conserve memory. We must loop through - * each event and perform the traversal for each one. We cannot perform a - * single traversal for the entire collection of events because each event may - * have a different target. - */ - -function accumulateTwoPhaseDispatchesSingle(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); - } -} -/** - * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. - */ - -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - var parentInst = targetInst ? getParentInstance(targetInst) : null; - traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ - -function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listener = getListener(inst, registrationName); - - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ - -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches(event._targetInst, null, event); - } -} - -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); -} -function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); -} -function accumulateDirectDispatches(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle); -} - -var EVENT_POOL_SIZE = 10; -/** - * @interface Event - * @see http://www.w3.org/TR/DOM-Level-3-Events/ - */ - -var EventInterface = { - type: null, - target: null, - // currentTarget is set when dispatching; no use in copying it here - currentTarget: function() { - return null; - }, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null -}; - -function functionThatReturnsTrue() { - return true; -} - -function functionThatReturnsFalse() { - return false; -} -/** - * Synthetic events are dispatched by event plugins, typically in response to a - * top-level event delegation handler. - * - * These systems should generally use pooling to reduce the frequency of garbage - * collection. The system should check `isPersistent` to determine whether the - * event should be released into the pool after being dispatched. Users that - * need a persisted event should invoke `persist`. - * - * Synthetic events (and subclasses) implement the DOM Level 3 Events API by - * normalizing browser quirks. Subclasses do not necessarily have to implement a - * DOM interface; custom application-specific events can also subclass this. - * - * @param {object} dispatchConfig Configuration used to dispatch this event. - * @param {*} targetInst Marker identifying the event target. - * @param {object} nativeEvent Native browser event. - * @param {DOMEventTarget} nativeEventTarget Target node. + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. */ function SyntheticEvent( @@ -1015,6 +617,8 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchListeners = null; + this._dispatchInstances = null; var Interface = this.constructor.Interface; for (var propName in Interface) { @@ -1203,13 +807,6 @@ addEventPoolingTo(SyntheticEvent); */ function getPooledWarningPropertyDefinition(propName, getVal) { - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; - function set(val) { var action = isFunction ? "setting the method" : "setting the property"; warn(action, "This is effectively a no-op"); @@ -1231,16 +828,28 @@ function getPooledWarningPropertyDefinition(propName, getVal) { "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", + "See https://reactjs.org/link/event-pooling for more information.", action, propName, result ); } } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; } -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { var EventConstructor = this; if (EventConstructor.eventPool.length) { @@ -1280,8 +889,8 @@ function releasePooledEvent(event) { } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } @@ -1547,51 +1156,139 @@ function accumulate(current, next) { } /** - * Instance of element that should respond to touch/move types of interactions, - * as indicated explicitly by relevant callbacks. + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. */ -var responderInst = null; -/** - * Count of current touches. A textInput should become responder iff the - * selection changes while there is a touch on the screen. - */ +function accumulateInto(current, next) { + if (!(next != null)) { + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + } -var trackedTouchCount = 0; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). -var changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst; + if (Array.isArray(current)) { + if (Array.isArray(next)) { + current.push.apply(current, next); + return current; + } - if (ResponderEventPlugin.GlobalResponderHandler !== null) { - ResponderEventPlugin.GlobalResponderHandler.onChange( - oldResponderInst, - nextResponderInst, - blockHostResponder - ); + current.push(next); + return current; } -}; -var eventTypes = { - /** - * On a `touchStart`/`mouseDown`, is it desired that this element become the - * responder? - */ - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, + if (Array.isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } - /** - * On a `scroll`, is it desired that this element become the responder? This - * is usually not needed, but should be used to retroactively infer that a - * `touchStart` had occurred during momentum scroll. During a momentum scroll, - * a touch start will be immediately followed by a scroll event if the view is - * currently scrolling. - * + return [current, next]; +} + +/** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ +function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } +} + +var FunctionComponent = 0; +var ClassComponent = 1; +var IndeterminateComponent = 2; // Before we know whether it is function or class + +var HostRoot = 3; // Root of a host tree. Could be nested inside another node. + +var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. + +var HostComponent = 5; +var HostText = 6; +var Fragment = 7; +var Mode = 8; +var ContextConsumer = 9; +var ContextProvider = 10; +var ForwardRef = 11; +var Profiler = 12; +var SuspenseComponent = 13; +var MemoComponent = 14; +var SimpleMemoComponent = 15; +var LazyComponent = 16; +var IncompleteClassComponent = 17; +var DehydratedFragment = 18; +var SuspenseListComponent = 19; +var FundamentalComponent = 20; +var ScopeComponent = 21; +var OffscreenComponent = 22; +var LegacyHiddenComponent = 23; + +/** + * Instance of element that should respond to touch/move types of interactions, + * as indicated explicitly by relevant callbacks. + */ + +var responderInst = null; +/** + * Count of current touches. A textInput should become responder iff the + * selection changes while there is a touch on the screen. + */ + +var trackedTouchCount = 0; + +var changeResponder = function(nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; + + if (ResponderEventPlugin.GlobalResponderHandler !== null) { + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); + } +}; + +var eventTypes = { + /** + * On a `touchStart`/`mouseDown`, is it desired that this element become the + * responder? + */ + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + }, + dependencies: startDependencies + }, + + /** + * On a `scroll`, is it desired that this element become the responder? This + * is usually not needed, but should be used to retroactively infer that a + * `touchStart` had occurred during momentum scroll. During a momentum scroll, + * a touch start will be immediately followed by a scroll event if the view is + * currently scrolling. + * * TODO: This shouldn't bubble. */ scrollShouldSetResponder: { @@ -1664,610 +1361,818 @@ var eventTypes = { registrationName: "onResponderTerminate", dependencies: [] } -}; +}; // Start of inline: the below functions were inlined from +// EventPropagator.js, as they deviated from ReactDOM's newer +// implementations. + +function getParent(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + + if (inst) { + return inst; + } + + return null; +} /** - * - * Responder System: - * ---------------- - * - * - A global, solitary "interaction lock" on a view. - * - If a node becomes the responder, it should convey visual feedback - * immediately to indicate so, either by highlighting or moving accordingly. - * - To be the responder means, that touches are exclusively important to that - * responder view, and no other view. - * - While touches are still occurring, the responder lock can be transferred to - * a new view, but only to increasingly "higher" views (meaning ancestors of - * the current responder). - * - * Responder being granted: - * ------------------------ - * - * - Touch starts, moves, and scrolls can cause an ID to become the responder. - * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to - * the "appropriate place". - * - If nothing is currently the responder, the "appropriate place" is the - * initiating event's `targetID`. - * - If something *is* already the responder, the "appropriate place" is the - * first common ancestor of the event target and the current `responderInst`. - * - Some negotiation happens: See the timing diagram below. - * - Scrolled views automatically become responder. The reasoning is that a - * platform scroll view that isn't built on top of the responder system has - * began scrolling, and the active responder must now be notified that the - * interaction is no longer locked to it - the system has taken over. - * - * - Responder being released: - * As soon as no more touches that *started* inside of descendants of the - * *current* responderInst, an `onResponderRelease` event is dispatched to the - * current responder, and the responder lock is released. - * - * TODO: - * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that - * determines if the responder lock should remain. - * - If a view shouldn't "remain" the responder, any active touches should by - * default be considered "dead" and do not influence future negotiations or - * bubble paths. It should be as if those touches do not exist. - * -- For multitouch: Usually a translate-z will choose to "remain" responder - * after one out of many touches ended. For translate-y, usually the view - * doesn't wish to "remain" responder after one of many touches end. - * - Consider building this on top of a `stopPropagation` model similar to - * `W3C` events. - * - Ensure that `onResponderTerminate` is called on touch cancels, whether or - * not `onResponderTerminationRequest` returns `true` or `false`. - * + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. */ -/* Negotiation Performed - +-----------------------+ - / \ -Process low level events to + Current Responder + wantsResponderID -determine who to perform negot-| (if any exists at all) | -iation/transition | Otherwise just pass through| --------------------------------+----------------------------+------------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchStart| | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderReject - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderStart| - | | +----------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchMove | | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderRejec| - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderMove | - | | +----------------+ - | | - | | - Some active touch started| | - inside current responder | +------------------------+ | - +------------------------->| onResponderEnd | | - | | +------------------------+ | - +---+---------+ | | - | onTouchEnd | | | - +---+---------+ | | - | | +------------------------+ | - +------------------------->| onResponderEnd | | - No active touches started| +-----------+------------+ | - inside current responder | | | - | v | - | +------------------------+ | - | | onResponderRelease | | - | +------------------------+ | - | | - + + */ +function getLowestCommonAncestor(instA, instB) { + var depthA = 0; -/** - * A note about event ordering in the `EventPluginRegistry`. - * - * Suppose plugins are injected in the following order: - * - * `[R, S, C]` - * - * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for - * `onClick` etc) and `R` is `ResponderEventPlugin`. - * - * "Deferred-Dispatched Events": - * - * - The current event plugin system will traverse the list of injected plugins, - * in order, and extract events by collecting the plugin's return value of - * `extractEvents()`. - * - These events that are returned from `extractEvents` are "deferred - * dispatched events". - * - When returned from `extractEvents`, deferred-dispatched events contain an - * "accumulation" of deferred dispatches. - * - These deferred dispatches are accumulated/collected before they are - * returned, but processed at a later time by the `EventPluginRegistry` (hence the - * name deferred). - * - * In the process of returning their deferred-dispatched events, event plugins - * themselves can dispatch events on-demand without returning them from - * `extractEvents`. Plugins might want to do this, so that they can use event - * dispatching as a tool that helps them decide which events should be extracted - * in the first place. - * - * "On-Demand-Dispatched Events": - * - * - On-demand-dispatched events are not returned from `extractEvents`. - * - On-demand-dispatched events are dispatched during the process of returning - * the deferred-dispatched events. - * - They should not have side effects. - * - They should be avoided, and/or eventually be replaced with another - * abstraction that allows event plugins to perform multiple "rounds" of event - * extraction. - * - * Therefore, the sequence of event dispatches becomes: - * - * - `R`s on-demand events (if any) (dispatched by `R` on-demand) - * - `S`s on-demand events (if any) (dispatched by `S` on-demand) - * - `C`s on-demand events (if any) (dispatched by `C` on-demand) - * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` - * on-demand dispatch returns `true` (and some other details are satisfied) the - * `onResponderGrant` deferred dispatched event is returned from - * `extractEvents`. The sequence of dispatch executions in this case - * will appear as follows: - * - * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) - * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) - * - `touchStart` (`EventPluginRegistry` dispatches as usual) - * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) - */ - -function setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) - ? eventTypes.moveShouldSetResponder - : topLevelType === TOP_SELECTION_CHANGE - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. - - var bubbleShouldSetFrom = !responderInst - ? targetInst - : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target - // (deepest ID) if it happens to be the current responder. The reasoning: - // It's strange to get an `onMoveShouldSetResponder` when you're *already* - // the responder. - - var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; - var shouldSetEvent = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - bubbleShouldSetFrom, - nativeEvent, - nativeEventTarget - ); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - - if (skipOverBubbleShouldSetFrom) { - accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); - } else { - accumulateTwoPhaseDispatches(shouldSetEvent); + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; } - var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + var depthB = 0; - if (!shouldSetEvent.isPersistent()) { - shouldSetEvent.constructor.release(shouldSetEvent); - } + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } // If A is deeper, crawl up. - if (!wantsResponderInst || wantsResponderInst === responderInst) { - return null; - } + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } // If B is deeper, crawl up. - var extracted; - var grantEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(grantEvent); - var blockHostResponder = executeDirectDispatch(grantEvent) === true; + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } // Walk in lockstep until we find a match. - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminationRequestEvent.touchHistory = - ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = - !hasDispatches(terminationRequestEvent) || - executeDirectDispatch(terminationRequestEvent); + var depth = depthA; - if (!terminationRequestEvent.isPersistent()) { - terminationRequestEvent.constructor.release(terminationRequestEvent); + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; } - if (shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminateEvent); - extracted = accumulate(extracted, [grantEvent, terminateEvent]); - changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(rejectEvent); - extracted = accumulate(extracted, rejectEvent); - } - } else { - extracted = accumulate(extracted, grantEvent); - changeResponder(wantsResponderInst, blockHostResponder); + instA = getParent(instA); + instB = getParent(instB); } - return extracted; + return null; } /** - * A transfer is a negotiation between a currently set responder and the next - * element to claim responder status. Any start event could trigger a transfer - * of responderInst. Any move event could trigger a transfer. - * - * @param {string} topLevelType Record from `BrowserEventConstants`. - * @return {boolean} True if a transfer of responder could possibly occur. + * Return if A is an ancestor of B. */ -function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return ( - topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically - // tracking native scroll events here and responderIgnoreScroll indicates we - // will send topTouchCancel to handle canceling touch events instead - ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || - (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ); +function isAncestor(instA, instB) { + while (instB) { + if (instA === instB || instA === instB.alternate) { + return true; + } + + instB = getParent(instB); + } + + return false; } /** - * Returns whether or not this touch end event makes it such that there are no - * longer any touches that started inside of the current `responderInst`. - * - * @param {NativeEvent} nativeEvent Native touch end event. - * @return {boolean} Whether or not this touch end event ends the responder. + * Simulates the traversal of a two-phase, capture/bubble event dispatch. */ -function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; +function traverseTwoPhase(inst, fn, arg) { + var path = []; - if (!touches || touches.length === 0) { - return true; + while (inst) { + path.push(inst); + inst = getParent(inst); } - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i]; - var target = activeTouch.target; - - if (target !== null && target !== undefined && target !== 0) { - // Is the original touch location inside of the current responder? - var targetInst = getInstanceFromNode(target); + var i; - if (isAncestor(responderInst, targetInst)) { - return false; - } - } + for (i = path.length; i-- > 0; ) { + fn(path[i], "captured", arg); } - return true; + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } } -var ResponderEventPlugin = { - /* For unit testing only */ - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, +function getListener(inst, registrationName) { + var stateNode = inst.stateNode; - /** - * We must be resilient to `targetInst` being `null` on `touchMove` or - * `touchEnd`. On certain platforms, this means that a native scroll has - * assumed control and the original touch targets are destroyed. - */ - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget, - eventSystemFlags - ) { - if (isStartish(topLevelType)) { - trackedTouchCount += 1; - } else if (isEndish(topLevelType)) { - if (trackedTouchCount >= 0) { - trackedTouchCount -= 1; - } else { - { - warn( - "Ended a touch event which was not counted in `trackedTouchCount`." - ); - } + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } - return null; - } - } + var props = getFiberCurrentPropsFromNode(stateNode); - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) - ? setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) - : null; // Responder may or may not have transferred on a new touch start/move. - // Regardless, whoever is the responder after any potential transfer, we - // direct all touch start/move/ends to them in the form of - // `onResponderMove/Start/End`. These will be called for *every* additional - // finger that move/start/end, dispatched directly to whoever is the - // current responder at that moment, until the responder is "released". - // - // These multiple individual change touch events are are always bookended - // by `onResponderGrant`, and one of - // (`onResponderRelease/onResponderTerminate`). + if (props === null) { + // Work in progress. + return null; + } - var isResponderTouchStart = responderInst && isStartish(topLevelType); - var isResponderTouchMove = responderInst && isMoveish(topLevelType); - var isResponderTouchEnd = responderInst && isEndish(topLevelType); - var incrementalTouch = isResponderTouchStart - ? eventTypes.responderStart - : isResponderTouchMove - ? eventTypes.responderMove - : isResponderTouchEnd - ? eventTypes.responderEnd - : null; + var listener = props[registrationName]; - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent.getPooled( - incrementalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(gesture); - extracted = accumulate(extracted, gesture); - } + if (!(!listener || typeof listener === "function")) { + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } - var isResponderTerminate = - responderInst && topLevelType === TOP_TOUCH_CANCEL; - var isResponderRelease = - responderInst && - !isResponderTerminate && - isEndish(topLevelType) && - noResponderTouches(nativeEvent); - var finalTouch = isResponderTerminate - ? eventTypes.responderTerminate - : isResponderRelease - ? eventTypes.responderRelease - : null; + return listener; +} - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent.getPooled( - finalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(finalEvent); - extracted = accumulate(extracted, finalEvent); - changeResponder(null); - } +function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); +} - return extracted; - }, - GlobalResponderHandler: null, - injection: { - /** - * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler - * Object that handles any change in responder. Use this to inject - * integration with an existing touch handling system etc. - */ - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; +function accumulateDirectionalDispatches(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); } } -}; -/** - * Injectable ordering of event plugins. - */ -var eventPluginOrder = null; -/** - * Injectable mapping from names to event plugin modules. - */ + var listener = listenerAtPhase(inst, event, phase); -var namesToPlugins = {}; + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} /** - * Recomputes the plugin list using the injected plugins and plugin ordering. - * - * @private + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. */ -function recomputePluginOrdering() { - if (!eventPluginOrder) { - // Wait until an `eventPluginOrder` is injected. - return; - } - - for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName]; - var pluginIndex = eventPluginOrder.indexOf(pluginName); - - if (!(pluginIndex > -1)) { - throw Error( - "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + - pluginName + - "`." - ); - } - - if (plugins[pluginIndex]) { - continue; - } +function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); - if (!pluginModule.extractEvents) { - throw Error( - "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + - pluginName + - "` does not." + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener ); - } - - plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; - - for (var eventName in publishedEvents) { - if ( - !publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName - ) - ) { - throw Error( - "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." - ); - } + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); } } } /** - * Publishes an event so that it can be dispatched by the supplied plugin. - * - * @param {object} dispatchConfig Dispatch configuration for the event. - * @param {object} PluginModule Plugin publishing the event. - * @return {boolean} True if the event was successfully published. - * @private + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event */ -function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - if (!!eventNameDispatchConfigs.hasOwnProperty(eventName)) { - throw Error( - "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + - eventName + - "`." - ); +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); } +} - eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; - - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) { - if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName( - phasedRegistrationName, - pluginModule, - eventName - ); - } - } +function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); +} - return true; - } else if (dispatchConfig.registrationName) { - publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName - ); - return true; +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); } +} - return false; +function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); } -/** - * Publishes a registration name that is used to identify dispatched events. - * - * @param {string} registrationName Registration name to add. - * @param {object} PluginModule Plugin publishing the event. - * @private - */ -function publishRegistrationName(registrationName, pluginModule, eventName) { - if (!!registrationNameModules[registrationName]) { - throw Error( - "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + - registrationName + - "`." - ); +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } +} - registrationNameModules[registrationName] = pluginModule; - registrationNameDependencies[registrationName] = - pluginModule.eventTypes[eventName].dependencies; +function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); +} // End of inline - { - var lowerCasedName = registrationName.toLowerCase(); - } -} /** - * Registers plugins so that they can extract and dispatch events. + * + * Responder System: + * ---------------- + * + * - A global, solitary "interaction lock" on a view. + * - If a node becomes the responder, it should convey visual feedback + * immediately to indicate so, either by highlighting or moving accordingly. + * - To be the responder means, that touches are exclusively important to that + * responder view, and no other view. + * - While touches are still occurring, the responder lock can be transferred to + * a new view, but only to increasingly "higher" views (meaning ancestors of + * the current responder). + * + * Responder being granted: + * ------------------------ + * + * - Touch starts, moves, and scrolls can cause an ID to become the responder. + * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to + * the "appropriate place". + * - If nothing is currently the responder, the "appropriate place" is the + * initiating event's `targetID`. + * - If something *is* already the responder, the "appropriate place" is the + * first common ancestor of the event target and the current `responderInst`. + * - Some negotiation happens: See the timing diagram below. + * - Scrolled views automatically become responder. The reasoning is that a + * platform scroll view that isn't built on top of the responder system has + * began scrolling, and the active responder must now be notified that the + * interaction is no longer locked to it - the system has taken over. + * + * - Responder being released: + * As soon as no more touches that *started* inside of descendants of the + * *current* responderInst, an `onResponderRelease` event is dispatched to the + * current responder, and the responder lock is released. + * + * TODO: + * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that + * determines if the responder lock should remain. + * - If a view shouldn't "remain" the responder, any active touches should by + * default be considered "dead" and do not influence future negotiations or + * bubble paths. It should be as if those touches do not exist. + * -- For multitouch: Usually a translate-z will choose to "remain" responder + * after one out of many touches ended. For translate-y, usually the view + * doesn't wish to "remain" responder after one of many touches end. + * - Consider building this on top of a `stopPropagation` model similar to + * `W3C` events. + * - Ensure that `onResponderTerminate` is called on touch cancels, whether or + * not `onResponderTerminationRequest` returns `true` or `false`. + * + */ + +/* Negotiation Performed + +-----------------------+ + / \ +Process low level events to + Current Responder + wantsResponderID +determine who to perform negot-| (if any exists at all) | +iation/transition | Otherwise just pass through| +-------------------------------+----------------------------+------------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchStart| | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderReject + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderStart| + | | +----------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchMove | | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderRejec| + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderMove | + | | +----------------+ + | | + | | + Some active touch started| | + inside current responder | +------------------------+ | + +------------------------->| onResponderEnd | | + | | +------------------------+ | + +---+---------+ | | + | onTouchEnd | | | + +---+---------+ | | + | | +------------------------+ | + +------------------------->| onResponderEnd | | + No active touches started| +-----------+------------+ | + inside current responder | | | + | v | + | +------------------------+ | + | | onResponderRelease | | + | +------------------------+ | + | | + + + */ + +/** + * A note about event ordering in the `EventPluginRegistry`. + * + * Suppose plugins are injected in the following order: + * + * `[R, S, C]` + * + * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for + * `onClick` etc) and `R` is `ResponderEventPlugin`. + * + * "Deferred-Dispatched Events": + * + * - The current event plugin system will traverse the list of injected plugins, + * in order, and extract events by collecting the plugin's return value of + * `extractEvents()`. + * - These events that are returned from `extractEvents` are "deferred + * dispatched events". + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginRegistry` (hence the + * name deferred). + * + * In the process of returning their deferred-dispatched events, event plugins + * themselves can dispatch events on-demand without returning them from + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. + * + * "On-Demand-Dispatched Events": + * + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning + * the deferred-dispatched events. + * - They should not have side effects. + * - They should be avoided, and/or eventually be replaced with another + * abstraction that allows event plugins to perform multiple "rounds" of event + * extraction. + * + * Therefore, the sequence of event dispatches becomes: + * + * - `R`s on-demand events (if any) (dispatched by `R` on-demand) + * - `S`s on-demand events (if any) (dispatched by `S` on-demand) + * - `C`s on-demand events (if any) (dispatched by `C` on-demand) + * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * + * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` + * on-demand dispatch returns `true` (and some other details are satisfied) the + * `onResponderGrant` deferred dispatched event is returned from + * `extractEvents`. The sequence of dispatch executions in this case + * will appear as follows: + * + * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) + * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) + * - `touchStart` (`EventPluginRegistry` dispatches as usual) + * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) + */ + +function setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : topLevelType === TOP_SELECTION_CHANGE + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. + + var bubbleShouldSetFrom = !responderInst + ? targetInst + : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target + // (deepest ID) if it happens to be the current responder. The reasoning: + // It's strange to get an `onMoveShouldSetResponder` when you're *already* + // the responder. + + var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; + var shouldSetEvent = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, + nativeEvent, + nativeEventTarget + ); + shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + + if (skipOverBubbleShouldSetFrom) { + accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); + } else { + accumulateTwoPhaseDispatches(shouldSetEvent); + } + + var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } + + if (!wantsResponderInst || wantsResponderInst === responderInst) { + return null; + } + + var extracted; + var grantEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(grantEvent); + var blockHostResponder = executeDirectDispatch(grantEvent) === true; + + if (responderInst) { + var terminationRequestEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminationRequestEvent.touchHistory = + ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = + !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } + + if (shouldSwitch) { + var terminateEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + changeResponder(wantsResponderInst, blockHostResponder); + } else { + var rejectEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + changeResponder(wantsResponderInst, blockHostResponder); + } + + return extracted; +} +/** + * A transfer is a negotiation between a currently set responder and the next + * element to claim responder status. Any start event could trigger a transfer + * of responderInst. Any move event could trigger a transfer. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. + */ + +function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return ( + topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || + isStartish(topLevelType) || + isMoveish(topLevelType)) + ); +} +/** + * Returns whether or not this touch end event makes it such that there are no + * longer any touches that started inside of the current `responderInst`. + * + * @param {NativeEvent} nativeEvent Native touch end event. + * @return {boolean} Whether or not this touch end event ends the responder. + */ + +function noResponderTouches(nativeEvent) { + var touches = nativeEvent.touches; + + if (!touches || touches.length === 0) { + return true; + } + + for (var i = 0; i < touches.length; i++) { + var activeTouch = touches[i]; + var target = activeTouch.target; + + if (target !== null && target !== undefined && target !== 0) { + // Is the original touch location inside of the current responder? + var targetInst = getInstanceFromNode(target); + + if (isAncestor(responderInst, targetInst)) { + return false; + } + } + } + + return true; +} + +var ResponderEventPlugin = { + /* For unit testing only */ + _getResponder: function() { + return responderInst; + }, + eventTypes: eventTypes, + + /** + * We must be resilient to `targetInst` being `null` on `touchMove` or + * `touchEnd`. On certain platforms, this means that a native scroll has + * assumed control and the original touch targets are destroyed. + */ + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget, + eventSystemFlags + ) { + if (isStartish(topLevelType)) { + trackedTouchCount += 1; + } else if (isEndish(topLevelType)) { + if (trackedTouchCount >= 0) { + trackedTouchCount -= 1; + } else { + { + warn( + "Ended a touch event which was not counted in `trackedTouchCount`." + ); + } + + return null; + } + } + + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) + ? setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) + : null; // Responder may or may not have transferred on a new touch start/move. + // Regardless, whoever is the responder after any potential transfer, we + // direct all touch start/move/ends to them in the form of + // `onResponderMove/Start/End`. These will be called for *every* additional + // finger that move/start/end, dispatched directly to whoever is the + // current responder at that moment, until the responder is "released". + // + // These multiple individual change touch events are are always bookended + // by `onResponderGrant`, and one of + // (`onResponderRelease/onResponderTerminate`). + + var isResponderTouchStart = responderInst && isStartish(topLevelType); + var isResponderTouchMove = responderInst && isMoveish(topLevelType); + var isResponderTouchEnd = responderInst && isEndish(topLevelType); + var incrementalTouch = isResponderTouchStart + ? eventTypes.responderStart + : isResponderTouchMove + ? eventTypes.responderMove + : isResponderTouchEnd + ? eventTypes.responderEnd + : null; + + if (incrementalTouch) { + var gesture = ResponderSyntheticEvent.getPooled( + incrementalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } + + var isResponderTerminate = + responderInst && topLevelType === TOP_TOUCH_CANCEL; + var isResponderRelease = + responderInst && + !isResponderTerminate && + isEndish(topLevelType) && + noResponderTouches(nativeEvent); + var finalTouch = isResponderTerminate + ? eventTypes.responderTerminate + : isResponderRelease + ? eventTypes.responderRelease + : null; + + if (finalTouch) { + var finalEvent = ResponderSyntheticEvent.getPooled( + finalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(finalEvent); + extracted = accumulate(extracted, finalEvent); + changeResponder(null); + } + + return extracted; + }, + GlobalResponderHandler: null, + injection: { + /** + * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler + * Object that handles any change in responder. Use this to inject + * integration with an existing touch handling system etc. + */ + injectGlobalResponderHandler: function(GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } +}; + +/** + * Injectable ordering of event plugins. + */ +var eventPluginOrder = null; +/** + * Injectable mapping from names to event plugin modules. + */ + +var namesToPlugins = {}; +/** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ + +function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } + + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); + + if (!(pluginIndex > -1)) { + throw Error( + "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + + pluginName + + "`." + ); + } + + if (plugins[pluginIndex]) { + continue; + } + + if (!pluginModule.extractEvents) { + throw Error( + "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + + pluginName + + "` does not." + ); + } + + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; + + for (var eventName in publishedEvents) { + if ( + !publishEventForPlugin( + publishedEvents[eventName], + pluginModule, + eventName + ) + ) { + throw Error( + "EventPluginRegistry: Failed to publish event `" + + eventName + + "` for plugin `" + + pluginName + + "`." + ); + } + } + } +} +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ + +function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + if (!!eventNameDispatchConfigs.hasOwnProperty(eventName)) { + throw Error( + "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + + eventName + + "`." + ); + } + + eventNameDispatchConfigs[eventName] = dispatchConfig; + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName + ); + } + } + + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName + ); + return true; + } + + return false; +} +/** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ + +function publishRegistrationName(registrationName, pluginModule, eventName) { + if (!!registrationNameModules[registrationName]) { + throw Error( + "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + + registrationName + + "`." + ); + } + + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; + + { + var lowerCasedName = registrationName.toLowerCase(); + } +} +/** + * Registers plugins so that they can extract and dispatch events. */ /** @@ -2352,20 +2257,163 @@ function injectEventPluginsByName(injectedNamesToPlugins) { } } +function getListener$1(inst, registrationName) { + var stateNode = inst.stateNode; + + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } + + var props = getFiberCurrentPropsFromNode(stateNode); + + if (props === null) { + // Work in progress. + return null; + } + + var listener = props[registrationName]; + + if (!(!listener || typeof listener === "function")) { + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } + + return listener; +} + var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customDirectEventTypes; + .customDirectEventTypes; // Start of inline: the below functions were inlined from +// EventPropagator.js, as they deviated from ReactDOM's newer +// implementations. + +function listenerAtPhase$1(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener$1(inst, registrationName); +} + +function accumulateDirectionalDispatches$1(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } + + var listener = listenerAtPhase$1(inst, event, phase); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} + +function getParent$1(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + + if (inst) { + return inst; + } + + return null; +} +/** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ + +function traverseTwoPhase$1(inst, fn, arg) { + var path = []; + + while (inst) { + path.push(inst); + inst = getParent$1(inst); + } + + var i; + + for (i = path.length; i-- > 0; ) { + fn(path[i], "captured", arg); + } + + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } +} + +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event + ); + } +} + +function accumulateTwoPhaseDispatches$1(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); +} +/** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ + +function accumulateDispatches$1(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener$1(inst, registrationName); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } +} +/** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ + +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches$1(event._targetInst, null, event); + } +} + +function accumulateDirectDispatches$1(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle$1); +} // End of inline + var ReactNativeBridgeEventPlugin = { eventTypes: {}, extractEvents: function( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { if (targetInst == null) { // Probably a node belonging to another renderer's tree. @@ -2389,9 +2437,9 @@ var ReactNativeBridgeEventPlugin = { ); if (bubbleDispatchConfig) { - accumulateTwoPhaseDispatches(event); + accumulateTwoPhaseDispatches$1(event); } else if (directDispatchConfig) { - accumulateDirectDispatches(event); + accumulateDirectDispatches$1(event); } else { return null; } @@ -2477,37 +2525,58 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler( * If this becomes an actual Map, that will break. */ function get(key) { - return key._reactInternalFiber; + return key._reactInternals; } function set(key, value) { - key._reactInternalFiber = value; + key._reactInternals = value; } +// ATTENTION +// When adding new symbols to this file, +// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' // The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. -var hasSymbol = typeof Symbol === "function" && Symbol.for; -var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 0xeac7; -var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 0xeaca; -var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 0xeacb; -var REACT_STRICT_MODE_TYPE = hasSymbol - ? Symbol.for("react.strict_mode") - : 0xeacc; -var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 0xead2; -var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 0xeacd; -var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary -var REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 0xeacf; -var REACT_FORWARD_REF_TYPE = hasSymbol - ? Symbol.for("react.forward_ref") - : 0xead0; -var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 0xead1; -var REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 0xead8; -var REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 0xead3; -var REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 0xead4; -var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 0xead9; +var REACT_ELEMENT_TYPE = 0xeac7; +var REACT_PORTAL_TYPE = 0xeaca; +var REACT_FRAGMENT_TYPE = 0xeacb; +var REACT_STRICT_MODE_TYPE = 0xeacc; +var REACT_PROFILER_TYPE = 0xead2; +var REACT_PROVIDER_TYPE = 0xeacd; +var REACT_CONTEXT_TYPE = 0xeace; +var REACT_FORWARD_REF_TYPE = 0xead0; +var REACT_SUSPENSE_TYPE = 0xead1; +var REACT_SUSPENSE_LIST_TYPE = 0xead8; +var REACT_MEMO_TYPE = 0xead3; +var REACT_LAZY_TYPE = 0xead4; +var REACT_FUNDAMENTAL_TYPE = 0xead5; +var REACT_SCOPE_TYPE = 0xead7; +var REACT_OPAQUE_ID_TYPE = 0xeae0; +var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1; +var REACT_OFFSCREEN_TYPE = 0xeae2; +var REACT_LEGACY_HIDDEN_TYPE = 0xeae3; + +if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + REACT_FUNDAMENTAL_TYPE = symbolFor("react.fundamental"); + REACT_SCOPE_TYPE = symbolFor("react.scope"); + REACT_OPAQUE_ID_TYPE = symbolFor("react.opaque.id"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} + var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; function getIteratorFn(maybeIterable) { @@ -2526,63 +2595,6 @@ function getIteratorFn(maybeIterable) { return null; } -// TODO: Move this to "react" once we can import from externals. -var Uninitialized = -1; -var Pending = 0; -var Resolved = 1; -var Rejected = 2; - -function refineResolvedLazyComponent(lazyComponent) { - return lazyComponent._status === Resolved ? lazyComponent._result : null; -} -function initializeLazyComponentType(lazyComponent) { - if (lazyComponent._status === Uninitialized) { - var ctor = lazyComponent._result; - - if (!ctor) { - // TODO: Remove this later. THis only exists in case you use an older "react" package. - ctor = lazyComponent._ctor; - } - - var thenable = ctor(); // Transition to the next state. - - var pending = lazyComponent; - pending._status = Pending; - pending._result = thenable; - thenable.then( - function(moduleObject) { - if (lazyComponent._status === Pending) { - var defaultExport = moduleObject.default; - - { - if (defaultExport === undefined) { - error( - "lazy: Expected the result of a dynamic import() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))", - moduleObject - ); - } - } // Transition to the next state. - - var resolved = lazyComponent; - resolved._status = Resolved; - resolved._result = defaultExport; - } - }, - function(error) { - if (lazyComponent._status === Pending) { - // Transition to the next state. - var rejected = lazyComponent; - rejected._status = Rejected; - rejected._result = error; - } - } - ); - } -} - function getWrappedName(outerType, innerType, wrapperName) { var functionName = innerType.displayName || innerType.name || ""; return ( @@ -2654,18 +2666,16 @@ function getComponentName(type) { case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); - case REACT_LAZY_TYPE: { - var thenable = type; - var resolvedThenable = refineResolvedLazyComponent(thenable); + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (resolvedThenable) { - return getComponentName(resolvedThenable); + try { + return getComponentName(init(payload)); + } catch (x) { + return null; } - - break; } } } @@ -2673,67 +2683,73 @@ function getComponentName(type) { return null; } +var enableProfilerTimer = true; +var warnAboutStringRefs = false; +var enableNewReconciler = false; + // Don't change these two values. They're used by React Dev Tools. -var NoEffect = - /* */ +var NoFlags = + /* */ 0; var PerformedWork = - /* */ + /* */ 1; // You can change the rest (and add more). var Placement = - /* */ + /* */ 2; var Update = - /* */ + /* */ 4; var PlacementAndUpdate = - /* */ + /* */ 6; var Deletion = - /* */ + /* */ 8; var ContentReset = - /* */ + /* */ 16; var Callback = - /* */ + /* */ 32; var DidCapture = - /* */ + /* */ 64; var Ref = - /* */ + /* */ 128; var Snapshot = - /* */ + /* */ 256; var Passive = - /* */ + /* */ 512; var Hydrating = - /* */ + /* */ 1024; var HydratingAndUpdate = - /* */ - 1028; // Passive & Update & Callback & Ref & Snapshot - -var LifecycleEffectMask = - /* */ - 932; // Union of all host effects + /* */ + 1028; +var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = - /* */ - 2047; + /* */ + 4095; // These are not really side effects, but we still reuse this field. + var Incomplete = - /* */ - 2048; -var ShouldCapture = - /* */ + /* */ 4096; +var ShouldCapture = + /* */ + 8192; // TODO (effects) Remove this bit once the new reconciler is synced to the old. -var enableProfilerTimer = true; -var warnAboutStringRefs = false; +var PassiveUnmountPendingDev = + /* */ + 16384; +var ForceUpdateForLegacySuspense = + /* */ + 32768; // Static tags describe aspects of a fiber that are not specific to a render, var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -2748,7 +2764,7 @@ function getNearestMountedFiber(fiber) { do { node = nextNode; - if ((node.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { // This is an insertion or in-progress hydration. The nearest possible // mounted fiber is the parent but we need to continue to figure out // if that one is still mounted. @@ -3008,6 +3024,20 @@ function findCurrentHostFiber(parent) { return null; } +function doesFiberContain(parentFiber, childFiber) { + var node = childFiber; + var parentFiberAlternate = parentFiber.alternate; + + while (node !== null) { + if (node === parentFiber || node === parentFiberAlternate) { + return true; + } + + node = node.return; + } + + return false; +} /** * In the future, we should cleanup callbacks by cancelling them instead of @@ -3497,19 +3527,16 @@ function diff(prevProps, nextProps, validAttributes) { ); } -var PLUGIN_EVENT_SYSTEM = 1; - +// Used as a way to call batchedUpdates when we don't have a reference to // the renderer. Such as when we're dispatching events or if third party // libraries need to call batchedUpdates. Eventually, this API will go away when // everything is batched by default. We'll then have a similar API to opt-out of // scheduled work and instead do synchronous work. // Defaults - var batchedUpdatesImpl = function(fn, bookkeeping) { return fn(bookkeeping); }; var isInsideEventHandler = false; - function batchedUpdates(fn, bookkeeping) { if (isInsideEventHandler) { // If we are currently inside another batch, we need to wait until it @@ -3597,22 +3624,21 @@ function extractPluginEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { var events = null; + var legacyPlugins = plugins; - for (var i = 0; i < plugins.length; i++) { + for (var i = 0; i < legacyPlugins.length; i++) { // Not every plugin in the ordering may be loaded at runtime. - var possiblePlugin = plugins[i]; + var possiblePlugin = legacyPlugins[i]; if (possiblePlugin) { var extractedEvents = possiblePlugin.extractEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ); if (extractedEvents) { @@ -3628,15 +3654,13 @@ function runExtractedPluginEventsInBatch( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { var events = extractPluginEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ); runEventsInBatch(events); } @@ -3659,8 +3683,7 @@ function dispatchEvent(target, topLevelType, nativeEvent) { topLevelType, targetFiber, nativeEvent, - eventTarget, - PLUGIN_EVENT_SYSTEM + eventTarget ); }); // React Native doesn't use ReactControlledComponent but if it did, here's // where it would do it. @@ -3678,6 +3701,7 @@ function shim() { var supportsMutation = false; var commitMount = shim; +var clearContainer = shim; // can re-export everything from this module. @@ -3726,82 +3750,80 @@ if (registerEventHandler) { * This is used for refs on host components. */ -var ReactFabricHostComponent = - /*#__PURE__*/ - (function() { - function ReactFabricHostComponent( - tag, - viewConfig, - props, - internalInstanceHandle - ) { - this._nativeTag = tag; - this.viewConfig = viewConfig; - this.currentProps = props; - this._internalInstanceHandle = internalInstanceHandle; - } - - var _proto = ReactFabricHostComponent.prototype; - - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; +var ReactFabricHostComponent = /*#__PURE__*/ (function() { + function ReactFabricHostComponent( + tag, + viewConfig, + props, + internalInstanceHandle + ) { + this._nativeTag = tag; + this.viewConfig = viewConfig; + this.currentProps = props; + this._internalInstanceHandle = internalInstanceHandle; + } - _proto.measure = function measure(callback) { - fabricMeasure( - this._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + var _proto = ReactFabricHostComponent.prototype; - _proto.measureInWindow = function measureInWindow(callback) { - fabricMeasureInWindow( - this._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - if ( - typeof relativeToNativeNode === "number" || - !(relativeToNativeNode instanceof ReactFabricHostComponent) - ) { - { - error( - "Warning: ref.measureLayout must be called with a ref to a native component." - ); - } + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; - return; - } + _proto.measure = function measure(callback) { + fabricMeasure( + this._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - fabricMeasureLayout( - this._internalInstanceHandle.stateNode.node, - relativeToNativeNode._internalInstanceHandle.stateNode.node, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; + _proto.measureInWindow = function measureInWindow(callback) { + fabricMeasureInWindow( + this._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - _proto.setNativeProps = function setNativeProps(nativeProps) { + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ + { + if ( + typeof relativeToNativeNode === "number" || + !(relativeToNativeNode instanceof ReactFabricHostComponent) + ) { { - error("Warning: setNativeProps is not currently supported in Fabric"); + error( + "Warning: ref.measureLayout must be called with a ref to a native component." + ); } return; - }; + } + + fabricMeasureLayout( + this._internalInstanceHandle.stateNode.node, + relativeToNativeNode._internalInstanceHandle.stateNode.node, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + }; + + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + error("Warning: setNativeProps is not currently supported in Fabric"); + } - return ReactFabricHostComponent; - })(); // eslint-disable-next-line no-unused-expressions + return; + }; + + return ReactFabricHostComponent; +})(); // eslint-disable-next-line no-unused-expressions function appendInitialChild(parentInstance, child) { appendChildNode(parentInstance.node, child.node); } @@ -3897,6 +3919,7 @@ function getPublicInstance(instance) { } function prepareForCommit(containerInfo) { // Noop + return null; } function prepareUpdate( instance, @@ -3917,9 +3940,6 @@ function prepareUpdate( function resetAfterCommit(containerInfo) { // Noop } -function shouldDeprioritizeSubtree(type, props) { - return false; -} function shouldSetTextContent(type, props) { // TODO (bvaughn) Revisit this decision. // Always returning false simplifies the createInstance() implementation, @@ -3992,522 +4012,232 @@ function appendChildToContainerChildSet(childSet, child) { function finalizeContainerChildren(container, newChildren) { completeRoot(container, newChildren); } +function makeClientIdInDEV(warnOnAccessInDEV) { + throw new Error("Not yet implemented"); +} +function preparePortalMount(portalInstance) { + // noop +} -var loggedTypeFailures = {}; -function checkPropTypes(typeSpecs, values, location, componentName) { +var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; +function describeBuiltInComponentFrame(name, source, ownerFn) { { - // $FlowFixMe This is okay but Flow doesn't know it. - var has = Function.call.bind(Object.prototype.hasOwnProperty); - - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - var err = Error( - (componentName || "React class") + - ": " + - location + - " type `" + - typeSpecName + - "` is invalid; " + - "it must be a function, usually from the `prop-types` package, but received `" + - typeof typeSpecs[typeSpecName] + - "`." + - "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." - ); - err.name = "Invariant Violation"; - throw err; - } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; - } - - if (error$1 && !(error$1 instanceof Error)) { - error( - "%s: type specification of %s" + - " `%s` is invalid; the type checker " + - "function must return `null` or an `Error` but returned a %s. " + - "You may have forgotten to pass an argument to the type checker " + - "creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and " + - "shape all require an argument).", - componentName || "React class", - location, - typeSpecName, - typeof error$1 - ); - } - - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; + var ownerName = null; - error("Failed %s type: %s", location, error$1.message); - } - } + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } - } -} - -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -var reactEmoji = "\u269B"; -var warningEmoji = "\u26D4"; -var supportsUserTiming = - typeof performance !== "undefined" && - typeof performance.mark === "function" && - typeof performance.clearMarks === "function" && - typeof performance.measure === "function" && - typeof performance.clearMeasures === "function"; // Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? - -var currentFiber = null; // If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). - -var currentPhase = null; -var currentPhaseFiber = null; // Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. - -var isCommitting = false; -var hasScheduledUpdateInCurrentCommit = false; -var hasScheduledUpdateInCurrentPhase = false; -var commitCountInCurrentWorkLoop = 0; -var effectCountInCurrentCommit = 0; -// to avoid stretch the commit phase with measurement overhead. - -var labelsInCurrentCommit = new Set(); - -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; - -var formatLabel = function(label, warning) { - var prefix = warning ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning ? " Warning: " + warning : ""; - return "" + prefix + label + suffix; -}; - -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; -var clearMark = function(markName) { - performance.clearMarks(formatMarkName(markName)); -}; - -var endMark = function(label, markName, warning) { - var formattedMarkName = formatMarkName(markName); - var formattedLabel = formatLabel(label, warning); - - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. - // Clear marks immediately to avoid growing buffer. - - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; - -var getFiberMarkName = function(label, debugID) { - return label + " (#" + debugID + ")"; -}; - -var getFiberLabel = function(componentName, isMounted, phase) { - if (phase === null) { - // These are composite component total time measurements. - return componentName + " [" + (isMounted ? "update" : "mount") + "]"; - } else { - // Composite component methods. - return componentName + "." + phase; - } -}; - -var beginFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. - return false; + return describeComponentFrame(name, source, ownerName); } +} +var componentFrameCache; - labelsInCurrentCommit.add(label); - var markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; - -var clearFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; - -var endFiberMark = function(fiber, phase, warning) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning); -}; - -var shouldIgnoreFiber = function(fiber) { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case Fragment: - case ContextProvider: - case ContextConsumer: - case Mode: - return true; +{ + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); +} +var BEFORE_SLASH_RE = /^(.*)[\\\/]/; - default: - return false; - } -}; +function describeComponentFrame(name, source, ownerName) { + var sourceInfo = ""; -var clearPendingPhaseMeasurement = function() { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); - } + if (source) { + var path = source.fileName; + var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: + // prefer "folder/index.js" instead of just "index.js". - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; + if (/^index\./.test(fileName)) { + var match = path.match(BEFORE_SLASH_RE); -var pauseTimers = function() { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - var fiber = currentFiber; + if (match) { + var pathBeforeSlash = match[1]; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); + if (pathBeforeSlash) { + var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); + fileName = folderName + "/" + fileName; + } + } } - fiber = fiber.return; - } -}; - -var resumeTimersRecursively = function(fiber) { - if (fiber.return !== null) { - resumeTimersRecursively(fiber.return); - } - - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); + sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; + } else if (ownerName) { + sourceInfo = " (created by " + ownerName + ")"; } -}; -var resumeTimers = function() { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; + return "\n in " + (name || "Unknown") + sourceInfo; +} -function recordEffect() { +function describeClassComponentFrame(ctor, source, ownerFn) { { - effectCountInCurrentCommit++; + return describeFunctionComponentFrame(ctor, source, ownerFn); } } -function recordScheduleUpdate() { +function describeFunctionComponentFrame(fn, source, ownerFn) { { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; + if (!fn) { + return ""; } - } -} -function startWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, this is the fiber to unwind from. - currentFiber = fiber; + var name = fn.displayName || fn.name || null; + var ownerName = null; - if (!beginFiberMark(fiber, null)) { - return; + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } - fiber._debugIsCurrentlyTiming = true; - } -} -function cancelWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); + return describeComponentFrame(name, source, ownerName); } } -function stopWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, its parent is the fiber to unwind from. - - currentFiber = fiber.return; - - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); +function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; } -} -function stopFailedWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber.return; - - if (!fiber._debugIsCurrentlyTiming) { - return; + if (typeof type === "function") { + { + return describeFunctionComponentFrame(type, source, ownerFn); } - - fiber._debugIsCurrentlyTiming = false; - var warning = - fiber.tag === SuspenseComponent - ? "Rendering was suspended" - : "An error was thrown inside this error boundary"; - endFiberMark(fiber, null, warning); } -} -function startPhaseTimer(fiber, phase) { - { - if (!supportsUserTiming) { - return; - } - - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - - currentPhaseFiber = fiber; - currentPhase = phase; + if (typeof type === "string") { + return describeBuiltInComponentFrame(type, source, ownerFn); } -} -function stopPhaseTimer() { - { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - var warning = hasScheduledUpdateInCurrentPhase - ? "Scheduled a cascading update" - : null; - endFiberMark(currentPhaseFiber, currentPhase, warning); - } + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense", source, ownerFn); - currentPhase = null; - currentPhaseFiber = null; + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); } -} -function startWorkLoopTimer(nextUnitOfWork) { - { - currentFiber = nextUnitOfWork; - - if (!supportsUserTiming) { - return; - } - commitCountInCurrentWorkLoop = 0; // This is top level call. - // Any other measurements are performed within. - - beginMark("(React Tree Reconciliation)"); // Resume any measurements that were in progress during the last loop. + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render, source, ownerFn); - resumeTimers(); - } -} -function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { - { - if (!supportsUserTiming) { - return; - } + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); - var warning = null; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning = "A top-level update interrupted the previous render"; - } else { - var componentName = getComponentName(interruptedBy.type) || "Unknown"; - warning = - "An update to " + componentName + " interrupted the previous render"; + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} } - } else if (commitCountInCurrentWorkLoop > 1) { - warning = "There were cascading updates"; } - - commitCountInCurrentWorkLoop = 0; - var label = didCompleteRoot - ? "(React Tree Reconciliation: Completed Root)" - : "(React Tree Reconciliation: Yielded)"; // Pause any measurements until the next loop. - - pauseTimers(); - endMark(label, "(React Tree Reconciliation)", warning); } + + return ""; } -function startCommitTimer() { + +var loggedTypeFailures = {}; +var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + +function setCurrentlyValidatingElement(element) { { - if (!supportsUserTiming) { - return; + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); } - - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark("(Committing Changes)"); } } -function stopCommitTimer() { + +function checkPropTypes(typeSpecs, values, location, componentName, element) { { - if (!supportsUserTiming) { - return; - } + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(Object.prototype.hasOwnProperty); - var warning = null; + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. - if (hasScheduledUpdateInCurrentCommit) { - warning = "Lifecycle hook scheduled a cascading update"; - } else if (commitCountInCurrentWorkLoop > 0) { - warning = "Caused by a cascading update in earlier commit"; - } + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + var err = Error( + (componentName || "React class") + + ": " + + location + + " type `" + + typeSpecName + + "` is invalid; " + + "it must be a function, usually from the `prop-types` package, but received `" + + typeof typeSpecs[typeSpecName] + + "`." + + "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." + ); + err.name = "Invariant Violation"; + throw err; + } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); - endMark("(Committing Changes)", "(Committing Changes)", warning); - } -} -function startCommitSnapshotEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - effectCountInCurrentCommit = 0; - beginMark("(Committing Snapshot Effects)"); - } -} -function stopCommitSnapshotEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Snapshot Effects: " + count + " Total)", - "(Committing Snapshot Effects)", - null - ); - } -} -function startCommitHostEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + error( + "%s: type specification of %s" + + " `%s` is invalid; the type checker " + + "function must return `null` or an `Error` but returned a %s. " + + "You may have forgotten to pass an argument to the type checker " + + "creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and " + + "shape all require an argument).", + componentName || "React class", + location, + typeSpecName, + typeof error$1 + ); - effectCountInCurrentCommit = 0; - beginMark("(Committing Host Effects)"); - } -} -function stopCommitHostEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + setCurrentlyValidatingElement(null); + } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Host Effects: " + count + " Total)", - "(Committing Host Effects)", - null - ); - } -} -function startCommitLifeCyclesTimer() { - { - if (!supportsUserTiming) { - return; - } + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); - effectCountInCurrentCommit = 0; - beginMark("(Calling Lifecycle Methods)"); - } -} -function stopCommitLifeCyclesTimer() { - { - if (!supportsUserTiming) { - return; - } + error("Failed %s type: %s", location, error$1.message); - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Calling Lifecycle Methods: " + count + " Total)", - "(Calling Lifecycle Methods)", - null - ); + setCurrentlyValidatingElement(null); + } + } + } } } @@ -4714,10 +4444,7 @@ function processChildContext(fiber, type, parentContext) { return parentContext; } - var childContext; - startPhaseTimer(fiber, "getChildContext"); - childContext = instance.getChildContext(); - stopPhaseTimer(); + var childContext = instance.getChildContext(); for (var contextKey in childContext) { if (!(contextKey in childContextTypes)) { @@ -4735,7 +4462,7 @@ function processChildContext(fiber, type, parentContext) { checkPropTypes(childContextTypes, childContext, "child context", name); } - return Object.assign({}, parentContext, {}, childContext); + return Object.assign({}, parentContext, childContext); } } @@ -4838,20 +4565,112 @@ var LegacyRoot = 0; var BlockingRoot = 1; var ConcurrentRoot = 2; +var rendererID = null; +var injectedHook = null; +var hasLoggedError = false; +var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } + + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + + if (!hook.supportsFiber) { + { + error( + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://reactjs.org/link/react-devtools" + ); + } // DevTools exists, even though it doesn't support Fiber. + + return true; + } + + try { + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + + injectedHook = hook; + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); + } + } // DevTools exists + + return true; +} +function onScheduleRoot(root, children) { + { + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} +function onCommitRoot(root, priorityLevel) { + if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; + + if (enableProfilerTimer) { + injectedHook.onCommitFiberRoot( + rendererID, + root, + priorityLevel, + didError + ); + } else { + injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} +function onCommitUnmount(fiber) { + if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} + // Intentionally not named imports because Rollup would use dynamic dispatch for -var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, - Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, - Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, - Scheduler_shouldYield = Scheduler.unstable_shouldYield, - Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, - Scheduler_getCurrentPriorityLevel = - Scheduler.unstable_getCurrentPriorityLevel, - Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, - Scheduler_UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, - Scheduler_NormalPriority = Scheduler.unstable_NormalPriority, - Scheduler_LowPriority = Scheduler.unstable_LowPriority, - Scheduler_IdlePriority = Scheduler.unstable_IdlePriority; +var Scheduler_now = Scheduler.unstable_now; { // Provide explicit error message when production+profiling bundle of e.g. @@ -4864,12 +4683,10 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } - -var fakeCallbackNode = {}; // Except for NoPriority, these correspond to Scheduler priorities. We use // ascending numbers so we can compare them like numbers. They start at 90 to // avoid clashing with Scheduler's priorities. @@ -4880,1214 +4697,1434 @@ var LowPriority = 96; var IdlePriority = 95; // NoPriority is the absence of priority. Also React-only. var NoPriority = 90; -var shouldYield = Scheduler_shouldYield; -var requestPaint = // Fall back gracefully if we're running an older version of Scheduler. - Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : function() {}; -var syncQueue = null; -var immediateQueueCallbackNode = null; -var isFlushingSyncQueue = false; var initialTimeMs = Scheduler_now(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. -// This will be the case for modern browsers that support `performance.now`. In -// older browsers, Scheduler falls back to `Date.now`, which returns a Unix -// timestamp. In that case, subtract the module initialization time to simulate -// the behavior of performance.now and keep our times small enough to fit -// within 32 bits. -// TODO: Consider lifting this into Scheduler. - -var now = - initialTimeMs < 10000 - ? Scheduler_now - : function() { - return Scheduler_now() - initialTimeMs; - }; -function getCurrentPriorityLevel() { - switch (Scheduler_getCurrentPriorityLevel()) { - case Scheduler_ImmediatePriority: - return ImmediatePriority; - - case Scheduler_UserBlockingPriority: - return UserBlockingPriority; - - case Scheduler_NormalPriority: - return NormalPriority; - - case Scheduler_LowPriority: - return LowPriority; - - case Scheduler_IdlePriority: - return IdlePriority; - - default: { - throw Error("Unknown priority level."); - } - } -} - -function reactPriorityToSchedulerPriority(reactPriorityLevel) { - switch (reactPriorityLevel) { - case ImmediatePriority: - return Scheduler_ImmediatePriority; - case UserBlockingPriority: - return Scheduler_UserBlockingPriority; +var SyncLanePriority = 15; +var SyncBatchedLanePriority = 14; +var InputDiscreteHydrationLanePriority = 13; +var InputDiscreteLanePriority = 12; +var InputContinuousHydrationLanePriority = 11; +var InputContinuousLanePriority = 10; +var DefaultHydrationLanePriority = 9; +var DefaultLanePriority = 8; +var TransitionHydrationPriority = 7; +var TransitionPriority = 6; +var RetryLanePriority = 5; +var SelectiveHydrationLanePriority = 4; +var IdleHydrationLanePriority = 3; +var IdleLanePriority = 2; +var OffscreenLanePriority = 1; +var NoLanePriority = 0; +var TotalLanes = 31; +var NoLanes = + /* */ + 0; +var NoLane = + /* */ + 0; +var SyncLane = + /* */ + 1; +var SyncBatchedLane = + /* */ + 2; +var InputDiscreteHydrationLane = + /* */ + 4; +var InputDiscreteLanes = + /* */ + 24; +var InputContinuousHydrationLane = + /* */ + 32; +var InputContinuousLanes = + /* */ + 192; +var DefaultHydrationLane = + /* */ + 256; +var DefaultLanes = + /* */ + 3584; +var TransitionHydrationLane = + /* */ + 4096; +var TransitionLanes = + /* */ + 4186112; +var RetryLanes = + /* */ + 62914560; +var SomeRetryLane = + /* */ + 33554432; +var SelectiveHydrationLane = + /* */ + 67108864; +var NonIdleLanes = + /* */ + 134217727; +var IdleHydrationLane = + /* */ + 134217728; +var IdleLanes = + /* */ + 805306368; +var OffscreenLane = + /* */ + 1073741824; +var NoTimestamp = -1; +// Used by getHighestPriorityLanes and getNextLanes: - case NormalPriority: - return Scheduler_NormalPriority; +var return_highestLanePriority = DefaultLanePriority; - case LowPriority: - return Scheduler_LowPriority; +function getHighestPriorityLanes(lanes) { + if ((SyncLane & lanes) !== NoLanes) { + return_highestLanePriority = SyncLanePriority; + return SyncLane; + } - case IdlePriority: - return Scheduler_IdlePriority; + if ((SyncBatchedLane & lanes) !== NoLanes) { + return_highestLanePriority = SyncBatchedLanePriority; + return SyncBatchedLane; + } - default: { - throw Error("Unknown priority level."); - } + if ((InputDiscreteHydrationLane & lanes) !== NoLanes) { + return_highestLanePriority = InputDiscreteHydrationLanePriority; + return InputDiscreteHydrationLane; } -} -function runWithPriority(reactPriorityLevel, fn) { - var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_runWithPriority(priorityLevel, fn); -} -function scheduleCallback(reactPriorityLevel, callback, options) { - var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_scheduleCallback(priorityLevel, callback, options); -} -function scheduleSyncCallback(callback) { - // Push this callback into an internal queue. We'll flush these either in - // the next tick, or earlier if something calls `flushSyncCallbackQueue`. - if (syncQueue === null) { - syncQueue = [callback]; // Flush the queue in the next tick, at the earliest. + var inputDiscreteLanes = InputDiscreteLanes & lanes; - immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ); - } else { - // Push onto existing queue. Don't need to schedule a callback because - // we already scheduled one when we created the queue. - syncQueue.push(callback); + if (inputDiscreteLanes !== NoLanes) { + return_highestLanePriority = InputDiscreteLanePriority; + return inputDiscreteLanes; } - return fakeCallbackNode; -} -function cancelCallback(callbackNode) { - if (callbackNode !== fakeCallbackNode) { - Scheduler_cancelCallback(callbackNode); - } -} -function flushSyncCallbackQueue() { - if (immediateQueueCallbackNode !== null) { - var node = immediateQueueCallbackNode; - immediateQueueCallbackNode = null; - Scheduler_cancelCallback(node); + if ((lanes & InputContinuousHydrationLane) !== NoLanes) { + return_highestLanePriority = InputContinuousHydrationLanePriority; + return InputContinuousHydrationLane; } - flushSyncCallbackQueueImpl(); -} - -function flushSyncCallbackQueueImpl() { - if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrancy. - isFlushingSyncQueue = true; - var i = 0; - - try { - var _isSync = true; - var queue = syncQueue; - runWithPriority(ImmediatePriority, function() { - for (; i < queue.length; i++) { - var callback = queue[i]; + var inputContinuousLanes = InputContinuousLanes & lanes; - do { - callback = callback(_isSync); - } while (callback !== null); - } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick - - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue - ); - throw error; - } finally { - isFlushingSyncQueue = false; - } + if (inputContinuousLanes !== NoLanes) { + return_highestLanePriority = InputContinuousLanePriority; + return inputContinuousLanes; } -} -var NoMode = 0; -var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root -// tag instead + if ((lanes & DefaultHydrationLane) !== NoLanes) { + return_highestLanePriority = DefaultHydrationLanePriority; + return DefaultHydrationLane; + } -var BlockingMode = 2; -var ConcurrentMode = 4; -var ProfileMode = 8; + var defaultLanes = DefaultLanes & lanes; -// Max 31 bit integer. The max integer size in V8 for 32-bit systems. -// Math.pow(2, 30) - 1 -// 0b111111111111111111111111111111 -var MAX_SIGNED_31_BIT_INT = 1073741823; + if (defaultLanes !== NoLanes) { + return_highestLanePriority = DefaultLanePriority; + return defaultLanes; + } -var NoWork = 0; // TODO: Think of a better name for Never. The key difference with Idle is that -// Never work can be committed in an inconsistent state without tearing the UI. -// The main example is offscreen content, like a hidden subtree. So one possible -// name is Offscreen. However, it also includes dehydrated Suspense boundaries, -// which are inconsistent in the sense that they haven't finished yet, but -// aren't visibly inconsistent because the server rendered HTML matches what the -// hydrated tree would look like. + if ((lanes & TransitionHydrationLane) !== NoLanes) { + return_highestLanePriority = TransitionHydrationPriority; + return TransitionHydrationLane; + } -var Never = 1; // Idle is slightly higher priority than Never. It must completely finish in -// order to be consistent. + var transitionLanes = TransitionLanes & lanes; -var Idle = 2; // Continuous Hydration is slightly higher than Idle and is used to increase -var Sync = MAX_SIGNED_31_BIT_INT; -var Batched = Sync - 1; -var UNIT_SIZE = 10; -var MAGIC_NUMBER_OFFSET = Batched - 1; // 1 unit of expiration time represents 10ms. + if (transitionLanes !== NoLanes) { + return_highestLanePriority = TransitionPriority; + return transitionLanes; + } -function msToExpirationTime(ms) { - // Always subtract from the offset so that we don't clash with the magic number for NoWork. - return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0); -} -function expirationTimeToMs(expirationTime) { - return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE; -} + var retryLanes = RetryLanes & lanes; -function ceiling(num, precision) { - return (((num / precision) | 0) + 1) * precision; -} + if (retryLanes !== NoLanes) { + return_highestLanePriority = RetryLanePriority; + return retryLanes; + } -function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { - return ( - MAGIC_NUMBER_OFFSET - - ceiling( - MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE, - bucketSizeMs / UNIT_SIZE - ) - ); -} // TODO: This corresponds to Scheduler's NormalPriority, not LowPriority. Update -// the names to reflect. - -var LOW_PRIORITY_EXPIRATION = 5000; -var LOW_PRIORITY_BATCH_SIZE = 250; -function computeAsyncExpiration(currentTime) { - return computeExpirationBucket( - currentTime, - LOW_PRIORITY_EXPIRATION, - LOW_PRIORITY_BATCH_SIZE - ); -} -function computeSuspenseExpiration(currentTime, timeoutMs) { - // TODO: Should we warn if timeoutMs is lower than the normal pri expiration time? - return computeExpirationBucket( - currentTime, - timeoutMs, - LOW_PRIORITY_BATCH_SIZE - ); -} // We intentionally set a higher expiration time for interactive updates in -// dev than in production. -// -// If the main thread is being blocked so long that you hit the expiration, -// it's a problem that could be solved with better scheduling. -// -// People will be more likely to notice this and fix it with the long -// expiration time in development. -// -// In production we opt for better UX at the risk of masking scheduling -// problems, by expiring fast. - -var HIGH_PRIORITY_EXPIRATION = 500; -var HIGH_PRIORITY_BATCH_SIZE = 100; -function computeInteractiveExpiration(currentTime) { - return computeExpirationBucket( - currentTime, - HIGH_PRIORITY_EXPIRATION, - HIGH_PRIORITY_BATCH_SIZE - ); -} -function inferPriorityFromExpirationTime(currentTime, expirationTime) { - if (expirationTime === Sync) { - return ImmediatePriority; + if (lanes & SelectiveHydrationLane) { + return_highestLanePriority = SelectiveHydrationLanePriority; + return SelectiveHydrationLane; } - if (expirationTime === Never || expirationTime === Idle) { - return IdlePriority; + if ((lanes & IdleHydrationLane) !== NoLanes) { + return_highestLanePriority = IdleHydrationLanePriority; + return IdleHydrationLane; } - var msUntil = - expirationTimeToMs(expirationTime) - expirationTimeToMs(currentTime); + var idleLanes = IdleLanes & lanes; - if (msUntil <= 0) { - return ImmediatePriority; + if (idleLanes !== NoLanes) { + return_highestLanePriority = IdleLanePriority; + return idleLanes; } - if (msUntil <= HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE) { - return UserBlockingPriority; + if ((OffscreenLane & lanes) !== NoLanes) { + return_highestLanePriority = OffscreenLanePriority; + return OffscreenLane; } - if (msUntil <= LOW_PRIORITY_EXPIRATION + LOW_PRIORITY_BATCH_SIZE) { - return NormalPriority; - } // TODO: Handle LowPriority - // Assume anything lower has idle priority + { + error("Should have found matching lanes. This is a bug in React."); + } // This shouldn't be reachable, but as a fallback, return the entire bitmask. - return IdlePriority; + return_highestLanePriority = DefaultLanePriority; + return lanes; } -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - return ( - (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare - ); -} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case ImmediatePriority: + return SyncLanePriority; -var objectIs = typeof Object.is === "function" ? Object.is : is; + case UserBlockingPriority: + return InputContinuousLanePriority; -var hasOwnProperty = Object.prototype.hasOwnProperty; -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ + case NormalPriority: + case LowPriority: + // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration. + return DefaultLanePriority; -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; - } + case IdlePriority: + return IdleLanePriority; - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; + default: + return NoLanePriority; } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case SyncLanePriority: + case SyncBatchedLanePriority: + return ImmediatePriority; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + case InputDiscreteHydrationLanePriority: + case InputDiscreteLanePriority: + case InputContinuousHydrationLanePriority: + case InputContinuousLanePriority: + return UserBlockingPriority; - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + case DefaultHydrationLanePriority: + case DefaultLanePriority: + case TransitionHydrationPriority: + case TransitionPriority: + case SelectiveHydrationLanePriority: + case RetryLanePriority: + return NormalPriority; - for (var i = 0; i < keysA.length; i++) { - if ( - !hasOwnProperty.call(objB, keysA[i]) || - !objectIs(objA[keysA[i]], objB[keysA[i]]) - ) { - return false; + case IdleHydrationLanePriority: + case IdleLanePriority: + case OffscreenLanePriority: + return IdlePriority; + + case NoLanePriority: + return NoPriority; + + default: { + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); } } - - return true; } +function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; -function describeComponentFrame(name, source, ownerName) { - var sourceInfo = ""; + if (pendingLanes === NoLanes) { + return_highestLanePriority = NoLanePriority; + return NoLanes; + } - if (source) { - var path = source.fileName; - var fileName = path.replace(BEFORE_SLASH_RE, ""); + var nextLanes = NoLanes; + var nextLanePriority = NoLanePriority; + var expiredLanes = root.expiredLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; // Check if any work has expired. - { - // In DEV, include code for a common special case: - // prefer "folder/index.js" instead of just "index.js". - if (/^index\./.test(fileName)) { - var match = path.match(BEFORE_SLASH_RE); + if (expiredLanes !== NoLanes) { + nextLanes = expiredLanes; + nextLanePriority = return_highestLanePriority = SyncLanePriority; + } else { + // Do not work on any idle work until all the non-idle work has finished, + // even if the work is suspended. + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; - if (match) { - var pathBeforeSlash = match[1]; + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - if (pathBeforeSlash) { - var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); - fileName = folderName + "/" + fileName; - } + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + nextLanePriority = return_highestLanePriority; + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + nextLanePriority = return_highestLanePriority; } } - } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; - sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; - } else if (ownerName) { - sourceInfo = " (created by " + ownerName + ")"; + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + nextLanePriority = return_highestLanePriority; + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + nextLanePriority = return_highestLanePriority; + } + } + } } - return "\n in " + (name || "Unknown") + sourceInfo; -} + if (nextLanes === NoLanes) { + // This should only be reachable if we're suspended + // TODO: Consider warning in this path if a fallback timer is not scheduled. + return NoLanes; + } // If there are higher priority lanes, we'll include them even if they + // are suspended. -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + nextLanes = pendingLanes & getEqualOrHigherPriorityLanes(nextLanes); // If we're already in the middle of a render, switching lanes will interrupt + // it and we'll lose our progress. We should only do this if the new lanes are + // higher priority. -function describeFiber(fiber) { - switch (fiber.tag) { - case HostRoot: - case HostPortal: - case HostText: - case Fragment: - case ContextProvider: - case ContextConsumer: - return ""; + if ( + wipLanes !== NoLanes && + wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't + // bother waiting until the root is complete. + (wipLanes & suspendedLanes) === NoLanes + ) { + getHighestPriorityLanes(wipLanes); + var wipLanePriority = return_highestLanePriority; - default: - var owner = fiber._debugOwner; - var source = fiber._debugSource; - var name = getComponentName(fiber.type); - var ownerName = null; + if (nextLanePriority <= wipLanePriority) { + return wipLanes; + } else { + return_highestLanePriority = nextLanePriority; + } + } // Check for entangled lanes and add them to the batch. + // + // A lane is said to be entangled with another when it's not allowed to render + // in a batch that does not also include the other lane. Typically we do this + // when multiple updates have the same source, and we only want to respond to + // the most recent event from that source. + // + // Note that we apply entanglements *after* checking for partial work above. + // This means that if a lane is entangled during an interleaved event while + // it's already rendering, we won't interrupt it. This is intentional, since + // entanglement is usually "best effort": we'll try our best to render the + // lanes in the same batch, but it's not worth throwing out partially + // completed work in order to do it. + // + // For those exceptions where entanglement is semantically important, like + // useMutableSource, we should ensure that there is no partial work at the + // time we apply the entanglement. - if (owner) { - ownerName = getComponentName(owner.type); - } + var entangledLanes = root.entangledLanes; - return describeComponentFrame(name, source, ownerName); + if (entangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = nextLanes & entangledLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + nextLanes |= entanglements[index]; + lanes &= ~lane; + } } + + return nextLanes; } +function getMostRecentEventTime(root, lanes) { + var eventTimes = root.eventTimes; + var mostRecentEventTime = NoTimestamp; -function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - var node = workInProgress; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var eventTime = eventTimes[index]; - do { - info += describeFiber(node); - node = node.return; - } while (node); + if (eventTime > mostRecentEventTime) { + mostRecentEventTime = eventTime; + } + + lanes &= ~lane; + } - return info; + return mostRecentEventTime; } -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; - } - var owner = current._debugOwner; +function computeExpirationTime(lane, currentTime) { + // TODO: Expiration heuristic is constant per lane, so could use a map. + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; - if (owner !== null && typeof owner !== "undefined") { - return getComponentName(owner.type); + if (priority >= InputContinuousLanePriority) { + // User interactions should expire slightly more quickly. + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. When + // we made it larger, a product metric in www regressed, suggesting there's + // a user interaction that's being starved by a series of synchronous + // updates. If that theory is correct, the proper solution is to fix the + // starvation. However, this scenario supports the idea that expiration + // times are an important safeguard when starvation does happen. + // + // Also note that, in the case of user input specifically, this will soon no + // longer be an issue because we plan to make user input synchronous by + // default (until you enter `startTransition`, of course.) + // + // If weren't planning to make these updates synchronous soon anyway, I + // would probably make this number a configurable parameter. + return currentTime + 250; + } else if (priority >= TransitionPriority) { + return currentTime + 5000; + } else { + // Anything idle priority or lower should never expire. + return NoTimestamp; + } +} + +function markStarvedLanesAsExpired(root, currentTime) { + // TODO: This gets called every time we yield. We can optimize by storing + // the earliest expiration time on the root. Then use that to quickly bail out + // of this function. + var pendingLanes = root.pendingLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; + var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their + // expiration time. If so, we'll assume the update is being starved and mark + // it as expired to force it to finish. + + var lanes = pendingLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; + + if (expirationTime === NoTimestamp) { + // Found a pending lane with no expiration time. If it's not suspended, or + // if it's pinged, assume it's CPU-bound. Compute a new expiration time + // using the current time. + if ( + (lane & suspendedLanes) === NoLanes || + (lane & pingedLanes) !== NoLanes + ) { + // Assumes timestamps are monotonically increasing. + expirationTimes[index] = computeExpirationTime(lane, currentTime); + } + } else if (expirationTime <= currentTime) { + // This lane expired + root.expiredLanes |= lane; } + + lanes &= ~lane; } +} // This returns the highest priority pending lanes regardless of whether they +function getLanesToRetrySynchronouslyOnError(root) { + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - return null; -} -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } - return getStackByFiberInDevAndProd(current); + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; } + + return NoLanes; } -function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } +function returnNextLanesPriority() { + return return_highestLanePriority; } -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } +function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; } -function setIsRendering(rendering) { - { - isRendering = rendering; - } +function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; } +function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; +} // To ensure consistency across multiple updates in the same event, this should +// be a pure function, so that it always returns the same lane for given inputs. + +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case NoLanePriority: + break; -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function(fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordLegacyContextWarning: function(fiber, instance) {}, - flushLegacyContextWarning: function() {}, - discardPendingWarnings: function() {} -}; + case SyncLanePriority: + return SyncLane; -{ - var findStrictRoot = function(fiber) { - var maybeStrictRoot = null; - var node = fiber; + case SyncBatchedLanePriority: + return SyncBatchedLane; - while (node !== null) { - if (node.mode & StrictMode) { - maybeStrictRoot = node; + case InputDiscreteLanePriority: { + var _lane = pickArbitraryLane(InputDiscreteLanes & ~wipLanes); + + if (_lane === NoLane) { + // Shift to the next priority level + return findUpdateLane(InputContinuousLanePriority, wipLanes); } - node = node.return; + return _lane; } - return maybeStrictRoot; - }; + case InputContinuousLanePriority: { + var _lane2 = pickArbitraryLane(InputContinuousLanes & ~wipLanes); - var setToSortedString = function(set) { - var array = []; - set.forEach(function(value) { - array.push(value); - }); - return array.sort().join(", "); - }; + if (_lane2 === NoLane) { + // Shift to the next priority level + return findUpdateLane(DefaultLanePriority, wipLanes); + } - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + return _lane2; + } - var didWarnAboutUnsafeLifecycles = new Set(); + case DefaultLanePriority: { + var _lane3 = pickArbitraryLane(DefaultLanes & ~wipLanes); - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - // Dedup strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + if (_lane3 === NoLane) { + // If all the default lanes are already being worked on, look for a + // lane in the transition range. + _lane3 = pickArbitraryLane(TransitionLanes & ~wipLanes); - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + if (_lane3 === NoLane) { + // All the transition lanes are taken, too. This should be very + // rare, but as a last resort, pick a default lane. This will have + // the effect of interrupting the current work-in-progress render. + _lane3 = pickArbitraryLane(DefaultLanes); + } + } - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + return _lane3; } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } + case TransitionPriority: // Should be handled by findTransitionLane instead - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + case RetryLanePriority: + // Should be handled by findRetryLane instead + break; - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + case IdleLanePriority: + var lane = pickArbitraryLane(IdleLanes & ~wipLanes); - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + if (lane === NoLane) { + lane = pickArbitraryLane(IdleLanes); + } - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + return lane; + } - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function(fiber) { - componentWillMountUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + { + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} // To ensure consistency across multiple updates in the same event, this should +// be pure function, so that it always returns the same lane for given inputs. - var UNSAFE_componentWillMountUniqueNames = new Set(); +function findTransitionLane(wipLanes, pendingLanes) { + // First look for lanes that are completely unclaimed, i.e. have no + // pending work. + var lane = pickArbitraryLane(TransitionLanes & ~pendingLanes); - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; + if (lane === NoLane) { + // If all lanes have pending work, look for a lane that isn't currently + // being worked on. + lane = pickArbitraryLane(TransitionLanes & ~wipLanes); + + if (lane === NoLane) { + // If everything is being worked on, pick any lane. This has the + // effect of interrupting the current work-in-progress. + lane = pickArbitraryLane(TransitionLanes); } + } - var componentWillReceivePropsUniqueNames = new Set(); + return lane; +} // To ensure consistency across multiple updates in the same event, this should +// be pure function, so that it always returns the same lane for given inputs. - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } +function findRetryLane(wipLanes) { + // This is a fork of `findUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + var lane = pickArbitraryLane(RetryLanes & ~wipLanes); - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (lane === NoLane) { + lane = pickArbitraryLane(RetryLanes); + } - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + return lane; +} - var componentWillUpdateUniqueNames = new Set(); +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - componentWillUpdateUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } +function getLowestPriorityLane(lanes) { + // This finds the most significant non-zero bit. + var index = 31 - clz32(lanes); + return index < 0 ? NoLanes : 1 << index; +} - var UNSAFE_componentWillUpdateUniqueNames = new Set(); +function getEqualOrHigherPriorityLanes(lanes) { + return (getLowestPriorityLane(lanes) << 1) - 1; +} - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function(fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' +function pickArbitraryLane(lanes) { + // This wrapper function gets inlined. Only exists so to communicate that it + // doesn't matter which bit is selected; you can pick any bit without + // affecting the algorithms where its used. Here I'm using + // getHighestPriorityLane because it requires the fewest operations. + return getHighestPriorityLane(lanes); +} - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); +function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); +} - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); - } +function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); +} - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); +function includesSomeLane(a, b) { + return (a & b) !== NoLanes; +} +function isSubsetOfLanes(set, subset) { + return (set & subset) === subset; +} +function mergeLanes(a, b) { + return a | b; +} +function removeLanes(set, subset) { + return set & ~subset; +} // Seems redundant, but it changes the type from a single lane (used for +// updates) to a group of lanes (used for flushing work). - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } +function laneToLanes(lane) { + return lane; +} +function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But + // it's not practical to try every single possible combination. We need a + // heuristic to decide which lanes to attempt to render, and in which batches. + // For now, we use the same heuristic as in the old ExpirationTimes model: + // retry any lane at equal or lower priority, but don't try updates at higher + // priority without also including the lower priority updates. This works well + // when considering updates across different priority levels, but isn't + // sufficient for updates within the same priority, since we want to treat + // those updates as parallel. + // Unsuspend any update at equal or lower priority. - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + var higherPriorityLanes = updateLane - 1; // Turns 0b1000 into 0b0111 - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + var eventTimes = root.eventTimes; + var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most + // recent event, and we assume time is monotonically increasing. - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); + eventTimes[index] = eventTime; +} +function markRootSuspended(root, suspendedLanes) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. + + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } +} +function markRootPinged(root, pingedLanes, eventTime) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; +} +function hasDiscreteLanes(lanes) { + return (lanes & InputDiscreteLanes) !== NoLanes; +} +function markRootMutableRead(root, updateLane) { + root.mutableReadLanes |= updateLane & root.pendingLanes; +} +function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again + + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + var entanglements = root.entanglements; + var eventTimes = root.eventTimes; + var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work + + var lanes = noLongerPendingLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + eventTimes[index] = NoTimestamp; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } +} +function markRootEntangled(root, entangledLanes) { + root.entangledLanes |= entangledLanes; + var entanglements = root.entanglements; + var lanes = entangledLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] |= entangledLanes; + lanes &= ~lane; + } +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. Only used on lanes, so assume input is an integer. +// Based on: +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +var log = Math.log; +var LN2 = Math.LN2; + +function clz32Fallback(lanes) { + if (lanes === 0) { + return 32; + } + + return (31 - ((log(lanes) / LN2) | 0)) | 0; +} + +// Intentionally not named imports because Rollup would use dynamic dispatch for +var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, + Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, + Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, + Scheduler_shouldYield = Scheduler.unstable_shouldYield, + Scheduler_requestPaint = Scheduler.unstable_requestPaint, + Scheduler_now$1 = Scheduler.unstable_now, + Scheduler_getCurrentPriorityLevel = + Scheduler.unstable_getCurrentPriorityLevel, + Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, + Scheduler_UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, + Scheduler_NormalPriority = Scheduler.unstable_NormalPriority, + Scheduler_LowPriority = Scheduler.unstable_LowPriority, + Scheduler_IdlePriority = Scheduler.unstable_IdlePriority; + +{ + // Provide explicit error message when production+profiling bundle of e.g. + // react-dom is used with production (non-profiling) bundle of + // scheduler/tracing + if ( + !( + tracing.__interactionsRef != null && + tracing.__interactionsRef.current != null + ) + ) { + throw Error( + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" + ); + } +} - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); - } +var fakeCallbackNode = {}; // Except for NoPriority, these correspond to Scheduler priorities. We use +// ascending numbers so we can compare them like numbers. They start at 90 to +// avoid clashing with Scheduler's priorities. - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); +var ImmediatePriority$1 = 99; +var UserBlockingPriority$1 = 98; +var NormalPriority$1 = 97; +var LowPriority$1 = 96; +var IdlePriority$1 = 95; // NoPriority is the absence of priority. Also React-only. - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); - } - }; +var NoPriority$1 = 90; +var shouldYield = Scheduler_shouldYield; +var requestPaint = // Fall back gracefully if we're running an older version of Scheduler. + Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : function() {}; +var syncQueue = null; +var immediateQueueCallbackNode = null; +var isFlushingSyncQueue = false; +var initialTimeMs$1 = Scheduler_now$1(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. +// This will be the case for modern browsers that support `performance.now`. In +// older browsers, Scheduler falls back to `Date.now`, which returns a Unix +// timestamp. In that case, subtract the module initialization time to simulate +// the behavior of performance.now and keep our times small enough to fit +// within 32 bits. +// TODO: Consider lifting this into Scheduler. - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. +var now = + initialTimeMs$1 < 10000 + ? Scheduler_now$1 + : function() { + return Scheduler_now$1() - initialTimeMs$1; + }; +function getCurrentPriorityLevel() { + switch (Scheduler_getCurrentPriorityLevel()) { + case Scheduler_ImmediatePriority: + return ImmediatePriority$1; - var didWarnAboutLegacyContext = new Set(); + case Scheduler_UserBlockingPriority: + return UserBlockingPriority$1; - ReactStrictModeWarnings.recordLegacyContextWarning = function( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + case Scheduler_NormalPriority: + return NormalPriority$1; - if (strictRoot === null) { - error( - "Expected to find a StrictMode component in a strict mode tree. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + case Scheduler_LowPriority: + return LowPriority$1; - return; - } // Dedup strategy: Warn once per component. + case Scheduler_IdlePriority: + return IdlePriority$1; - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; + default: { + throw Error("Unknown priority level."); } + } +} - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); +function reactPriorityToSchedulerPriority(reactPriorityLevel) { + switch (reactPriorityLevel) { + case ImmediatePriority$1: + return Scheduler_ImmediatePriority; - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } + case UserBlockingPriority$1: + return Scheduler_UserBlockingPriority; - warningsForRoot.push(fiber); - } - }; + case NormalPriority$1: + return Scheduler_NormalPriority; - ReactStrictModeWarnings.flushLegacyContextWarning = function() { - pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } + case LowPriority$1: + return Scheduler_LowPriority; - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function(fiber) { - uniqueNames.add(getComponentName(fiber.type) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); - var firstComponentStack = getStackByFiberInDevAndProd(firstFiber); + case IdlePriority$1: + return Scheduler_IdlePriority; - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://fb.me/react-legacy-context" + - "%s", - sortedNames, - firstComponentStack - ); - }); - }; + default: { + throw Error("Unknown priority level."); + } + } +} - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; +function runWithPriority(reactPriorityLevel, fn) { + var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); + return Scheduler_runWithPriority(priorityLevel, fn); +} +function scheduleCallback(reactPriorityLevel, callback, options) { + var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); + return Scheduler_scheduleCallback(priorityLevel, callback, options); } +function scheduleSyncCallback(callback) { + // Push this callback into an internal queue. We'll flush these either in + // the next tick, or earlier if something calls `flushSyncCallbackQueue`. + if (syncQueue === null) { + syncQueue = [callback]; // Flush the queue in the next tick, at the earliest. -var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. + immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ); + } else { + // Push onto existing queue. Don't need to schedule a callback because + // we already scheduled one when we created the queue. + syncQueue.push(callback); + } -var failedBoundaries = null; -var setRefreshHandler = function(handler) { - { - resolveFamily = handler; + return fakeCallbackNode; +} +function cancelCallback(callbackNode) { + if (callbackNode !== fakeCallbackNode) { + Scheduler_cancelCallback(callbackNode); + } +} +function flushSyncCallbackQueue() { + if (immediateQueueCallbackNode !== null) { + var node = immediateQueueCallbackNode; + immediateQueueCallbackNode = null; + Scheduler_cancelCallback(node); } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } - var family = resolveFamily(type); + flushSyncCallbackQueueImpl(); +} - if (family === undefined) { - return type; - } // Use the latest known implementation. +function flushSyncCallbackQueueImpl() { + if (!isFlushingSyncQueue && syncQueue !== null) { + // Prevent re-entrancy. + isFlushingSyncQueue = true; + var i = 0; - return family.current; + { + try { + var _isSync2 = true; + var _queue = syncQueue; + runWithPriority(ImmediatePriority$1, function() { + for (; i < _queue.length; i++) { + var callback = _queue[i]; + + do { + callback = callback(_isSync2); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick + + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue + ); + throw error; + } finally { + isFlushingSyncQueue = false; + } + } } } -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); -} -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } - var family = resolveFamily(type); +// TODO: this is special because it gets imported during build. +var ReactVersion = "17.0.1-454c2211c"; - if (family === undefined) { - // Check if we're dealing with a real forwardRef. Don't want to crash early. - if ( - type !== null && - type !== undefined && - typeof type.render === "function" - ) { - // ForwardRef is special because its resolved .type is an object, - // but it's possible that we only have its inner render function in the map. - // If that inner render function is different, we'll build a new forwardRef type. - var currentRender = resolveFunctionForHotReloading(type.render); +var NoMode = 0; +var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root +// tag instead - if (type.render !== currentRender) { - var syntheticType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: currentRender - }; +var BlockingMode = 2; +var ConcurrentMode = 4; +var ProfileMode = 8; +var DebugTracingMode = 16; - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; - } +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var NoTransition = 0; +function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; +} - return syntheticType; - } - } +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + return ( + (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare + ); +} + +var objectIs = typeof Object.is === "function" ? Object.is : is; + +var hasOwnProperty = Object.prototype.hasOwnProperty; +/** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - return type; - } // Use the latest known implementation. +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - return family.current; + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. + + for (var i = 0; i < keysA.length; i++) { + if ( + !hasOwnProperty.call(objB, keysA[i]) || + !objectIs(objA[keysA[i]], objB[keysA[i]]) + ) { return false; } + } - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. - - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + return true; +} - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } +function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - break; - } + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - case FunctionComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - // We don't know the inner type yet. - // We're going to assume that the lazy inner type is stable, - // and so it is sufficient to avoid reconciling it away. - // We're not going to unwrap or actually use the new lazy type. - needsCompareFamilies = true; - } + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - break; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - break; - } + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - case MemoComponent: - case SimpleMemoComponent: { - if ($$typeofNextType === REACT_MEMO_TYPE) { - // TODO: if it was but can no longer be simple, - // we shouldn't set this. - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); - break; - } + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); - default: - return false; - } // Check if both types have a family and it's the same one. + default: + return ""; + } +} - if (needsCompareFamilies) { - // Note: memo() and forwardRef() we'll compare outer rather than inner type. - // This means both of them need to be registered to preserve state. - // If we unwrapped and compared the inner types for wrappers instead, - // then we would risk falsely saying two separate memo(Foo) - // calls are equivalent because they wrap the same Foo function. - var prevFamily = resolveFamily(prevType); +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; - } - } + do { + info += describeFiber(node); + node = node.return; + } while (node); - return false; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } -function markFailedErrorBoundaryForHotReloading(fiber) { + +var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; +var current = null; +var isRendering = false; +function getCurrentFiberOwnerNameInDevOrNull() { { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; + if (current === null) { + return null; } - if (typeof WeakSet !== "function") { - return; - } + var owner = current._debugOwner; - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); + if (owner !== null && typeof owner !== "undefined") { + return getComponentName(owner.type); } + } - failedBoundaries.add(fiber); + return null; +} + +function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + + return getStackByFiberInDevAndProd(current); } } -var scheduleRefresh = function(root, update) { + +function resetCurrentFiber() { { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; + ReactDebugCurrentFrame$1.getCurrentStack = null; + current = null; + isRendering = false; + } +} +function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame$1.getCurrentStack = getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } +} +function setIsRendering(rendering) { + { + isRendering = rendering; + } +} +function getIsRendering() { + { + return isRendering; + } +} + +var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function(fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function() {}, + recordLegacyContextWarning: function(fiber, instance) {}, + flushLegacyContextWarning: function() {}, + discardPendingWarnings: function() {} +}; + +{ + var findStrictRoot = function(fiber) { + var maybeStrictRoot = null; + var node = fiber; + + while (node !== null) { + if (node.mode & StrictMode) { + maybeStrictRoot = node; + } + + node = node.return; } - var staleFamilies = update.staleFamilies, - updatedFamilies = update.updatedFamilies; - flushPassiveEffects(); - flushSync(function() { - scheduleFibersWithFamiliesRecursively( - root.current, - updatedFamilies, - staleFamilies - ); + return maybeStrictRoot; + }; + + var setToSortedString = function(set) { + var array = []; + set.forEach(function(value) { + array.push(value); }); - } -}; -var scheduleRoot = function(root, element) { - { - if (root.context !== emptyContextObject) { - // Super edge case: root has a legacy _renderSubtree context - // but we don't know the parentComponent so we can't pass it. - // Just ignore. We'll delete this with _renderSubtree code path later. + return array.sort().join(", "); + }; + + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + + var didWarnAboutUnsafeLifecycles = new Set(); + + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( + fiber, + instance + ) { + // Dedup strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { return; } - flushPassiveEffects(); - syncUpdates(function() { - updateContainer(element, root, null, null); - }); - } -}; + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } -function scheduleFibersWithFamiliesRecursively( - fiber, - updatedFamilies, - staleFamilies -) { - { - var alternate = fiber.alternate, - child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - case ForwardRef: - candidateType = type.render; - break; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); } - if (resolveFamily === null) { - throw new Error("Expected resolveFamily to be set during hot reload."); + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); } - var needsRender = false; - var needsRemount = false; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; - if (candidateType !== null) { - var family = resolveFamily(candidateType); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - if (family !== undefined) { - if (staleFamilies.has(family)) { - needsRemount = true; - } else if (updatedFamilies.has(family)) { - if (tag === ClassComponent) { - needsRemount = true; - } else { - needsRender = true; - } - } - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function(fiber) { + componentWillMountUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; - } + var UNSAFE_componentWillMountUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; } - if (needsRemount) { - fiber._debugNeedsRemount = true; + var componentWillReceivePropsUniqueNames = new Set(); + + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; } - if (needsRemount || needsRender) { - scheduleWork(fiber, Sync); + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; } - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); + var componentWillUpdateUniqueNames = new Set(); + + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function(fiber) { + componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; } - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies + var UNSAFE_componentWillUpdateUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function(fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); + + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames ); } - } -} -var findHostInstancesForRefresh = function(root, families) { - { - var hostInstances = new Set(); - var types = new Set( - families.map(function(family) { - return family.current; - }) - ); - findHostInstancesForMatchingFibersRecursively( - root.current, - types, - hostInstances - ); - return hostInstances; - } -}; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); -function findHostInstancesForMatchingFibersRecursively( - fiber, - types, - hostInstances -) { - { - var child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - case ForwardRef: - candidateType = type.render; - break; + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - var didMatch = false; + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); - if (candidateType !== null) { - if (types.has(candidateType)) { - didMatch = true; - } + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 + ); } - if (didMatch) { - // We have a match. This only drills down to the closest host components. - // There's no need to search deeper because for the purpose of giving - // visual feedback, "flashing" outermost parent rectangles is sufficient. - findHostInstancesForFiberShallowly(fiber, hostInstances); - } else { - // If there's no match, maybe there will be one further down in the child tree. - if (child !== null) { - findHostInstancesForMatchingFibersRecursively( - child, - types, - hostInstances - ); - } + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); + + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 ); } - } -} + }; -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. + var didWarnAboutLegacyContext = new Set(); - var node = fiber; + ReactStrictModeWarnings.recordLegacyContextWarning = function( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - while (true) { - switch (node.tag) { - case HostComponent: - hostInstances.add(node.stateNode); - return; + if (strictRoot === null) { + error( + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + return; + } // Dedup strategy: Warn once per component. - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; - } + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - if (node.return === null) { - throw new Error("Expected to reach root first."); + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); } - node = node.return; + warningsForRoot.push(fiber); } - } -} - -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + }; - while (true) { - if (node.tag === HostComponent) { - // We got a match. - foundHostInstances = true; - hostInstances.add(node.stateNode); // There may still be more, so keep searching. - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; + ReactStrictModeWarnings.flushLegacyContextWarning = function() { + pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; } - if (node === fiber) { - return foundHostInstances; - } + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function(fiber) { + uniqueNames.add(getComponentName(fiber.type) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; - } + try { + setCurrentFiber(firstFiber); - node = node.return; + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); } + }); + }; - node.sibling.return = node.return; - node = node.sibling; - } - } - - return false; + ReactStrictModeWarnings.discardPendingWarnings = function() { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; } function resolveDefaultProps(Component, baseProps) { @@ -6107,15 +6144,11 @@ function resolveDefaultProps(Component, baseProps) { return baseProps; } -function readLazyComponentType(lazyComponent) { - initializeLazyComponentType(lazyComponent); - - if (lazyComponent._status !== Resolved) { - throw lazyComponent._result; - } - return lazyComponent._result; -} +// Max 31 bit integer. The max integer size in V8 for 32-bit systems. +// Math.pow(2, 30) - 1 +// 0b111111111111111111111111111111 +var MAX_SIGNED_31_BIT_INT = 1073741823; var valueCursor = createCursor(null); var rendererSigil; @@ -6205,28 +6238,24 @@ function calculateChangedBits(context, newValue, oldValue) { return changedBits | 0; } } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { - // Update the child expiration time of all the ancestors, including - // the alternates. +function scheduleWorkOnParentPath(parent, renderLanes) { + // Update the child lanes of all the ancestors, including the alternates. var node = parent; while (node !== null) { var alternate = node.alternate; - if (node.childExpirationTime < renderExpirationTime) { - node.childExpirationTime = renderExpirationTime; + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } } else if ( alternate !== null && - alternate.childExpirationTime < renderExpirationTime + !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { - alternate.childExpirationTime = renderExpirationTime; + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } else { // Neither alternate was updated, which means the rest of the // ancestor path already has sufficient priority. @@ -6240,7 +6269,7 @@ function propagateContextChange( workInProgress, context, changedBits, - renderExpirationTime + renderLanes ) { var fiber = workInProgress.child; @@ -6267,7 +6296,10 @@ function propagateContextChange( // Match! Schedule an update on this fiber. if (fiber.tag === ClassComponent) { // Schedule a force update on the work-in-progress. - var update = createUpdate(renderExpirationTime, null); + var update = createUpdate( + NoTimestamp, + pickArbitraryLane(renderLanes) + ); update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the // update to the current fiber, too, which means it will persist even if // this render is thrown away. Since it's a race condition, not sure it's @@ -6276,24 +6308,16 @@ function propagateContextChange( enqueueUpdate(fiber, update); } - if (fiber.expirationTime < renderExpirationTime) { - fiber.expirationTime = renderExpirationTime; - } - + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; - if ( - alternate !== null && - alternate.expirationTime < renderExpirationTime - ) { - alternate.expirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); // Mark the expiration time on the list, too. + scheduleWorkOnParentPath(fiber.return, renderLanes); // Mark the updated lanes on the list, too. - if (list.expirationTime < renderExpirationTime) { - list.expirationTime = renderExpirationTime; - } // Since we already found a match, we can stop traversing the + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the // dependency list. break; @@ -6339,7 +6363,7 @@ function propagateContextChange( fiber = nextFiber; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextDependency = null; lastContextWithAllBitsObserved = null; @@ -6349,7 +6373,7 @@ function prepareToReadContext(workInProgress, renderExpirationTime) { var firstContext = dependencies.firstContext; if (firstContext !== null) { - if (dependencies.expirationTime >= renderExpirationTime) { + if (includesSomeLane(dependencies.lanes, renderLanes)) { // Context list has a pending update. Mark that this fiber performed work. markWorkInProgressReceivedUpdate(); } // Reset the work-in-progress list @@ -6403,7 +6427,7 @@ function readContext(context, observedBits) { lastContextDependency = contextItem; currentlyRenderingFiber.dependencies = { - expirationTime: NoWork, + lanes: NoLanes, firstContext: contextItem, responders: null }; @@ -6435,7 +6459,8 @@ var currentlyProcessingQueue; function initializeUpdateQueue(fiber) { var queue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, @@ -6451,28 +6476,23 @@ function cloneUpdateQueue(current, workInProgress) { if (queue === currentQueue) { var clone = { baseState: currentQueue.baseState, - baseQueue: currentQueue.baseQueue, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, shared: currentQueue.shared, effects: currentQueue.effects }; workInProgress.updateQueue = clone; } } -function createUpdate(expirationTime, suspenseConfig) { +function createUpdate(eventTime, lane) { var update = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, + eventTime: eventTime, + lane: lane, tag: UpdateState, payload: null, callback: null, next: null }; - update.next = update; - - { - update.priority = getCurrentPriorityLevel(); - } - return update; } function enqueueUpdate(fiber, update) { @@ -6512,25 +6532,84 @@ function enqueueUpdate(fiber, update) { } } } -function enqueueCapturedUpdate(workInProgress, update) { +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. + var current = workInProgress.alternate; if (current !== null) { - // Ensure the work-in-progress queue is a clone - cloneUpdateQueue(current, workInProgress); - } // Captured updates go only on the work-in-progress queue. + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; + + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; + + do { + var clone = { + eventTime: update.eventTime, + lane: update.lane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - var queue = workInProgress.updateQueue; // Append the update to the end of the list. + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } - var last = queue.baseQueue; + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - if (last === null) { - queue.baseQueue = update.next = update; - update.next = update; + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } + + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; } else { - update.next = last.next; - last.next = update; + lastBaseUpdate.next = capturedUpdate; } + + queue.lastBaseUpdate = capturedUpdate; } function getStateFromUpdate( @@ -6564,8 +6643,8 @@ function getStateFromUpdate( } case CaptureUpdate: { - workInProgress.effectTag = - (workInProgress.effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; } // Intentional fallthrough @@ -6606,161 +6685,163 @@ function getStateFromUpdate( return prevState; } -function processUpdateQueue( - workInProgress, - props, - instance, - renderExpirationTime -) { +function processUpdateQueue(workInProgress, props, instance, renderLanes) { // This is always non-null on a ClassComponent or HostRoot var queue = workInProgress.updateQueue; hasForceUpdate = false; { currentlyProcessingQueue = queue.shared; - } // The last rebase update that is NOT part of the base state. + } - var baseQueue = queue.baseQueue; // The last pending update that hasn't been processed yet. + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. var pendingQueue = queue.shared.pending; if (pendingQueue !== null) { - // We have new updates that haven't been processed yet. - // We'll add them to the base queue. - if (baseQueue !== null) { - // Merge the pending queue and the base queue. - var baseFirst = baseQueue.next; - var pendingFirst = pendingQueue.next; - baseQueue.next = pendingFirst; - pendingQueue.next = baseFirst; + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. + + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - baseQueue = pendingQueue; - queue.shared.pending = null; // TODO: Pass `current` as argument + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument var current = workInProgress.alternate; if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; + + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } - if (currentQueue !== null) { - currentQueue.baseQueue = pendingQueue; + currentQueue.lastBaseUpdate = lastPendingUpdate; } } } // These values may change as we process the queue. - if (baseQueue !== null) { - var first = baseQueue.next; // Iterate through the list of updates to compute the result. + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. - var newState = queue.baseState; - var newExpirationTime = NoWork; + var newLanes = NoLanes; var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; + + do { + var updateLane = update.lane; + var updateEventTime = update.eventTime; - if (first !== null) { - var update = first; + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + eventTime: updateEventTime, + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - do { - var updateExpirationTime = update.expirationTime; + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if (updateExpirationTime < renderExpirationTime) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + eventTime: updateEventTime, + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, tag: update.tag, payload: update.payload, callback: update.callback, next: null }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = clone; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = clone; - } // Update the remaining priority in the queue. - - if (updateExpirationTime > newExpirationTime) { - newExpirationTime = updateExpirationTime; - } - } else { - // This update does have sufficient priority. - if (newBaseQueueLast !== null) { - var _clone = { - expirationTime: Sync, - // This update is going to be committed so we never want uncommit it. - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reverseable value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ); // Process this update. - - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - if (callback !== null) { - workInProgress.effectTag |= Callback; - var effects = queue.effects; + if (callback !== null) { + workInProgress.flags |= Callback; + var effects = queue.effects; - if (effects === null) { - queue.effects = [update]; - } else { - effects.push(update); - } + if (effects === null) { + queue.effects = [update]; + } else { + effects.push(update); } } + } - update = update.next; + update = update.next; - if (update === null || update === first) { - pendingQueue = queue.shared.pending; + if (update === null) { + pendingQueue = queue.shared.pending; - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - update = baseQueue.next = pendingQueue.next; - pendingQueue.next = first; - queue.baseQueue = baseQueue = pendingQueue; - queue.shared.pending = null; - } + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. + + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; } - } while (true); - } + } + } while (true); - if (newBaseQueueLast === null) { + if (newLastBaseUpdate === null) { newBaseState = newState; - } else { - newBaseQueueLast.next = newBaseQueueFirst; } queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; // Set the remaining expiration time to be whatever is remaining in the queue. + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; // Set the remaining expiration time to be whatever is remaining in the queue. // This should be fine because the only two other things that contribute to // expiration time are props and context. We're already in the middle of the // begin phase by the time we start processing the queue, so we've already @@ -6768,8 +6849,8 @@ function processUpdateQueue( // shouldComponentUpdate is tricky; but we'll have to account for // that regardless. - markUnprocessedUpdateTime(newExpirationTime); - workInProgress.expirationTime = newExpirationTime; + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; workInProgress.memoizedState = newState; } @@ -6813,11 +6894,6 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -function requestCurrentSuspenseConfig() { - return ReactCurrentBatchConfig.suspense; -} - var fakeInternalInstance = {}; var isArray = Array.isArray; // React.Component uses a shared frozen object by default. // We'll use it to determine whether we need to initialize legacy refs. @@ -6918,7 +6994,7 @@ function applyDerivedStateFromProps( workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the // base state. - if (workInProgress.expirationTime === NoWork) { + if (workInProgress.lanes === NoLanes) { // Queue is always non-null for classes var updateQueue = workInProgress.updateQueue; updateQueue.baseState = memoizedState; @@ -6928,14 +7004,9 @@ var classComponentUpdater = { isMounted: isMounted, enqueueSetState: function(inst, payload, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.payload = payload; if (callback !== undefined && callback !== null) { @@ -6947,18 +7018,13 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ReplaceState; update.payload = payload; @@ -6971,18 +7037,13 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ForceUpdate; if (callback !== undefined && callback !== null) { @@ -6994,7 +7055,7 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } }; @@ -7010,13 +7071,11 @@ function checkShouldComponentUpdate( var instance = workInProgress.stateNode; if (typeof instance.shouldComponentUpdate === "function") { - startPhaseTimer(workInProgress, "shouldComponentUpdate"); var shouldUpdate = instance.shouldComponentUpdate( newProps, newState, nextContext ); - stopPhaseTimer(); { if (shouldUpdate === undefined) { @@ -7419,7 +7478,7 @@ function constructClassInstance(workInProgress, ctor, props) { "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + "The above lifecycles should be removed. Learn more about this warning here:\n" + - "https://fb.me/react-unsafe-component-lifecycles", + "https://reactjs.org/link/unsafe-component-lifecycles", _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : "", @@ -7442,7 +7501,6 @@ function constructClassInstance(workInProgress, ctor, props) { } function callComponentWillMount(workInProgress, instance) { - startPhaseTimer(workInProgress, "componentWillMount"); var oldState = instance.state; if (typeof instance.componentWillMount === "function") { @@ -7453,8 +7511,6 @@ function callComponentWillMount(workInProgress, instance) { instance.UNSAFE_componentWillMount(); } - stopPhaseTimer(); - if (oldState !== instance.state) { { error( @@ -7476,7 +7532,6 @@ function callComponentWillReceiveProps( nextContext ) { var oldState = instance.state; - startPhaseTimer(workInProgress, "componentWillReceiveProps"); if (typeof instance.componentWillReceiveProps === "function") { instance.componentWillReceiveProps(newProps, nextContext); @@ -7486,8 +7541,6 @@ function callComponentWillReceiveProps( instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); } - stopPhaseTimer(); - if (instance.state !== oldState) { { var componentName = getComponentName(workInProgress.type) || "Component"; @@ -7508,12 +7561,7 @@ function callComponentWillReceiveProps( } } // Invokes the mount life-cycles on a previously never rendered instance. -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { { checkClassInstance(workInProgress, ctor, newProps); } @@ -7563,7 +7611,7 @@ function mountClassInstance( } } - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; var getDerivedStateFromProps = ctor.getDerivedStateFromProps; @@ -7587,26 +7635,16 @@ function mountClassInstance( callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's // process them now. - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } -} - -function resumeMountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +} + +function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; var oldProps = workInProgress.memoizedProps; instance.props = oldProps; @@ -7652,7 +7690,7 @@ function resumeMountClassInstance( resetHasForceUpdateBeforeProcessing(); var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); newState = workInProgress.memoizedState; if ( @@ -7664,7 +7702,7 @@ function resumeMountClassInstance( // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } return false; @@ -7700,8 +7738,6 @@ function resumeMountClassInstance( (typeof instance.UNSAFE_componentWillMount === "function" || typeof instance.componentWillMount === "function") ) { - startPhaseTimer(workInProgress, "componentWillMount"); - if (typeof instance.componentWillMount === "function") { instance.componentWillMount(); } @@ -7709,18 +7745,16 @@ function resumeMountClassInstance( if (typeof instance.UNSAFE_componentWillMount === "function") { instance.UNSAFE_componentWillMount(); } - - stopPhaseTimer(); } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // If shouldComponentUpdate returned false, we should still update the // memoized state to indicate that this work can be reused. @@ -7740,15 +7774,17 @@ function updateClassInstance( workInProgress, ctor, newProps, - renderExpirationTime + renderLanes ) { var instance = workInProgress.stateNode; cloneUpdateQueue(current, workInProgress); - var oldProps = workInProgress.memoizedProps; - instance.props = + var unresolvedOldProps = workInProgress.memoizedProps; + var oldProps = workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps); + ? unresolvedOldProps + : resolveDefaultProps(workInProgress.type, unresolvedOldProps); + instance.props = oldProps; + var unresolvedNewProps = workInProgress.pendingProps; var oldContext = instance.context; var contextType = ctor.contextType; var nextContext = emptyContextObject; @@ -7774,7 +7810,10 @@ function updateClassInstance( (typeof instance.UNSAFE_componentWillReceiveProps === "function" || typeof instance.componentWillReceiveProps === "function") ) { - if (oldProps !== newProps || oldContext !== nextContext) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { callComponentWillReceiveProps( workInProgress, instance, @@ -7787,11 +7826,11 @@ function updateClassInstance( resetHasForceUpdateBeforeProcessing(); var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); newState = workInProgress.memoizedState; if ( - oldProps === newProps && + unresolvedOldProps === unresolvedNewProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing() @@ -7800,19 +7839,19 @@ function updateClassInstance( // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } if (typeof instance.getSnapshotBeforeUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -7849,8 +7888,6 @@ function updateClassInstance( (typeof instance.UNSAFE_componentWillUpdate === "function" || typeof instance.componentWillUpdate === "function") ) { - startPhaseTimer(workInProgress, "componentWillUpdate"); - if (typeof instance.componentWillUpdate === "function") { instance.componentWillUpdate(newProps, newState, nextContext); } @@ -7858,35 +7895,33 @@ function updateClassInstance( if (typeof instance.UNSAFE_componentWillUpdate === "function") { instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); } - - stopPhaseTimer(); } if (typeof instance.componentDidUpdate === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } if (typeof instance.getSnapshotBeforeUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -7908,7 +7943,7 @@ var didWarnAboutStringRefs; var ownerHasKeyUseWarning; var ownerHasFunctionTypeWarning; -var warnForMissingKey = function(child) {}; +var warnForMissingKey = function(child, returnFiber) {}; { didWarnAboutMaps = false; @@ -7923,7 +7958,7 @@ var warnForMissingKey = function(child) {}; ownerHasKeyUseWarning = {}; ownerHasFunctionTypeWarning = {}; - warnForMissingKey = function(child) { + warnForMissingKey = function(child, returnFiber) { if (child === null || typeof child !== "object") { return; } @@ -7939,21 +7974,17 @@ var warnForMissingKey = function(child) {}; } child._store.validated = true; - var currentComponentErrorInfo = - "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + - "more information." + - getCurrentFiberStackInDev(); + var componentName = getComponentName(returnFiber.type) || "Component"; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + if (ownerHasKeyUseWarning[componentName]) { return; } - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; + ownerHasKeyUseWarning[componentName] = true; error( "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + "more information." ); }; @@ -7991,9 +8022,8 @@ function coerceRef(returnFiber, current, element) { "String refs are a source of potential bugs and should be avoided. " + "We recommend using useRef() or createRef() instead. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-string-ref%s", - mixedRef, - getStackByFiberInDevAndProd(returnFiber) + "https://reactjs.org/link/strict-mode-string-ref", + mixedRef ); } @@ -8011,7 +8041,7 @@ function coerceRef(returnFiber, current, element) { if (!(ownerFiber.tag === ClassComponent)) { throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); } @@ -8065,7 +8095,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + mixedRef + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } } @@ -8076,41 +8106,27 @@ function coerceRef(returnFiber, current, element) { function throwOnInvalidObjectType(returnFiber, newChild) { if (returnFiber.type !== "textarea") { - var addendum = ""; - - { - addendum = - " If you meant to render a collection of children, use an array " + - "instead." + - getCurrentFiberStackInDev(); - } - { throw Error( "Objects are not valid as a React child (found: " + (Object.prototype.toString.call(newChild) === "[object Object]" ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + - addendum + "). If you meant to render a collection of children, use an array instead." ); } } } -function warnOnFunctionType() { +function warnOnFunctionType(returnFiber) { { - var currentComponentErrorInfo = - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." + - getCurrentFiberStackInDev(); + var componentName = getComponentName(returnFiber.type) || "Component"; - if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) { + if (ownerHasFunctionTypeWarning[componentName]) { return; } - ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true; + ownerHasFunctionTypeWarning[componentName] = true; error( "Functions are not valid as a React child. This may happen if " + @@ -8144,7 +8160,7 @@ function ChildReconciler(shouldTrackSideEffects) { } childToDelete.nextEffect = null; - childToDelete.effectTag = Deletion; + childToDelete.flags = Deletion; } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -8208,7 +8224,7 @@ function ChildReconciler(shouldTrackSideEffects) { if (oldIndex < lastPlacedIndex) { // This is a move. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } else { // This item can stay in place. @@ -8216,7 +8232,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } else { // This is an insertion. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } } @@ -8225,20 +8241,16 @@ function ChildReconciler(shouldTrackSideEffects) { // This is simpler for the single child case. We only need to do a // placement for inserting new children. if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.effectTag = Placement; + newFiber.flags = Placement; } return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (current === null || current.tag !== HostText) { // Insert - var created = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); created.return = returnFiber; return created; } else { @@ -8249,7 +8261,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (current !== null) { if ( current.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -8269,17 +8281,13 @@ function ChildReconciler(shouldTrackSideEffects) { } } // Insert - var created = createFiberFromElement( - element, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromElement(element, returnFiber.mode, lanes); created.ref = coerceRef(returnFiber, current, element); created.return = returnFiber; return created; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( current === null || current.tag !== HostPortal || @@ -8287,11 +8295,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) { // Insert - var created = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); created.return = returnFiber; return created; } else { @@ -8302,13 +8306,13 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (current === null || current.tag !== Fragment) { // Insert var created = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key ); created.return = returnFiber; @@ -8321,16 +8325,12 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if (typeof newChild === "string" || typeof newChild === "number") { // Text nodes don't have keys. If the previous node is implicitly keyed // we can continue to replace it without aborting even if it is not a text // node. - var created = createFiberFromText( - "" + newChild, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText("" + newChild, returnFiber.mode, lanes); created.return = returnFiber; return created; } @@ -8341,7 +8341,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created = createFiberFromElement( newChild, returnFiber.mode, - expirationTime + lanes ); _created.ref = coerceRef(returnFiber, null, newChild); @@ -8353,7 +8353,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created2 = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); _created2.return = returnFiber; @@ -8365,7 +8365,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created3 = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null ); @@ -8378,14 +8378,14 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { // Update the fiber if the keys match, otherwise return null. var key = oldFiber !== null ? oldFiber.key : null; @@ -8397,12 +8397,7 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } - return updateTextNode( - returnFiber, - oldFiber, - "" + newChild, - expirationTime - ); + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } if (typeof newChild === "object" && newChild !== null) { @@ -8414,17 +8409,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ); } - return updateElement( - returnFiber, - oldFiber, - newChild, - expirationTime - ); + return updateElement(returnFiber, oldFiber, newChild, lanes); } else { return null; } @@ -8432,12 +8422,7 @@ function ChildReconciler(shouldTrackSideEffects) { case REACT_PORTAL_TYPE: { if (newChild.key === key) { - return updatePortal( - returnFiber, - oldFiber, - newChild, - expirationTime - ); + return updatePortal(returnFiber, oldFiber, newChild, lanes); } else { return null; } @@ -8449,13 +8434,7 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } - return updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); } throwOnInvalidObjectType(returnFiber, newChild); @@ -8463,7 +8442,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -8475,18 +8454,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if (typeof newChild === "string" || typeof newChild === "number") { // Text nodes don't have keys, so we neither have to check the old nor // new node for the key. If both are text nodes, they match. var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode( - returnFiber, - matchedFiber, - "" + newChild, - expirationTime - ); + return updateTextNode(returnFiber, matchedFiber, "" + newChild, lanes); } if (typeof newChild === "object" && newChild !== null) { @@ -8502,17 +8476,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, _matchedFiber, newChild.props.children, - expirationTime, + lanes, newChild.key ); } - return updateElement( - returnFiber, - _matchedFiber, - newChild, - expirationTime - ); + return updateElement(returnFiber, _matchedFiber, newChild, lanes); } case REACT_PORTAL_TYPE: { @@ -8521,12 +8490,7 @@ function ChildReconciler(shouldTrackSideEffects) { newChild.key === null ? newIdx : newChild.key ) || null; - return updatePortal( - returnFiber, - _matchedFiber2, - newChild, - expirationTime - ); + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } } @@ -8537,7 +8501,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, _matchedFiber3, newChild, - expirationTime, + lanes, null ); } @@ -8547,7 +8511,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -8557,7 +8521,7 @@ function ChildReconciler(shouldTrackSideEffects) { * Warns if there is a duplicate or missing key */ - function warnOnInvalidKey(child, knownKeys) { + function warnOnInvalidKey(child, knownKeys, returnFiber) { { if (typeof child !== "object" || child === null) { return knownKeys; @@ -8566,7 +8530,7 @@ function ChildReconciler(shouldTrackSideEffects) { switch (child.$$typeof) { case REACT_ELEMENT_TYPE: case REACT_PORTAL_TYPE: - warnForMissingKey(child); + warnForMissingKey(child, returnFiber); var key = child.key; if (typeof key !== "string") { @@ -8604,7 +8568,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { // This algorithm can't optimize by searching from both ends since we // don't have backpointers on fibers. I'm trying to see how far we can get @@ -8627,7 +8591,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (var i = 0; i < newChildren.length; i++) { var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys); + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } } @@ -8650,7 +8614,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (newFiber === null) { @@ -8700,11 +8664,7 @@ function ChildReconciler(shouldTrackSideEffects) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - ); + var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); if (_newFiber === null) { continue; @@ -8733,7 +8693,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes ); if (_newFiber2 !== null) { @@ -8776,7 +8736,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { // This is the same implementation as reconcileChildrenArray(), // but using the iterator instead. @@ -8811,9 +8771,8 @@ function ChildReconciler(shouldTrackSideEffects) { if (newChildrenIterable.entries === iteratorFn) { if (!didWarnAboutMaps) { error( - "Using Maps as children is unsupported and will likely yield " + - "unexpected results. Convert it to a sequence/iterable of keyed " + - "ReactElements instead." + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." ); } @@ -8830,7 +8789,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (; !_step.done; _step = _newChildren.next()) { var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys); + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } } } @@ -8861,12 +8820,7 @@ function ChildReconciler(shouldTrackSideEffects) { nextOldFiber = oldFiber.sibling; } - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (newFiber === null) { // TODO: This breaks on empty slots like null children. That's @@ -8915,7 +8869,7 @@ function ChildReconciler(shouldTrackSideEffects) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, expirationTime); + var _newFiber3 = createChild(returnFiber, step.value, lanes); if (_newFiber3 === null) { continue; @@ -8944,7 +8898,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, step.value, - expirationTime + lanes ); if (_newFiber4 !== null) { @@ -8987,7 +8941,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, textContent, - expirationTime + lanes ) { // There's no need to check for keys on text nodes since we don't have a // way to define them. @@ -9002,11 +8956,7 @@ function ChildReconciler(shouldTrackSideEffects) { // and delete the existing ones. deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); created.return = returnFiber; return created; } @@ -9015,7 +8965,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, element, - expirationTime + lanes ) { var key = element.key; var child = currentFirstChild; @@ -9042,11 +8992,6 @@ function ChildReconciler(shouldTrackSideEffects) { break; } - case Block: - - // We intentionally fallthrough here if enableBlocksAPI is not on. - // eslint-disable-next-lined no-fallthrough - default: { if ( child.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -9054,17 +8999,17 @@ function ChildReconciler(shouldTrackSideEffects) { ) { deleteRemainingChildren(returnFiber, child.sibling); - var _existing3 = useFiber(child, element.props); + var _existing = useFiber(child, element.props); - _existing3.ref = coerceRef(returnFiber, child, element); - _existing3.return = returnFiber; + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; { - _existing3._debugSource = element._source; - _existing3._debugOwner = element._owner; + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; } - return _existing3; + return _existing; } break; @@ -9084,17 +9029,13 @@ function ChildReconciler(shouldTrackSideEffects) { var created = createFiberFromFragment( element.props.children, returnFiber.mode, - expirationTime, + lanes, element.key ); created.return = returnFiber; return created; } else { - var _created4 = createFiberFromElement( - element, - returnFiber.mode, - expirationTime - ); + var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); _created4.ref = coerceRef(returnFiber, currentFirstChild, element); _created4.return = returnFiber; @@ -9106,7 +9047,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, portal, - expirationTime + lanes ) { var key = portal.key; var child = currentFirstChild; @@ -9135,11 +9076,7 @@ function ChildReconciler(shouldTrackSideEffects) { child = child.sibling; } - var created = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); created.return = returnFiber; return created; } // This API will tag the children with the side-effect of the reconciliation @@ -9150,7 +9087,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) { // This function is not recursive. // If the top level item is an array, we treat it as a set of children, @@ -9179,7 +9116,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) ); @@ -9189,7 +9126,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) ); } @@ -9201,7 +9138,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, "" + newChild, - expirationTime + lanes ) ); } @@ -9211,7 +9148,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); } @@ -9220,7 +9157,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); } @@ -9230,7 +9167,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -9253,12 +9190,12 @@ function ChildReconciler(shouldTrackSideEffects) { // functions and classes // eslint-disable-next-lined no-fallthrough - case FunctionComponent: { - var Component = returnFiber.type; - + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { { throw Error( - (Component.displayName || Component.name || "Component") + + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." ); } @@ -9300,11 +9237,11 @@ function cloneChildFibers(current, workInProgress) { newChild.sibling = null; } // Reset a workInProgress child set to prepare it for a second pass. -function resetChildFibers(workInProgress, renderExpirationTime) { +function resetChildFibers(workInProgress, lanes) { var child = workInProgress.child; while (child !== null) { - resetWorkInProgress(child, renderExpirationTime); + resetWorkInProgress(child, lanes); child = child.sibling; } } @@ -9476,7 +9413,7 @@ function findFirstSuspended(row) { // keep track of whether it suspended or not. node.memoizedProps.revealOrder !== undefined ) { - var didSuspend = (node.effectTag & DidCapture) !== NoEffect; + var didSuspend = (node.flags & DidCapture) !== NoFlags; if (didSuspend) { return node; @@ -9506,18 +9443,9 @@ function findFirstSuspended(row) { return null; } -function createDeprecatedResponderListener(responder, props) { - var eventResponderListener = { - responder: responder, - props: props - }; - - { - Object.freeze(eventResponderListener); - } - - return eventResponderListener; -} +var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. var HasEffect = /* */ @@ -9530,16 +9458,113 @@ var Passive$1 = /* */ 4; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var isHydrating = false; + +function enterHydrationState(fiber) { + { + return false; + } +} + +function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext +) { + { + { + throw Error( + "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + } +} + +function prepareToHydrateHostTextInstance(fiber) { + { + { + throw Error( + "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + } + var shouldUpdate = hydrateTextInstance(); +} + +function popHydrationState(fiber) { + { + return false; + } +} + +function getIsHydrating() { + return isHydrating; +} + +// and should be reset before starting a new render. +// This tracks which mutable sources need to be reset after a render. + +var workInProgressSources = []; +var rendererSigil$1; + +{ + // Used to detect multiple renderers using the same mutable source. + rendererSigil$1 = {}; +} + +function markSourceAsDirty(mutableSource) { + workInProgressSources.push(mutableSource); +} +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) { + var mutableSource = workInProgressSources[i]; + + { + mutableSource._workInProgressVersionSecondary = null; + } + } + + workInProgressSources.length = 0; +} +function getWorkInProgressVersion(mutableSource) { + { + return mutableSource._workInProgressVersionSecondary; + } +} +function setWorkInProgressVersion(mutableSource, version) { + { + mutableSource._workInProgressVersionSecondary = version; + } + + workInProgressSources.push(mutableSource); +} +function warnAboutMultipleRenderersDEV(mutableSource) { + { + { + if (mutableSource._currentSecondaryRenderer == null) { + mutableSource._currentSecondaryRenderer = rendererSigil$1; + } else if (mutableSource._currentSecondaryRenderer !== rendererSigil$1) { + error( + "Detected multiple renderers concurrently rendering the " + + "same mutable source. This is currently unsupported." + ); + } + } + } +} // Eager reads the version of a mutable source and stores it on the root. + +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; +var didWarnAboutUseOpaqueIdentifier; { + didWarnAboutUseOpaqueIdentifier = {}; didWarnAboutMismatchedHooksForComponent = new Set(); } // These are set right before calling the component. -var renderExpirationTime = NoWork; // The work-in-progress fiber. I've named it differently to distinguish it from +var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from // the work-in-progress hook. var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The @@ -9553,7 +9578,12 @@ var workInProgressHook = null; // Whether an update was scheduled at any point d // finished evaluating this component. This is an optimization so we know // whether we need to clear render phase updates after a throw. -var didScheduleRenderPhaseUpdate = false; +var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This +// gets reset after each attempt. +// TODO: Maybe there's some way to consolidate this with +// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. + +var didScheduleRenderPhaseUpdateDuringThisPass = false; var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. @@ -9637,7 +9667,7 @@ function warnOnHookMismatchInDev(currentHookName) { error( "React has detected a change in the order of Hooks called by %s. " + "This will lead to bugs and errors if not fixed. " + - "For more information, read the Rules of Hooks: https://fb.me/rules-of-hooks\n\n" + + "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + " Previous render Next render\n" + " ------------------------------------------------------\n" + "%s" + @@ -9653,7 +9683,7 @@ function warnOnHookMismatchInDev(currentHookName) { function throwInvalidHookError() { { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } } @@ -9712,9 +9742,9 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; { @@ -9727,7 +9757,7 @@ function renderWithHooks( workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = NoWork; // The following should have already been reset + workInProgress.lanes = NoLanes; // The following should have already been reset // currentHook = null; // workInProgressHook = null; // didScheduleRenderPhaseUpdate = false; @@ -9740,28 +9770,28 @@ function renderWithHooks( { if (current !== null && current.memoizedState !== null) { - ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; } else if (hookTypesDev !== null) { // This dispatcher handles an edge case where a component is updating, // but no stateful hooks have been used. // We want to match the production code behavior (which will use HooksDispatcherOnMount), // but with the extra DEV validation to ensure hooks ordering hasn't changed. // This dispatcher does that. - ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountWithHookTypesInDEV; } else { - ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; } } var children = Component(props, secondArg); // Check if there was a render phase update - if (workInProgress.expirationTime === renderExpirationTime) { + if (didScheduleRenderPhaseUpdateDuringThisPass) { // Keep rendering in a loop for as long as render phase updates continue to // be scheduled. Use a counter to prevent infinite loops. var numberOfReRenders = 0; do { - workInProgress.expirationTime = NoWork; + didScheduleRenderPhaseUpdateDuringThisPass = false; if (!(numberOfReRenders < RE_RENDER_LIMIT)) { throw Error( @@ -9786,13 +9816,13 @@ function renderWithHooks( hookTypesUpdateIndexDev = -1; } - ReactCurrentDispatcher.current = HooksDispatcherOnRerenderInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; children = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrancy. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; { workInProgress._debugHookTypes = hookTypesDev; @@ -9800,7 +9830,7 @@ function renderWithHooks( // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderExpirationTime = NoWork; + renderLanes = NoLanes; currentlyRenderingFiber$1 = null; currentHook = null; workInProgressHook = null; @@ -9821,18 +9851,15 @@ function renderWithHooks( return children; } -function bailoutHooks(current, workInProgress, expirationTime) { +function bailoutHooks(current, workInProgress, lanes) { workInProgress.updateQueue = current.updateQueue; - workInProgress.effectTag &= ~(Passive | Update); - - if (current.expirationTime <= expirationTime) { - current.expirationTime = NoWork; - } + workInProgress.flags &= ~(Passive | Update); + current.lanes = removeLanes(current.lanes, lanes); } function resetHooksAfterThrow() { // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrancy. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; if (didScheduleRenderPhaseUpdate) { // There were render phase updates. These are only valid for this render @@ -9854,9 +9881,11 @@ function resetHooksAfterThrow() { hook = hook.next; } + + didScheduleRenderPhaseUpdate = false; } - renderExpirationTime = NoWork; + renderLanes = NoLanes; currentlyRenderingFiber$1 = null; currentHook = null; workInProgressHook = null; @@ -9865,9 +9894,10 @@ function resetHooksAfterThrow() { hookTypesDev = null; hookTypesUpdateIndexDev = -1; currentHookNameInDev = null; + isUpdatingOpaqueValueInRenderPhase = false; } - didScheduleRenderPhaseUpdate = false; + didScheduleRenderPhaseUpdateDuringThisPass = false; } function mountWorkInProgressHook() { @@ -10014,6 +10044,17 @@ function updateReducer(reducer, initialArg, init) { pendingQueue.next = baseFirst; } + { + if (current.baseQueue !== baseQueue) { + // Internal invariant that should never happen, but feasibly could in + // the future if we implement resuming, or some form of that. + error( + "Internal error: Expected work-in-progress queue to be a clone. " + + "This is a bug in React." + ); + } + } + current.baseQueue = baseQueue = pendingQueue; queue.pending = null; } @@ -10028,15 +10069,14 @@ function updateReducer(reducer, initialArg, init) { var update = first; do { - var updateExpirationTime = update.expirationTime; + var updateLane = update.lane; - if (updateExpirationTime < renderExpirationTime) { + if (!isSubsetOfLanes(renderLanes, updateLane)) { // Priority is insufficient. Skip this update. If this is the first // skipped update, the previous update/state is the new base // update/state. var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, + lane: updateLane, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, @@ -10049,35 +10089,29 @@ function updateReducer(reducer, initialArg, init) { } else { newBaseQueueLast = newBaseQueueLast.next = clone; } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. - if (updateExpirationTime > currentlyRenderingFiber$1.expirationTime) { - currentlyRenderingFiber$1.expirationTime = updateExpirationTime; - markUnprocessedUpdateTime(updateExpirationTime); - } + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + updateLane + ); + markSkippedUpdateLanes(updateLane); } else { // This update does have sufficient priority. if (newBaseQueueLast !== null) { var _clone = { - expirationTime: Sync, - // This update is going to be committed so we never want uncommit it. - suspenseConfig: update.suspenseConfig, + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }; newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reverseable value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ); // Process this update. + } // Process this update. if (update.eagerReducer === reducer) { // If this update was processed eagerly, and its reducer matches the @@ -10165,6 +10199,251 @@ function rerenderReducer(reducer, initialArg, init) { return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + { + warnAboutMultipleRenderersDEV(source); + } + + var getVersion = source._getVersion; + var version = getVersion(source._source); // Is it safe for this component to read from this source during the current render? + + var isSafeToReadFromSource = false; // Check the version first. + // If this render has already been started with a specific version, + // we can use it alone to determine if we can safely read from the source. + + var currentRenderVersion = getWorkInProgressVersion(source); + + if (currentRenderVersion !== null) { + // It's safe to read if the store hasn't been mutated since the last time + // we read something. + isSafeToReadFromSource = currentRenderVersion === version; + } else { + // If there's no version, then this is the first time we've read from the + // source during the current render pass, so we need to do a bit more work. + // What we need to determine is if there are any hooks that already + // subscribed to the source, and if so, whether there are any pending + // mutations that haven't been synchronized yet. + // + // If there are no pending mutations, then `root.mutableReadLanes` will be + // empty, and we know we can safely read. + // + // If there *are* pending mutations, we may still be able to safely read + // if the currently rendering lanes are inclusive of the pending mutation + // lanes, since that guarantees that the value we're about to read from + // the source is consistent with the values that we read during the most + // recent mutation. + isSafeToReadFromSource = isSubsetOfLanes( + renderLanes, + root.mutableReadLanes + ); + + if (isSafeToReadFromSource) { + // If it's safe to read from this source during the current render, + // store the version in case other components read from it. + // A changed version number will let those components know to throw and restart the render. + setWorkInProgressVersion(source, version); + } + } + + if (isSafeToReadFromSource) { + var snapshot = getSnapshot(source._source); + + { + if (typeof snapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } + } + + return snapshot; + } else { + // This handles the special case of a mutable source being shared between renderers. + // In that case, if the source is mutated between the first and second renderer, + // The second renderer don't know that it needs to reset the WIP version during unwind, + // (because the hook only marks sources as dirty if it's written to their WIP version). + // That would cause this tear check to throw again and eventually be visible to the user. + // We can avoid this infinite loop by explicitly marking the source as dirty. + // + // This can lead to tearing in the first renderer when it resumes, + // but there's nothing we can do about that (short of throwing here and refusing to continue the render). + markSourceAsDirty(source); + + { + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); + } + } +} + +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = getWorkInProgressRoot(); + + if (!(root !== null)) { + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + var getVersion = source._getVersion; + var version = getVersion(source._source); + var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const + + var _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + currentSnapshot = _dispatcher$useState[0], + setSnapshot = _dispatcher$useState[1]; + + var snapshot = currentSnapshot; // Grab a handle to the state hook as well. + // We use it to clear the pending update queue if we have a new source. + + var stateHook = workInProgressHook; + var memoizedState = hook.memoizedState; + var refs = memoizedState.refs; + var prevGetSnapshot = refs.getSnapshot; + var prevSource = memoizedState.source; + var prevSubscribe = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { + refs: refs, + source: source, + subscribe: subscribe + }; // Sync the values needed by our subscription handler after each commit. + + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; // Normally the dispatch function for a state hook never changes, + // but this hook recreates the queue in certain cases to avoid updates from stale sources. + // handleChange() below needs to reference the dispatch function without re-subscribing, + // so we use a ref to ensure that it always has the latest version. + + refs.setSnapshot = setSnapshot; // Check for a possible change between when we last rendered now. + + var maybeNewVersion = getVersion(source._source); + + if (!objectIs(version, maybeNewVersion)) { + var maybeNewSnapshot = getSnapshot(source._source); + + { + if (typeof maybeNewSnapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } + } + + if (!objectIs(snapshot, maybeNewSnapshot)) { + setSnapshot(maybeNewSnapshot); + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } // If the source mutated between render and now, + // there may be state updates already scheduled from the old source. + // Entangle the updates so that they render in the same batch. + + markRootEntangled(root, root.mutableReadLanes); + } + }, + [getSnapshot, source, subscribe] + ); // If we got a new source or subscribe function, re-subscribe in a passive effect. + + dispatcher.useEffect( + function() { + var handleChange = function() { + var latestGetSnapshot = refs.getSnapshot; + var latestSetSnapshot = refs.setSnapshot; + + try { + latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. + + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } catch (error) { + // A selector might throw after a source mutation. + // e.g. it might try to read from a part of the store that no longer exists. + // In this case we should still schedule an update with React. + // Worst case the selector will throw again and then an error boundary will handle it. + latestSetSnapshot(function() { + throw error; + }); + } + }; + + var unsubscribe = subscribe(source._source, handleChange); + + { + if (typeof unsubscribe !== "function") { + error( + "Mutable source subscribe function must return an unsubscribe function." + ); + } + } + + return unsubscribe; + }, + [source, subscribe] + ); // If any of the inputs to useMutableSource change, reading is potentially unsafe. + // + // If either the source or the subscription have changed we can't can't trust the update queue. + // Maybe the source changed in a way that the old subscription ignored but the new one depends on. + // + // If the getSnapshot function changed, we also shouldn't rely on the update queue. + // It's possible that the underlying source was mutated between the when the last "change" event fired, + // and when the current render (with the new getSnapshot function) is processed. + // + // In both cases, we need to throw away pending updates (since they are no longer relevant) + // and treat reading from the source as we do in the mount case. + + if ( + !objectIs(prevGetSnapshot, getSnapshot) || + !objectIs(prevSource, source) || + !objectIs(prevSubscribe, subscribe) + ) { + // Create a new queue and setState method, + // So if there are interleaved updates, they get pushed to the older queue. + // When this becomes current, the previous queue and dispatch method will be discarded, + // including any interleaving updates that occur. + var newQueue = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }; + newQueue.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + newQueue + ); + stateHook.queue = newQueue; + stateHook.baseQueue = null; + snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot); + stateHook.memoizedState = stateHook.baseState = snapshot; + } + + return snapshot; +} + +function mountMutableSource(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { + getSnapshot: getSnapshot, + setSnapshot: null + }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); +} + +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} + function mountState(initialState) { var hook = mountWorkInProgressHook(); @@ -10229,16 +10508,14 @@ function pushEffect(tag, create, destroy, deps) { function mountRef(initialValue) { var hook = mountWorkInProgressHook(); - var ref = { - current: initialValue - }; { - Object.seal(ref); + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } - - hook.memoizedState = ref; - return ref; } function updateRef(initialValue) { @@ -10246,19 +10523,19 @@ function updateRef(initialValue) { return hook.memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, undefined, nextDeps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; var destroy = undefined; @@ -10271,15 +10548,15 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { - pushEffect(hookEffectTag, create, destroy, nextDeps); + pushEffect(hookFlags, create, destroy, nextDeps); return; } } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, destroy, nextDeps @@ -10439,129 +10716,175 @@ function updateMemo(nextCreate, deps) { return nextValue; } -function mountDeferredValue(value, config) { +function mountDeferredValue(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function updateDeferredValue(value, config) { +function updateDeferredValue(value) { var _updateState = updateState(), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function rerenderDeferredValue(value, config) { +function rerenderDeferredValue(value) { var _rerenderState = rerenderState(), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); - runWithPriority( - priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel, - function() { - setPending(true); - } - ); - runWithPriority( - priorityLevel > NormalPriority ? NormalPriority : priorityLevel, - function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + { + runWithPriority( + priorityLevel < UserBlockingPriority$1 + ? UserBlockingPriority$1 + : priorityLevel, + function() { + setPending(true); + } + ); + runWithPriority( + priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, + function() { + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; + + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig$1.transition = prevTransition; + } } - } - ); + ); + } } -function mountTransition(config) { +function mountTransition() { var _mountState2 = mountState(false), isPending = _mountState2[0], - setPending = _mountState2[1]; + setPending = _mountState2[1]; // The `start` method never changes. - var start = mountCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; return [start, isPending]; } -function updateTransition(config) { +function updateTransition() { var _updateState2 = updateState(), - isPending = _updateState2[0], - setPending = _updateState2[1]; + isPending = _updateState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } -function rerenderTransition(config) { +function rerenderTransition() { var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0], - setPending = _rerenderState2[1]; + isPending = _rerenderState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } +var isUpdatingOpaqueValueInRenderPhase = false; +function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { + { + return isUpdatingOpaqueValueInRenderPhase; + } +} + +function warnOnOpaqueIdentifierAccessInDEV(fiber) { + { + // TODO: Should warn in effects and callbacks, too + var name = getComponentName(fiber.type) || "Unknown"; + + if (getIsRendering() && !didWarnAboutUseOpaqueIdentifier[name]) { + error( + "The object passed back from useOpaqueIdentifier is meant to be " + + "passed through to attributes only. Do not read the " + + "value directly." + ); + + didWarnAboutUseOpaqueIdentifier[name] = true; + } + } +} + +function mountOpaqueIdentifier() { + var makeId = makeClientIdInDEV.bind( + null, + warnOnOpaqueIdentifierAccessInDEV.bind(null, currentlyRenderingFiber$1) + ); + + { + var _id = makeId(); + + mountState(_id); + return _id; + } +} + +function updateOpaqueIdentifier() { + var id = updateState()[0]; + return id; +} + +function rerenderOpaqueIdentifier() { + var id = rerenderState()[0]; + return id; +} + function dispatchAction(fiber, queue, action) { { if (typeof arguments[3] === "function") { @@ -10573,25 +10896,15 @@ function dispatchAction(fiber, queue, action) { } } - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); var update = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, + lane: lane, action: action, eagerReducer: null, eagerState: null, next: null - }; - - { - update.priority = getCurrentPriorityLevel(); - } // Append the update to the end of the list. + }; // Append the update to the end of the list. var pending = queue.pending; @@ -10613,13 +10926,11 @@ function dispatchAction(fiber, queue, action) { // This is a render phase update. Stash it in a lazily-created map of // queue -> linked list of updates. After this render pass, we'll restart // and apply the stashed updates on top of the work-in-progress hook. - didScheduleRenderPhaseUpdate = true; - update.expirationTime = renderExpirationTime; - currentlyRenderingFiber$1.expirationTime = renderExpirationTime; + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; } else { if ( - fiber.expirationTime === NoWork && - (alternate === null || alternate.expirationTime === NoWork) + fiber.lanes === NoLanes && + (alternate === null || alternate.lanes === NoLanes) ) { // The queue is currently empty, which means we can eagerly compute the // next state before entering the render phase. If the new state is the @@ -10630,8 +10941,8 @@ function dispatchAction(fiber, queue, action) { var prevDispatcher; { - prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; } try { @@ -10655,24 +10966,16 @@ function dispatchAction(fiber, queue, action) { // Suppress the error. It will throw again in the render phase. } finally { { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } } } } - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function mountEventListener(event) { - return undefined; -} - -function updateEventListener(event) { - return undefined; -} - var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -10685,10 +10988,11 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: enableNewReconciler }; var HooksDispatcherOnMountInDEV = null; var HooksDispatcherOnMountWithHookTypesInDEV = null; @@ -10713,7 +11017,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + "You can only call Hooks at the top level of your React function. " + "For more information, see " + - "https://fb.me/rules-of-hooks" + "https://reactjs.org/link/rules-of-hooks" ); }; @@ -10754,25 +11058,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; mountHookTypesDev(); checkDepsAreArrayDev(deps); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -10783,13 +11087,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -10797,26 +11101,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - mountHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; mountHookTypesDev(); - return mountEventListener(); - } + return mountMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + mountHookTypesDev(); + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnMountWithHookTypesInDEV = { readContext: function(context, observedBits) { @@ -10850,25 +11155,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -10879,13 +11184,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -10893,26 +11198,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return mountEventListener(); - } + return mountMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnUpdateInDEV = { readContext: function(context, observedBits) { @@ -10946,25 +11252,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -10975,13 +11281,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -10989,26 +11295,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return updateEventListener(); - } + return updateMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return updateOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnRerenderInDEV = { readContext: function(context, observedBits) { @@ -11042,25 +11349,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11071,13 +11378,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11085,26 +11392,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return updateEventListener(); - } + return updateMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return rerenderOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnMountInDEV = { readContext: function(context, observedBits) { @@ -11145,26 +11453,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11177,13 +11485,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11192,30 +11500,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); mountHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return mountDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountTransition(config); + return mountMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountEventListener(); - } + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnUpdateInDEV = { readContext: function(context, observedBits) { @@ -11256,26 +11565,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11288,13 +11597,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11303,30 +11612,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return updateDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateTransition(config); + return updateMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateEventListener(); - } + return updateOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnRerenderInDEV = { readContext: function(context, observedBits) { @@ -11367,26 +11677,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11399,13 +11709,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11414,30 +11724,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return rerenderDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderTransition(config); + return updateMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateEventListener(); - } + return rerenderOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; } @@ -11478,40 +11789,15 @@ function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { } } -function enterHydrationState(fiber) { - { - return false; - } -} - -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - { - throw Error( - "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." - ); - } - } -} - -function prepareToHydrateHostTextInstance(fiber) { - { - { - throw Error( - "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." - ); - } - } - var shouldUpdate = hydrateTextInstance(); -} +function transferActualDuration(fiber) { + // Transfer time spent rendering these children so we don't lose it + // after we rerender. This is used as a helper in special cases + // where we should count the work of multiple passes. + var child = fiber.child; -function popHydrationState(fiber) { - { - return false; + while (child) { + fiber.actualDuration += child.actualDuration; + child = child.sibling; } } @@ -11537,12 +11823,7 @@ var didWarnAboutTailOptions; didWarnAboutTailOptions = {}; } -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { if (current === null) { // If this is a fresh new component that hasn't been rendered yet, we // won't update its child set by applying minimal side-effects. Instead, @@ -11552,7 +11833,7 @@ function reconcileChildren( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } else { // If the current child is the same as the work in progress, it means that @@ -11564,7 +11845,7 @@ function reconcileChildren( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } } @@ -11573,7 +11854,7 @@ function forceUnmountCurrentAndReconcile( current, workInProgress, nextChildren, - renderExpirationTime + renderLanes ) { // This function is fork of reconcileChildren. It's used in cases where we // want to reconcile without matching against the existing set. This has the @@ -11587,7 +11868,7 @@ function forceUnmountCurrentAndReconcile( workInProgress, current.child, null, - renderExpirationTime + renderLanes ); // In the second pass, we mount the new children. The trick here is that we // pass null in place of where we usually pass the current child set. This has // the effect of remounting all children regardless of whether their @@ -11597,7 +11878,7 @@ function forceUnmountCurrentAndReconcile( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } @@ -11606,7 +11887,7 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { // TODO: current can be non-null here even if the component // hasn't yet mounted. This happens after the first render suspends. @@ -11632,7 +11913,7 @@ function updateForwardRef( var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent var nextChildren; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); { ReactCurrentOwner$1.current = workInProgress; @@ -11643,28 +11924,19 @@ function updateForwardRef( render, nextProps, ref, - renderExpirationTime + renderLanes ); setIsRendering(false); } if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderExpirationTime); - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -11673,8 +11945,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (current === null) { var type = Component.type; @@ -11704,8 +11976,8 @@ function updateMemoComponent( workInProgress, resolvedType, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -11728,9 +12000,9 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); child.ref = workInProgress.ref; child.return = workInProgress; @@ -11756,7 +12028,7 @@ function updateMemoComponent( var currentChild = current.child; // This is always exactly one child - if (updateExpirationTime < renderExpirationTime) { + if (!includesSomeLane(updateLanes, renderLanes)) { // This will be the props with resolved defaultProps, // unlike current.memoizedProps which will be the unresolved ones. var prevProps = currentChild.memoizedProps; // Default to shallow comparison @@ -11765,15 +12037,11 @@ function updateMemoComponent( compare = compare !== null ? compare : shallowEqual; if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; var newChild = createWorkInProgress(currentChild, nextProps); newChild.ref = workInProgress.ref; newChild.return = workInProgress; @@ -11786,8 +12054,8 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { // TODO: current can be non-null here even if the component // hasn't yet mounted. This happens when the inner render suspends. @@ -11802,19 +12070,27 @@ function updateSimpleMemoComponent( // We warn when you define propTypes on lazy() // so let's just skip over it to find memo() outer wrapper. // Inner props for memo are validated later. - outerMemoType = refineResolvedLazyComponent(outerMemoType); - } - - var outerPropTypes = outerMemoType && outerMemoType.propTypes; + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentName(outerMemoType) - ); - } // Inner propTypes will be validated in the function component path. + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. + + var outerPropTypes = outerMemoType && outerMemoType.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentName(outerMemoType) + ); + } + } } } @@ -11828,10 +12104,10 @@ function updateSimpleMemoComponent( ) { didReceiveUpdate = false; - if (updateExpirationTime < renderExpirationTime) { - // The pending update priority was cleared at the beginning of - // beginWork. We're about to bail out, but there might be additional - // updates at a lower priority. Usually, the priority level of the + if (!includesSomeLane(renderLanes, updateLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the // remaining updates is accumlated during the evaluation of the // component (i.e. when processing the update queue). But since since // we're bailing out early *without* evaluating the component, we need @@ -11842,12 +12118,16 @@ function updateSimpleMemoComponent( // contains hooks. // TODO: Move the reset at in beginWork out of the common path so that // this is no longer necessary. - workInProgress.expirationTime = current.expirationTime; + workInProgress.lanes = current.lanes; return bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; } } } @@ -11857,35 +12137,103 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } -function updateFragment(current, workInProgress, renderExpirationTime) { +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; + + if ( + nextProps.mode === "hidden" || + nextProps.mode === "unstable-defer-without-hiding" + ) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Figure out what we should do in Blocking mode. + var nextState = { + baseLanes: NoLanes + }; + workInProgress.memoizedState = nextState; + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var nextBaseLanes; + + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. + + { + markSpawnedWork(OffscreenLane); + } + + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes + }; + workInProgress.memoizedState = _nextState; // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. + + pushRenderLanes(workInProgress, nextBaseLanes); + return null; + } else { + // Rendering at offscreen, so we can clear the base lanes. + var _nextState2 = { + baseLanes: NoLanes + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + var _subtreeRenderLanes; + + if (prevState !== null) { + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); // Since we're not hidden anymore, reset the state + + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + _subtreeRenderLanes = renderLanes; + } + + pushRenderLanes(workInProgress, _subtreeRenderLanes); + } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} // Note: These happen to have identical begin phases, for now. We shouldn't hold +// ourselves to this constraint, though. If the behavior diverges, we should +// fork the function. + +var updateLegacyHiddenComponent = updateOffscreenComponent; + +function updateFragment(current, workInProgress, renderLanes) { var nextChildren = workInProgress.pendingProps; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function updateMode(current, workInProgress, renderExpirationTime) { +function updateMode(current, workInProgress, renderLanes) { var nextChildren = workInProgress.pendingProps.children; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function updateProfiler(current, workInProgress, renderExpirationTime) { +function updateProfiler(current, workInProgress, renderLanes) { { - workInProgress.effectTag |= Update; // Reset effect durations for the next eventual effect phase. + workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, var stateNode = workInProgress.stateNode; @@ -11895,12 +12243,7 @@ function updateProfiler(current, workInProgress, renderExpirationTime) { var nextProps = workInProgress.pendingProps; var nextChildren = nextProps.children; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -11912,7 +12255,7 @@ function markRef(current, workInProgress) { (current !== null && current.ref !== ref) ) { // Schedule a Ref effect - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } } @@ -11921,7 +12264,7 @@ function updateFunctionComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { { if (workInProgress.type !== workInProgress.elementType) { @@ -11948,7 +12291,7 @@ function updateFunctionComponent( } var nextChildren; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); { ReactCurrentOwner$1.current = workInProgress; @@ -11959,28 +12302,19 @@ function updateFunctionComponent( Component, nextProps, context, - renderExpirationTime + renderLanes ); setIsRendering(false); } if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderExpirationTime); - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -11989,7 +12323,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { { if (workInProgress.type !== workInProgress.elementType) { @@ -12019,7 +12353,7 @@ function updateClassComponent( hasContext = false; } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var instance = workInProgress.stateNode; var shouldUpdate; @@ -12032,16 +12366,11 @@ function updateClassComponent( current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // In the initial pass we might need to construct the instance. constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); shouldUpdate = true; } else if (current === null) { // In a resume, we'll already have an instance we can reuse. @@ -12049,7 +12378,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } else { shouldUpdate = updateClassInstance( @@ -12057,7 +12386,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } @@ -12067,13 +12396,13 @@ function updateClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ); { var inst = workInProgress.stateNode; - if (inst.props !== nextProps) { + if (shouldUpdate && inst.props !== nextProps) { if (!didWarnAboutReassigningProps) { error( "It looks like %s is reassigning its own `this.props` while rendering. " + @@ -12095,11 +12424,11 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { // Refs should update even if shouldComponentUpdate returns false markRef(current, workInProgress); - var didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; if (!shouldUpdate && !didCaptureError) { // Context providers should defer to sCU for rendering @@ -12107,11 +12436,7 @@ function finishClassComponent( invalidateContextProvider(workInProgress, Component, false); } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } var instance = workInProgress.stateNode; // Rerender @@ -12142,7 +12467,7 @@ function finishClassComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; if (current !== null && didCaptureError) { // If we're recovering from an error, reconcile without reusing any of @@ -12153,15 +12478,10 @@ function finishClassComponent( current, workInProgress, nextChildren, - renderExpirationTime + renderLanes ); } else { - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } // Memoize state using the values we just used to render. // TODO: Restructure so we never read values from the instance. @@ -12191,7 +12511,7 @@ function pushHostRootContext(workInProgress) { pushHostContainer(workInProgress, root.containerInfo); } -function updateHostRoot(current, workInProgress, renderExpirationTime) { +function updateHostRoot(current, workInProgress, renderLanes) { pushHostRootContext(workInProgress); var updateQueue = workInProgress.updateQueue; @@ -12205,32 +12525,24 @@ function updateHostRoot(current, workInProgress, renderExpirationTime) { var prevState = workInProgress.memoizedState; var prevChildren = prevState !== null ? prevState.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderExpirationTime); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); var nextState = workInProgress.memoizedState; // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } var root = workInProgress.stateNode; if (root.hydrate && enterHydrationState()) { - // If we don't have any current children this might be the first pass. - // We always try to hydrate. If this isn't a hydration pass there won't - // be any children to hydrate which is effectively the same thing as - // not hydrating. var child = mountChildFibers( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); workInProgress.child = child; var node = child; @@ -12242,24 +12554,19 @@ function updateHostRoot(current, workInProgress, renderExpirationTime) { // Conceptually this is similar to Placement in that a new subtree is // inserted into the React tree here. It just happens to not need DOM // mutations because it already exists. - node.effectTag = (node.effectTag & ~Placement) | Hydrating; + node.flags = (node.flags & ~Placement) | Hydrating; node = node.sibling; } } else { // Otherwise reset hydration state in case we aborted and resumed another // root. - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } return workInProgress.child; } -function updateHostComponent(current, workInProgress, renderExpirationTime) { +function updateHostComponent(current, workInProgress, renderLanes) { pushHostContext(workInProgress); var type = workInProgress.type; @@ -12270,30 +12577,11 @@ function updateHostComponent(current, workInProgress, renderExpirationTime) { if (prevProps !== null && shouldSetTextContent()) { // If we're switching from a direct text child to a normal child, or to // empty, we need to schedule the text content to be reset. - workInProgress.effectTag |= ContentReset; - } - - markRef(current, workInProgress); // Check the host config to see if the children are offscreen/hidden. - - if ( - workInProgress.mode & ConcurrentMode && - renderExpirationTime !== Never && - shouldDeprioritizeSubtree() - ) { - { - markSpawnedWork(Never); - } // Schedule this fiber to re-render at offscreen priority. Then bailout. - - workInProgress.expirationTime = workInProgress.childExpirationTime = Never; - return null; + workInProgress.flags |= ContentReset; } - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12307,8 +12595,8 @@ function mountLazyComponent( _current, workInProgress, elementType, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (_current !== null) { // A lazy component only mounts if it suspended inside a non- @@ -12318,18 +12606,17 @@ function mountLazyComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } - var props = workInProgress.pendingProps; // We can't start a User Timing measurement with correct label yet. - // Cancel and resume right after we know the tag. - - cancelWorkTimer(workInProgress); - var Component = readLazyComponentType(elementType); // Store the unwrapped component in the type. + var props = workInProgress.pendingProps; + var lazyComponent = elementType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); // Store the unwrapped component in the type. workInProgress.type = Component; var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - startWorkTimer(workInProgress); var resolvedProps = resolveDefaultProps(Component, props); var child; @@ -12347,7 +12634,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12364,7 +12651,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12381,7 +12668,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12407,8 +12694,8 @@ function mountLazyComponent( workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); return child; } @@ -12443,7 +12730,7 @@ function mountIncompleteClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (_current !== null) { // An incomplete component only mounts if it suspended inside a non- @@ -12453,7 +12740,7 @@ function mountIncompleteClassComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // Promote the fiber to a class and try rendering again. workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` @@ -12470,21 +12757,16 @@ function mountIncompleteClassComponent( hasContext = false; } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); return finishClassComponent( null, workInProgress, Component, true, hasContext, - renderExpirationTime + renderLanes ); } @@ -12492,7 +12774,7 @@ function mountIndeterminateComponent( _current, workInProgress, Component, - renderExpirationTime + renderLanes ) { if (_current !== null) { // An indeterminate component only mounts if it suspended inside a non- @@ -12502,7 +12784,7 @@ function mountIndeterminateComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -12513,7 +12795,7 @@ function mountIndeterminateComponent( context = getMaskedContext(workInProgress, unmaskedContext); } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var value; { @@ -12539,6 +12821,7 @@ function mountIndeterminateComponent( ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); } + setIsRendering(true); ReactCurrentOwner$1.current = workInProgress; value = renderWithHooks( null, @@ -12546,34 +12829,65 @@ function mountIndeterminateComponent( Component, props, context, - renderExpirationTime + renderLanes ); + setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; + + { + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + var _componentName = getComponentName(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName, + _componentName, + _componentName + ); + + didWarnAboutModulePatternComponent[_componentName] = true; + } + } + } if ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. typeof value === "object" && value !== null && typeof value.render === "function" && value.$$typeof === undefined ) { { - var _componentName = getComponentName(Component) || "Unknown"; + var _componentName2 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutModulePatternComponent[_componentName]) { + if (!didWarnAboutModulePatternComponent[_componentName2]) { error( "The <%s /> component appears to be a function component that returns a class instance. " + "Change %s to a class that extends React.Component instead. " + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + "cannot be called with `new` by React.", - _componentName, - _componentName, - _componentName + _componentName2, + _componentName2, + _componentName2 ); - didWarnAboutModulePatternComponent[_componentName] = true; + didWarnAboutModulePatternComponent[_componentName2] = true; } } // Proceed under the assumption that this is a class instance @@ -12608,20 +12922,20 @@ function mountIndeterminateComponent( } adoptClassInstance(workInProgress, value); - mountClassInstance(workInProgress, Component, props, renderExpirationTime); + mountClassInstance(workInProgress, Component, props, renderLanes); return finishClassComponent( null, workInProgress, Component, true, hasContext, - renderExpirationTime + renderLanes ); } else { // Proceed under the assumption that this is a function component workInProgress.tag = FunctionComponent; - reconcileChildren(null, workInProgress, value, renderExpirationTime); + reconcileChildren(null, workInProgress, value, renderLanes); { validateFunctionComponentInDev(workInProgress, Component); @@ -12670,15 +12984,15 @@ function validateFunctionComponentInDev(workInProgress, Component) { } if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName2 = getComponentName(Component) || "Unknown"; + var _componentName3 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName2]) { + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { error( "%s: Function components do not support getDerivedStateFromProps.", - _componentName2 + _componentName3 ); - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName2] = true; + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; } } @@ -12686,15 +13000,15 @@ function validateFunctionComponentInDev(workInProgress, Component) { typeof Component.contextType === "object" && Component.contextType !== null ) { - var _componentName3 = getComponentName(Component) || "Unknown"; + var _componentName4 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName3]) { + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { error( "%s: Function components do not support contextType.", - _componentName3 + _componentName4 ); - didWarnAboutContextTypeOnFunctionComponent[_componentName3] = true; + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; } } } @@ -12702,41 +13016,68 @@ function validateFunctionComponentInDev(workInProgress, Component) { var SUSPENDED_MARKER = { dehydrated: null, - retryTime: NoWork + retryLane: NoLane }; -function shouldRemainOnFallback(suspenseContext, current, workInProgress) { - // If the context is telling us that we should show a fallback, and we're not - // already showing content, then we should show the fallback instead. - return ( - hasSuspenseContext(suspenseContext, ForceSuspenseFallback) && - (current === null || current.memoizedState !== null) - ); +function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes + }; } -function updateSuspenseComponent( +function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes) + }; +} // TODO: Probably should inline this back + +function shouldRemainOnFallback( + suspenseContext, current, workInProgress, - renderExpirationTime + renderLanes ) { - var mode = workInProgress.mode; + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + if (current !== null) { + var suspenseState = current.memoizedState; + + if (suspenseState === null) { + // Currently showing content. Don't hide it, even if ForceSuspenseFallack + // is true. More precise name might be "ForceRemainSuspenseFallback". + // Note: This is a factoring smell. Can't remain on a fallback if there's + // no fallback to remain on. + return false; + } + } // Not currently showing content. Consult the Suspense context. + + return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); +} + +function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); +} + +function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. { if (shouldSuspend(workInProgress)) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } } var suspenseContext = suspenseStackCursor.current; - var nextDidTimeout = false; - var didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { // Something in this boundary's subtree already suspended. Switch to // rendering the fallback children. - nextDidTimeout = true; - workInProgress.effectTag &= ~DidCapture; + showFallback = true; + workInProgress.flags &= ~DidCapture; } else { // Attempting the main content if (current === null || current.memoizedState !== null) { @@ -12758,290 +13099,411 @@ function updateSuspenseComponent( } suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // This next part is a bit confusing. If the children timeout, we switch to - // showing the fallback children in place of the "primary" children. - // However, we don't want to delete the primary children because then their - // state will be lost (both the React state and the host state, e.g. - // uncontrolled form inputs). Instead we keep them mounted and hide them. - // Both the fallback children AND the primary children are rendered at the - // same time. Once the primary children are un-suspended, we can delete - // the fallback children — don't need to preserve their state. + pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconcilation logic. Two + // main reasons this is so complicated. // - // The two sets of children are siblings in the host environment, but - // semantically, for purposes of reconciliation, they are two separate sets. - // So we store them using two fragment fibers. + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). // - // However, we want to avoid allocating extra fibers for every placeholder. - // They're only necessary when the children time out, because that's the - // only time when both sets are mounted. + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. // - // So, the extra fragment fibers are only used if the children time out. - // Otherwise, we render the primary children directly. This requires some - // custom reconciliation logic to preserve the state of the primary - // children. It's essentially a very basic form of re-parenting. + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. if (current === null) { + // Initial mount // If we're currently hydrating, try to hydrate this boundary. // But only if this has a fallback. - if (nextProps.fallback !== undefined); // This is the initial mount. This branch is pretty simple because there's - // no previous state that needs to be preserved. + if (nextProps.fallback !== undefined); - if (nextDidTimeout) { - // Mount separate fragments for primary and fallback children. - var nextFallbackChildren = nextProps.fallback; - var primaryChildFragment = createFiberFromFragment( - null, - mode, - NoWork, - null - ); - primaryChildFragment.return = workInProgress; - - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var progressedState = workInProgress.memoizedState; - var progressedPrimaryChild = - progressedState !== null - ? workInProgress.child.child - : workInProgress.child; - primaryChildFragment.child = progressedPrimaryChild; - var progressedChild = progressedPrimaryChild; - - while (progressedChild !== null) { - progressedChild.return = primaryChildFragment; - progressedChild = progressedChild.sibling; - } - } + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = createFiberFromFragment( + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, nextFallbackChildren, - mode, - renderExpirationTime, - null + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes ); - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; // Skip the primary children, and continue working on the - // fallback children. - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; + return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + + return _fallbackFragment; } else { - // Mount the primary children without an intermediate fragment fiber. - var nextPrimaryChildren = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( + return mountSuspensePrimaryChildren( workInProgress, - null, nextPrimaryChildren, - renderExpirationTime - )); + renderLanes + ); } } else { - // This is an update. This branch is more complicated because we need to - // ensure the state of the primary children is preserved. + // This is an update. + // If the current fiber has a SuspenseState, that means it's already showing + // a fallback. var prevState = current.memoizedState; if (prevState !== null) { - // wrapped in a fragment fiber. - - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - - if (nextDidTimeout) { - // Still timed out. Reuse the current primary children by cloning - // its fragment. We're going to skip over these entirely. + if (showFallback) { var _nextFallbackChildren2 = nextProps.fallback; + var _nextPrimaryChildren2 = nextProps.children; - var _primaryChildFragment2 = createWorkInProgress( - currentPrimaryChildFragment, - currentPrimaryChildFragment.pendingProps + var _fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren2, + _nextFallbackChildren2, + renderLanes ); - _primaryChildFragment2.return = workInProgress; - - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var _progressedState = workInProgress.memoizedState; - - var _progressedPrimaryChild = - _progressedState !== null - ? workInProgress.child.child - : workInProgress.child; - - if (_progressedPrimaryChild !== currentPrimaryChildFragment.child) { - _primaryChildFragment2.child = _progressedPrimaryChild; - var _progressedChild2 = _progressedPrimaryChild; - - while (_progressedChild2 !== null) { - _progressedChild2.return = _primaryChildFragment2; - _progressedChild2 = _progressedChild2.sibling; - } - } - } // Because primaryChildFragment is a new fiber that we're inserting as the - // parent of a new tree, we need to set its treeBaseDuration. - - if (workInProgress.mode & ProfileMode) { - // treeBaseDuration is the sum of all the child tree base durations. - var _treeBaseDuration = 0; - var _hiddenChild = _primaryChildFragment2.child; + var _primaryChildFragment3 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment3.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return _fallbackChildFragment; + } else { + var _nextPrimaryChildren3 = nextProps.children; - while (_hiddenChild !== null) { - _treeBaseDuration += _hiddenChild.treeBaseDuration; - _hiddenChild = _hiddenChild.sibling; - } + var _primaryChildFragment4 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren3, + renderLanes + ); - _primaryChildFragment2.treeBaseDuration = _treeBaseDuration; - } // Clone the fallback child fragment, too. These we'll continue - // working on. + workInProgress.memoizedState = null; + return _primaryChildFragment4; + } + } else { + // The current tree is not already showing a fallback. + if (showFallback) { + // Timed out. + var _nextFallbackChildren3 = nextProps.fallback; + var _nextPrimaryChildren4 = nextProps.children; - var _fallbackChildFragment2 = createWorkInProgress( - currentFallbackChildFragment, - _nextFallbackChildren2 + var _fallbackChildFragment2 = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren4, + _nextFallbackChildren3, + renderLanes ); - _fallbackChildFragment2.return = workInProgress; - _primaryChildFragment2.sibling = _fallbackChildFragment2; - _primaryChildFragment2.childExpirationTime = NoWork; // Skip the primary children, and continue working on the + var _primaryChildFragment5 = workInProgress.child; + var _prevOffscreenState = current.child.memoizedState; + _primaryChildFragment5.memoizedState = + _prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); + _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); // Skip the primary children, and continue working on the // fallback children. workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = _primaryChildFragment2; return _fallbackChildFragment2; } else { - // No longer suspended. Switch back to showing the primary children, - // and remove the intermediate fragment fiber. - var _nextPrimaryChildren = nextProps.children; - var currentPrimaryChild = currentPrimaryChildFragment.child; - var primaryChild = reconcileChildFibers( + // Still haven't timed out. Continue rendering the children, like we + // normally do. + var _nextPrimaryChildren5 = nextProps.children; + + var _primaryChildFragment6 = updateSuspensePrimaryChildren( + current, workInProgress, - currentPrimaryChild, - _nextPrimaryChildren, - renderExpirationTime - ); // If this render doesn't suspend, we need to delete the fallback - // children. Wait until the complete phase, after we've confirmed the - // fallback is no longer needed. - // TODO: Would it be better to store the fallback fragment on - // the stateNode? - // Continue rendering the children, like we normally do. + _nextPrimaryChildren5, + renderLanes + ); workInProgress.memoizedState = null; - return (workInProgress.child = primaryChild); + return _primaryChildFragment6; } - } else { - // The current tree has not already timed out. That means the primary - // children are not wrapped in a fragment fiber. - var _currentPrimaryChild = current.child; + } + } +} - if (nextDidTimeout) { - // Timed out. Wrap the children in a fragment fiber to keep them - // separate from the fallback children. - var _nextFallbackChildren3 = nextProps.fallback; +function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes +) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = createFiberFromOffscreen( + primaryChildProps, + mode, + renderLanes, + null + ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - var _primaryChildFragment3 = createFiberFromFragment( - // It shouldn't matter what the pending props are because we aren't - // going to render this fragment. - null, - mode, - NoWork, - null - ); +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; + + if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) { + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = 0; + primaryChildFragment.treeBaseDuration = 0; + } + + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = createFiberFromOffscreen( + primaryChildProps, + mode, + NoLanes, + null + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } - _primaryChildFragment3.return = workInProgress; - _primaryChildFragment3.child = _currentPrimaryChild; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} - if (_currentPrimaryChild !== null) { - _currentPrimaryChild.return = _primaryChildFragment3; - } // Even though we're creating a new fiber, there are no new children, - // because we're reusing an already mounted tree. So we don't need to - // schedule a placement. - // primaryChildFragment.effectTag |= Placement; +function createWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); +} - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var _progressedState2 = workInProgress.memoizedState; +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = createWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); - var _progressedPrimaryChild2 = - _progressedState2 !== null - ? workInProgress.child.child - : workInProgress.child; + if ((workInProgress.mode & BlockingMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; + } - _primaryChildFragment3.child = _progressedPrimaryChild2; - var _progressedChild3 = _progressedPrimaryChild2; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - while (_progressedChild3 !== null) { - _progressedChild3.return = _primaryChildFragment3; - _progressedChild3 = _progressedChild3.sibling; - } - } // Because primaryChildFragment is a new fiber that we're inserting as the - // parent of a new tree, we need to set its treeBaseDuration. + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + currentFallbackChildFragment.nextEffect = null; + currentFallbackChildFragment.flags = Deletion; + workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment; + } - if (workInProgress.mode & ProfileMode) { - // treeBaseDuration is the sum of all the child tree base durations. - var _treeBaseDuration2 = 0; - var _hiddenChild2 = _primaryChildFragment3.child; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - while (_hiddenChild2 !== null) { - _treeBaseDuration2 += _hiddenChild2.treeBaseDuration; - _hiddenChild2 = _hiddenChild2.sibling; - } +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; - _primaryChildFragment3.treeBaseDuration = _treeBaseDuration2; - } // Create a fragment from the fallback children, too. + if ( + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + (mode & BlockingMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was + // already cloned. In legacy mode, the only case where this isn't true is + // when DevTools forces us to display a fallback; we skip the first render + // pass entirely and go straight to rendering the fallback. (In Concurrent + // Mode, SuspenseList can also trigger this scenario, but this is a legacy- + // only codepath.) + workInProgress.child !== currentPrimaryChildFragment + ) { + var progressedPrimaryFragment = workInProgress.child; + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration; + primaryChildFragment.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration; + } // The fallback fiber was added as a deletion effect during the first pass. + // However, since we're going to remain on the fallback, we no longer want + // to delete it. So we need to remove it from the list. Deletions are stored + // on the same list as effects. We want to keep the effects from the primary + // tree. So we copy the primary child fragment's effect list, which does not + // include the fallback deletion effect. + + var progressedLastEffect = primaryChildFragment.lastEffect; + + if (progressedLastEffect !== null) { + workInProgress.firstEffect = primaryChildFragment.firstEffect; + workInProgress.lastEffect = progressedLastEffect; + progressedLastEffect.nextEffect = null; + } else { + // TODO: Reset this somewhere else? Lol legacy mode is so weird. + workInProgress.firstEffect = workInProgress.lastEffect = null; + } + } else { + primaryChildFragment = createWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); + } - var _fallbackChildFragment3 = createFiberFromFragment( - _nextFallbackChildren3, - mode, - renderExpirationTime, - null - ); + var fallbackChildFragment; - _fallbackChildFragment3.return = workInProgress; - _primaryChildFragment3.sibling = _fallbackChildFragment3; - _fallbackChildFragment3.effectTag |= Placement; - _primaryChildFragment3.childExpirationTime = NoWork; // Skip the primary children, and continue working on the - // fallback children. + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren + ); + } else { + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = _primaryChildFragment3; - return _fallbackChildFragment3; - } else { - // Still haven't timed out. Continue rendering the children, like we - // normally do. - workInProgress.memoizedState = null; - var _nextPrimaryChildren2 = nextProps.children; - return (workInProgress.child = reconcileChildFibers( - workInProgress, - _currentPrimaryChild, - _nextPrimaryChildren2, - renderExpirationTime - )); - } - } + fallbackChildFragment.flags |= Placement; } -} -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - if (fiber.expirationTime < renderExpirationTime) { - fiber.expirationTime = renderExpirationTime; - } + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; - if (alternate !== null && alternate.expirationTime < renderExpirationTime) { - alternate.expirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function propagateSuspenseContextChange( workInProgress, firstChild, - renderExpirationTime + renderLanes ) { // Mark any Suspense boundaries with fallbacks as having work to do. // If they were previously forced into fallbacks, they may now be able @@ -13053,7 +13515,7 @@ function propagateSuspenseContextChange( var state = node.memoizedState; if (state !== null) { - scheduleWorkOnFiber(node, renderExpirationTime); + scheduleWorkOnFiber(node, renderLanes); } } else if (node.tag === SuspenseListComponent) { // If the tail is hidden there might not be an Suspense boundaries @@ -13061,7 +13523,7 @@ function propagateSuspenseContextChange( // list itself. // We don't have to traverse to the children of the list since // the list will propagate the change when it rerenders. - scheduleWorkOnFiber(node, renderExpirationTime); + scheduleWorkOnFiber(node, renderLanes); } else if (node.child !== null) { node.child.return = node; node = node.child; @@ -13280,7 +13742,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }; @@ -13291,7 +13752,6 @@ function initSuspenseListRenderState( renderState.renderingStartTime = 0; renderState.last = lastContentRow; renderState.tail = tail; - renderState.tailExpiration = 0; renderState.tailMode = tailMode; renderState.lastEffect = lastEffectBeforeRendering; } @@ -13303,11 +13763,7 @@ function initSuspenseListRenderState( // in fallback state. Then we render each row in the tail one-by-one. // That happens in the completeWork phase without going back to beginWork. -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps; var revealOrder = nextProps.revealOrder; var tailMode = nextProps.tail; @@ -13315,7 +13771,7 @@ function updateSuspenseListComponent( validateRevealOrder(revealOrder); validateTailOptions(tailMode, revealOrder); validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + reconcileChildren(current, workInProgress, newChildren, renderLanes); var suspenseContext = suspenseStackCursor.current; var shouldForceFallback = hasSuspenseContext( suspenseContext, @@ -13327,10 +13783,10 @@ function updateSuspenseListComponent( suspenseContext, ForceSuspenseFallback ); - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } else { var didSuspendBefore = - current !== null && (current.effectTag & DidCapture) !== NoEffect; + current !== null && (current.flags & DidCapture) !== NoFlags; if (didSuspendBefore) { // If we previously forced a fallback, we need to schedule work @@ -13339,7 +13795,7 @@ function updateSuspenseListComponent( propagateSuspenseContextChange( workInProgress, workInProgress.child, - renderExpirationTime + renderLanes ); } @@ -13349,7 +13805,7 @@ function updateSuspenseListComponent( pushSuspenseContext(workInProgress, suspenseContext); if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, SuspenseList doesn't work so we just + // In legacy mode, SuspenseList doesn't work so we just // use make it a noop by treating it as the default revealOrder. workInProgress.memoizedState = null; } else { @@ -13439,7 +13895,7 @@ function updateSuspenseListComponent( return workInProgress.child; } -function updatePortalComponent(current, workInProgress, renderExpirationTime) { +function updatePortalComponent(current, workInProgress, renderLanes) { pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); var nextChildren = workInProgress.pendingProps; @@ -13453,21 +13909,18 @@ function updatePortalComponent(current, workInProgress, renderExpirationTime) { workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } else { - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } return workInProgress.child; } -function updateContextProvider(current, workInProgress, renderExpirationTime) { +var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + +function updateContextProvider(current, workInProgress, renderLanes) { var providerType = workInProgress.type; var context = providerType._context; var newProps = workInProgress.pendingProps; @@ -13475,6 +13928,16 @@ function updateContextProvider(current, workInProgress, renderExpirationTime) { var newValue = newProps.value; { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; + + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } + var providerPropTypes = workInProgress.type.propTypes; if (providerPropTypes) { @@ -13494,29 +13957,24 @@ function updateContextProvider(current, workInProgress, renderExpirationTime) { return bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); } } else { // The context value changed. Search for matching consumers and schedule // them to update. - propagateContextChange( - workInProgress, - context, - changedBits, - renderExpirationTime - ); + propagateContextChange(workInProgress, context, changedBits, renderLanes); } } var newChildren = newProps.children; - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } var hasWarnedAboutUsingContextAsConsumer = false; -function updateContextConsumer(current, workInProgress, renderExpirationTime) { +function updateContextConsumer(current, workInProgress, renderLanes) { var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In // DEV mode, we create a separate object for Context.Consumer that acts // like a proxy to Context. This proxy object adds unnecessary code in PROD @@ -13559,7 +14017,7 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) { } } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var newValue = readContext(context, newProps.unstable_observedBits); var newChildren; @@ -13570,8 +14028,8 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) { setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } @@ -13579,13 +14037,7 @@ function markWorkInProgressReceivedUpdate() { didReceiveUpdate = true; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { - cancelWorkTimer(workInProgress); - +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { if (current !== null) { // Reuse previous dependencies workInProgress.dependencies = current.dependencies; @@ -13596,15 +14048,9 @@ function bailoutOnAlreadyFinishedWork( stopProfilerTimerIfRunning(); } - var updateExpirationTime = workInProgress.expirationTime; - - if (updateExpirationTime !== NoWork) { - markUnprocessedUpdateTime(updateExpirationTime); - } // Check if the children have any pending work. - - var childExpirationTime = workInProgress.childExpirationTime; + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. - if (childExpirationTime < renderExpirationTime) { + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { // The children don't have any work either. We can skip them. // TODO: Once we add back resuming, we should check if the children are // a work-in-progress set. If so, we need to transfer their effects. @@ -13665,15 +14111,15 @@ function remountFiber(current, oldWorkInProgress, newWorkInProgress) { } current.nextEffect = null; - current.effectTag = Deletion; - newWorkInProgress.effectTag |= Placement; // Restart work from the new fiber. + current.flags = Deletion; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. return newWorkInProgress; } } -function beginWork(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +function beginWork(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; { if (workInProgress._debugNeedsRemount && current !== null) { @@ -13687,7 +14133,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, - workInProgress.expirationTime + workInProgress.lanes ) ); } @@ -13705,7 +14151,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // If props or context changed, mark the fiber as having performed work. // This may be unset if the props are determined to be equal later (memo). didReceiveUpdate = true; - } else if (updateExpirationTime < renderExpirationTime) { + } else if (!includesSomeLane(renderLanes, updateLanes)) { didReceiveUpdate = false; // This fiber does not have any pending work. Bailout without entering // the begin phase. There's still some bookkeeping we that needs to be done // in this optimized path, mostly pushing stuff onto the stack. @@ -13717,20 +14163,6 @@ function beginWork(current, workInProgress, renderExpirationTime) { case HostComponent: pushHostContext(workInProgress); - - if ( - workInProgress.mode & ConcurrentMode && - renderExpirationTime !== Never && - shouldDeprioritizeSubtree(workInProgress.type) - ) { - { - markSpawnedWork(Never); - } // Schedule this fiber to re-render at offscreen priority. Then bailout. - - workInProgress.expirationTime = workInProgress.childExpirationTime = Never; - return null; - } - break; case ClassComponent: { @@ -13759,11 +14191,13 @@ function beginWork(current, workInProgress, renderExpirationTime) { case Profiler: { // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = - workInProgress.childExpirationTime >= renderExpirationTime; + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); if (hasChildWork) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, @@ -13783,21 +14217,19 @@ function beginWork(current, workInProgress, renderExpirationTime) { // child fragment. var primaryChildFragment = workInProgress.child; - var primaryChildExpirationTime = - primaryChildFragment.childExpirationTime; + var primaryChildLanes = primaryChildFragment.childLanes; - if ( - primaryChildExpirationTime !== NoWork && - primaryChildExpirationTime >= renderExpirationTime - ) { + if (includesSomeLane(renderLanes, primaryChildLanes)) { // The primary children have pending work. Use the normal path // to attempt to render the primary children again. return updateSuspenseComponent( current, workInProgress, - renderExpirationTime + renderLanes ); } else { + // The primary child fragment does not have pending work marked + // on it pushSuspenseContext( workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current) @@ -13807,7 +14239,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { var child = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); if (child !== null) { @@ -13829,10 +14261,12 @@ function beginWork(current, workInProgress, renderExpirationTime) { } case SuspenseListComponent: { - var didSuspendBefore = (current.effectTag & DidCapture) !== NoEffect; + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; - var _hasChildWork = - workInProgress.childExpirationTime >= renderExpirationTime; + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); if (didSuspendBefore) { if (_hasChildWork) { @@ -13844,13 +14278,13 @@ function beginWork(current, workInProgress, renderExpirationTime) { return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); } // If none of the children had any work, that means that none of // them got retried so they'll still be blocked in the same way // as before. We can fast bail out. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } // If nothing suspended before and we're rendering the same children, // then the tail doesn't matter. Anything new that suspends will work // in the "together" mode, so we can continue from the state we had. @@ -13862,6 +14296,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // update in the past but didn't complete it. renderState.rendering = null; renderState.tail = null; + renderState.lastEffect = null; } pushSuspenseContext(workInProgress, suspenseStackCursor.current); @@ -13875,19 +14310,35 @@ function beginWork(current, workInProgress, renderExpirationTime) { return null; } } + + case OffscreenComponent: + case LegacyHiddenComponent: { + // Need to check if the tree still needs to be deferred. This is + // almost identical to the logic used in the normal update path, + // so we'll just enter that. The only difference is we'll bail out + // at the next level instead of this one, because the child props + // have not changed. Which is fine. + // TODO: Probably should refactor `beginWork` to split the bailout + // path from the normal path. I'm tempted to do a labeled break here + // but I won't :) + workInProgress.lanes = NoLanes; + return updateOffscreenComponent(current, workInProgress, renderLanes); + } } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; + } } } else { didReceiveUpdate = false; @@ -13897,7 +14348,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // sometimes bails out later in the begin phase. This indicates that we should // move this assignment out of the common path and into each branch. - workInProgress.expirationTime = NoWork; + workInProgress.lanes = NoLanes; switch (workInProgress.tag) { case IndeterminateComponent: { @@ -13905,7 +14356,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.type, - renderExpirationTime + renderLanes ); } @@ -13915,8 +14366,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { current, workInProgress, elementType, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -13932,7 +14383,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component, resolvedProps, - renderExpirationTime + renderLanes ); } @@ -13950,32 +14401,24 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component2, _resolvedProps, - renderExpirationTime + renderLanes ); } case HostRoot: - return updateHostRoot(current, workInProgress, renderExpirationTime); + return updateHostRoot(current, workInProgress, renderLanes); case HostComponent: - return updateHostComponent(current, workInProgress, renderExpirationTime); + return updateHostComponent(current, workInProgress, renderLanes); case HostText: return updateHostText(); case SuspenseComponent: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case HostPortal: - return updatePortalComponent( - current, - workInProgress, - renderExpirationTime - ); + return updatePortalComponent(current, workInProgress, renderLanes); case ForwardRef: { var type = workInProgress.type; @@ -13991,32 +14434,24 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, type, _resolvedProps2, - renderExpirationTime + renderLanes ); } case Fragment: - return updateFragment(current, workInProgress, renderExpirationTime); + return updateFragment(current, workInProgress, renderLanes); case Mode: - return updateMode(current, workInProgress, renderExpirationTime); + return updateMode(current, workInProgress, renderLanes); case Profiler: - return updateProfiler(current, workInProgress, renderExpirationTime); + return updateProfiler(current, workInProgress, renderLanes); case ContextProvider: - return updateContextProvider( - current, - workInProgress, - renderExpirationTime - ); + return updateContextProvider(current, workInProgress, renderLanes); case ContextConsumer: - return updateContextConsumer( - current, - workInProgress, - renderExpirationTime - ); + return updateContextConsumer(current, workInProgress, renderLanes); case MemoComponent: { var _type2 = workInProgress.type; @@ -14045,8 +14480,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _type2, _resolvedProps3, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -14056,8 +14491,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -14075,16 +14510,28 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component3, _resolvedProps4, - renderExpirationTime + renderLanes ); } case SuspenseListComponent: { - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } + + case FundamentalComponent: { + break; + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } + + case LegacyHiddenComponent: { + return updateLegacyHiddenComponent(current, workInProgress, renderLanes); } } @@ -14100,11 +14547,11 @@ function beginWork(current, workInProgress, renderExpirationTime) { function markUpdate(workInProgress) { // Tag the fiber with an update effect. This turns a Placement into // a PlacementAndUpdate. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } function markRef$1(workInProgress) { - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } var appendAllChildren; @@ -14149,7 +14596,7 @@ var updateHostText$1; appendInitialChild(parent, _instance); } else if (node.tag === HostPortal); else if (node.tag === SuspenseComponent) { - if ((node.effectTag & Update) !== NoEffect) { + if ((node.flags & Update) !== NoFlags) { // Need to toggle the visibility of the primary children. var newIsHidden = node.memoizedState !== null; @@ -14244,7 +14691,7 @@ var updateHostText$1; appendChildToContainerChildSet(containerChildSet, _instance3); } else if (node.tag === HostPortal); else if (node.tag === SuspenseComponent) { - if ((node.effectTag & Update) !== NoEffect) { + if ((node.flags & Update) !== NoFlags) { // Need to toggle the visibility of the primary children. var newIsHidden = node.memoizedState !== null; @@ -14474,7 +14921,7 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { @@ -14503,6 +14950,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { case HostRoot: { popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); var fiberRoot = workInProgress.stateNode; if (fiberRoot.pendingContext) { @@ -14519,6 +14967,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { // If we hydrated, then we'll need to schedule an update for // the commit side-effects on the root. markUpdate(workInProgress); + } else if (!fiberRoot.hydrate) { + // Schedule an effect to clear this container at the start of the next commit. + // This handles the case of React rendering into a container with previous children. + // It's also safe to do for updates too, because current.child would only be null + // if the previous render was null (so the the container would already be empty). + workInProgress.flags |= Snapshot; } } @@ -14577,9 +15031,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { currentHostContext, workInProgress ); - appendAllChildren(instance, workInProgress, false, false); // This needs to be set before we mount Flare event listeners - - workInProgress.stateNode = instance; + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. } if (workInProgress.ref !== null) { @@ -14635,9 +15088,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { popSuspenseContext(workInProgress); var nextState = workInProgress.memoizedState; - if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + if ((workInProgress.flags & DidCapture) !== NoFlags) { // Something suspended. Re-render with the fallback children. - workInProgress.expirationTime = renderExpirationTime; // Do not reset the effect list. + workInProgress.lanes = renderLanes; // Do not reset the effect list. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } return workInProgress; } @@ -14650,29 +15107,6 @@ function completeWork(current, workInProgress, renderExpirationTime) { } else { var prevState = current.memoizedState; prevDidTimeout = prevState !== null; - - if (!nextDidTimeout && prevState !== null) { - // We just switched from the fallback to the normal children. - // Delete the fallback. - // TODO: Would it be better to store the fallback fragment on - // the stateNode during the begin phase? - var currentFallbackChild = current.child.sibling; - - if (currentFallbackChild !== null) { - // Deletions go at the beginning of the return fiber's effect list - var first = workInProgress.firstEffect; - - if (first !== null) { - workInProgress.firstEffect = currentFallbackChild; - currentFallbackChild.nextEffect = first; - } else { - workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChild; - currentFallbackChild.nextEffect = null; - } - - currentFallbackChild.effectTag = Deletion; - } - } } if (nextDidTimeout && !prevDidTimeout) { @@ -14717,7 +15151,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { // If this boundary just timed out, schedule an effect to attach a // retry listener to the promise. This flag is also used to hide the // primary children. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -14727,6 +15161,11 @@ function completeWork(current, workInProgress, renderExpirationTime) { case HostPortal: popHostContainer(workInProgress); updateHostContainer(workInProgress); + + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } + return null; case ContextProvider: @@ -14756,8 +15195,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } - var didSuspendAlready = - (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; var renderedTail = renderState.rendering; if (renderedTail === null) { @@ -14774,7 +15212,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { // findFirstSuspended. var cannotBeSuspended = renderHasNotSuspendedYet() && - (current === null || (current.effectTag & DidCapture) === NoEffect); + (current === null || (current.flags & DidCapture) === NoFlags); if (!cannotBeSuspended) { var row = workInProgress.child; @@ -14784,7 +15222,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (suspended !== null) { didSuspendAlready = true; - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to // its thennables. Instead, we'll transfer its thennables to the @@ -14802,7 +15240,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (newThennables !== null) { workInProgress.updateQueue = newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect list before doing the second pass since that's now invalid. @@ -14813,7 +15251,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { workInProgress.lastEffect = renderState.lastEffect; // Reset the child fibers to their original state. - resetChildFibers(workInProgress, renderExpirationTime); // Set up the Suspense Context to force suspense and immediately + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately // rerender the children. pushSuspenseContext( @@ -14826,7 +15264,29 @@ function completeWork(current, workInProgress, renderExpirationTime) { return workInProgress.child; } - row = row.sibling; + row = row.sibling; + } + } + + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); } } } else { @@ -14838,7 +15298,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { var _suspended = findFirstSuspended(renderedTail); if (_suspended !== null) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. @@ -14846,7 +15306,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (_newThennables !== null) { workInProgress.updateQueue = _newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } cutOffTailIfNeeded(renderState, true); // This might have been modified. @@ -14854,7 +15314,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { if ( renderState.tail === null && renderState.tailMode === "hidden" && - !renderedTail.alternate + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. ) { // We need to delete the row we just rendered. // Reset the effect list to what it was before we rendered this @@ -14869,28 +15330,31 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } } else if ( - // The time it took to render last row is greater than time until - // the expiration. + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. now() * 2 - renderState.renderingStartTime > - renderState.tailExpiration && - renderExpirationTime > Never + getRenderTargetTime() && + renderLanes !== OffscreenLane ) { // We have now passed our CPU deadline and we'll just give up further // attempts to render the main content and only render fallbacks. // The assumption is that this is usually faster. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. If we can show - // them, then they really have the same priority as this render. - // So we'll pick it back up the very next render pass once we've had - // an opportunity to yield for paint. + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - var nextPriority = renderExpirationTime - 1; - workInProgress.expirationTime = workInProgress.childExpirationTime = nextPriority; + workInProgress.lanes = SomeRetryLane; { - markSpawnedWork(nextPriority); + markSpawnedWork(SomeRetryLane); } } } @@ -14918,18 +15382,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (renderState.tail !== null) { // We still have tail rows to render. - if (renderState.tailExpiration === 0) { - // Heuristic for how long we're willing to spend rendering rows - // until we just give up and show what we have so far. - var TAIL_EXPIRATION_TIMEOUT_MS = 500; - renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS; // TODO: This is meant to mimic the train model or JND but this - // is a per component value. It should really be since the start - // of the total render or last commit. Consider using something like - // globalMostRecentFallbackTime. That doesn't account for being - // suspended for part of the time or when it's a new render. - // It should probably use a global start time value instead. - } // Pop a row. - + // Pop a row. var next = renderState.tail; renderState.rendering = next; renderState.tail = next.sibling; @@ -14957,6 +15410,35 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } + + case FundamentalComponent: { + break; + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + + if (current !== null) { + var _nextState = workInProgress.memoizedState; + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; + var nextIsHidden = _nextState !== null; + + if ( + prevIsHidden !== nextIsHidden && + newProps.mode !== "unstable-defer-without-hiding" + ) { + workInProgress.flags |= Update; + } + } + + return null; + } } { @@ -14968,7 +15450,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { } } -function unwindWork(workInProgress, renderExpirationTime) { +function unwindWork(workInProgress, renderLanes) { switch (workInProgress.tag) { case ClassComponent: { var Component = workInProgress.type; @@ -14977,10 +15459,15 @@ function unwindWork(workInProgress, renderExpirationTime) { popContext(workInProgress); } - var effectTag = workInProgress.effectTag; + var flags = workInProgress.flags; + + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - if (effectTag & ShouldCapture) { - workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; return workInProgress; } @@ -14990,198 +15477,553 @@ function unwindWork(workInProgress, renderExpirationTime) { case HostRoot: { popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); - var _effectTag = workInProgress.effectTag; + resetWorkInProgressVersions(); + var _flags = workInProgress.flags; - if (!((_effectTag & DidCapture) === NoEffect)) { + if (!((_flags & DidCapture) === NoFlags)) { throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); } - workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; - return workInProgress; - } + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; + return workInProgress; + } + + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } + + case SuspenseComponent: { + popSuspenseContext(workInProgress); + + var _flags2 = workInProgress.flags; + + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } + + return workInProgress; + } + + return null; + } + + case SuspenseListComponent: { + popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. + + return null; + } + + case HostPortal: + popHostContainer(workInProgress); + return null; + + case ContextProvider: + popProvider(workInProgress); + return null; + + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(workInProgress); + return null; + + default: + return null; + } +} + +function unwindInterruptedWork(interruptedWork) { + switch (interruptedWork.tag) { + case ClassComponent: { + var childContextTypes = interruptedWork.type.childContextTypes; + + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); + } + + break; + } + + case HostRoot: { + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); + resetWorkInProgressVersions(); + break; + } + + case HostComponent: { + popHostContext(interruptedWork); + break; + } + + case HostPortal: + popHostContainer(interruptedWork); + break; + + case SuspenseComponent: + popSuspenseContext(interruptedWork); + break; + + case SuspenseListComponent: + popSuspenseContext(interruptedWork); + break; + + case ContextProvider: + popProvider(interruptedWork); + break; + + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(interruptedWork); + break; + } +} + +function createCapturedValue(value, source) { + // If the value is an error, call this function immediately after it is thrown + // so the stack is accurate. + return { + value: value, + source: source, + stack: getStackByFiberInDevAndProd(source) + }; +} + +if ( + !( + typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog === + "function" + ) +) { + throw Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." + ); +} + +function showErrorDialog(boundary, errorInfo) { + var capturedError = { + componentStack: errorInfo.stack !== null ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + boundary !== null && boundary.tag === ClassComponent + ? boundary.stateNode + : null + }; + return ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( + capturedError + ); +} + +function logCapturedError(boundary, errorInfo) { + try { + var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. + + if (logError === false) { + return; + } + + var error = errorInfo.value; + + if (true) { + var source = errorInfo.source; + var stack = errorInfo.stack; + var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling + // `preventDefault()` in window `error` handler. + // We record this information as an expando on the error. + + if (error != null && error._suppressLogging) { + if (boundary.tag === ClassComponent) { + // The error is recoverable and was silenced. + // Ignore it and don't print the stack addendum. + // This is handy for testing error boundaries without noise. + return; + } // The error is fatal. Since the silencing might have + // been accidental, we'll surface it anyway. + // However, the browser would have silenced the original error + // so we'll print it first, and then print the stack addendum. + + console["error"](error); // Don't transform to our wrapper + // For a more detailed description of this block, see: + // https://github.com/facebook/react/pull/13384 + } + + var componentName = source ? getComponentName(source.type) : null; + var componentNameMessage = componentName + ? "The above error occurred in the <" + componentName + "> component:" + : "The above error occurred in one of your React components:"; + var errorBoundaryMessage; + var errorBoundaryName = getComponentName(boundary.type); + + if (errorBoundaryName) { + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + errorBoundaryName + "."); + } else { + errorBoundaryMessage = + "Consider adding an error boundary to your tree to customize error handling behavior.\n" + + "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; + } + + var combinedMessage = + componentNameMessage + + "\n" + + componentStack + + "\n\n" + + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + + console["error"](combinedMessage); // Don't transform to our wrapper + } else { + // In production, we print the error directly. + // This will include the message, the JS stack, and anything the browser wants to show. + // We pass the error object instead of custom message so that the browser displays the error natively. + console["error"](error); // Don't transform to our wrapper + } + } catch (e) { + // This method must not throw, or React internal state will get messed up. + // If console.error is overridden, or logCapturedError() shows a dialog that throws, + // we want to report this error outside of the normal stack as a last resort. + // https://github.com/facebook/react/issues/13188 + setTimeout(function() { + throw e; + }); + } +} + +var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + +function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. + + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". + + update.payload = { + element: null + }; + var error = errorInfo.value; + + update.callback = function() { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; + + return update; +} + +function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; + + update.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error$1); + }; + } + + var inst = fiber.stateNode; + + if (inst !== null && typeof inst.componentDidCatch === "function") { + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } + + if (typeof getDerivedStateFromError !== "function") { + // To preserve the preexisting retry behavior of error boundaries, + // we keep track of which ones already failed during this batch. + // This gets reset before we yield back to the browser. + // TODO: Warn in strict mode if getDerivedStateFromError is + // not defined. + markLegacyErrorBoundaryAsFailed(this); // Only log here if componentDidCatch is the only error boundary method defined + + logCapturedError(fiber, errorInfo); + } + + var error$1 = errorInfo.value; + var stack = errorInfo.stack; + this.componentDidCatch(error$1, { + componentStack: stack !== null ? stack : "" + }); + + { + if (typeof getDerivedStateFromError !== "function") { + // If componentDidCatch is the only error boundary method defined, + // then it needs to call setState to recover from errors. + // If no state update is scheduled then the boundary will swallow the error. + if (!includesSomeLane(fiber.lanes, SyncLane)) { + error( + "%s: Error boundaries should implement getDerivedStateFromError(). " + + "In that method, return a state update to display an error message or fallback UI.", + getComponentName(fiber.type) || "Unknown" + ); + } + } + } + }; + } else { + update.callback = function() { + markFailedErrorBoundaryForHotReloading(fiber); + }; + } + + return update; +} + +function attachPingListener(root, wakeable, lanes) { + // Attach a listener to the promise to "ping" the root and retry. But only if + // one does not already exist for the lanes we're currently rendering (which + // acts like a "thread ID" here). + var pingCache = root.pingCache; + var threadIDs; + + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap$1(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); } + } - case SuspenseComponent: { - popSuspenseContext(workInProgress); - - var _effectTag2 = workInProgress.effectTag; + if (!threadIDs.has(lanes)) { + // Memoize using the thread ID to prevent redundant listeners. + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); + wakeable.then(ping, ping); + } +} - if (_effectTag2 & ShouldCapture) { - workInProgress.effectTag = (_effectTag2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; // Its effect list is no longer valid. - return workInProgress; - } + sourceFiber.firstEffect = sourceFiber.lastEffect = null; - return null; - } + if ( + value !== null && + typeof value === "object" && + typeof value.then === "function" + ) { + // This is a wakeable. + var wakeable = value; - case SuspenseListComponent: { - popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. + if ((sourceFiber.mode & BlockingMode) === NoMode) { + // Reset the memoizedState to what it was before we attempted + // to render it. + var currentSource = sourceFiber.alternate; - return null; + if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; + sourceFiber.memoizedState = currentSource.memoizedState; + sourceFiber.lanes = currentSource.lanes; + } else { + sourceFiber.updateQueue = null; + sourceFiber.memoizedState = null; + } } - case HostPortal: - popHostContainer(workInProgress); - return null; + var hasInvisibleParentBoundary = hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ); // Schedule the nearest Suspense to re-render the timed out view. - case ContextProvider: - popProvider(workInProgress); - return null; + var _workInProgress = returnFiber; - default: - return null; - } -} + do { + if ( + _workInProgress.tag === SuspenseComponent && + shouldCaptureSuspense(_workInProgress, hasInvisibleParentBoundary) + ) { + // Found the nearest boundary. + // Stash the promise on the boundary fiber. If the boundary times out, we'll + // attach another listener to flip the boundary back to its normal state. + var wakeables = _workInProgress.updateQueue; -function unwindInterruptedWork(interruptedWork) { - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; + if (wakeables === null) { + var updateQueue = new Set(); + updateQueue.add(wakeable); + _workInProgress.updateQueue = updateQueue; + } else { + wakeables.add(wakeable); + } // If the boundary is outside of blocking mode, we should *not* + // suspend the commit. Pretend as if the suspended component rendered + // null and keep rendering. In the commit phase, we'll schedule a + // subsequent synchronous update to re-render the Suspense. + // + // Note: It doesn't matter whether the component that suspended was + // inside a blocking mode tree. If the Suspense is outside of it, we + // should *not* suspend the commit. - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); - } + if ((_workInProgress.mode & BlockingMode) === NoMode) { + _workInProgress.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + // But we shouldn't call any lifecycle methods or callbacks. Remove + // all lifecycle effect tags. - break; - } + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); - case HostRoot: { - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - break; - } + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; - case HostComponent: { - popHostContext(interruptedWork); - break; - } + if (currentSourceFiber === null) { + // This is a new mount. Change the tag so it's not mistaken for a + // completed class component. For example, we should not call + // componentWillUnmount if it is deleted. + sourceFiber.tag = IncompleteClassComponent; + } else { + // When we try rendering again, we should not reuse the current fiber, + // since it's known to be in an inconsistent state. Use a force update to + // prevent a bail out. + var update = createUpdate(NoTimestamp, SyncLane); + update.tag = ForceUpdate; + enqueueUpdate(sourceFiber, update); + } + } // The source fiber did not complete. Mark it with Sync priority to + // indicate that it still has pending work. - case HostPortal: - popHostContainer(interruptedWork); - break; + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); // Exit without suspending. - case SuspenseComponent: - popSuspenseContext(interruptedWork); - break; + return; + } // Confirmed that the boundary is in a concurrent mode tree. Continue + // with the normal suspend path. + // + // After this we'll use a set of heuristics to determine whether this + // render pass will run to completion or restart or "suspend" the commit. + // The actual logic for this is spread out in different places. + // + // This first principle is that if we're going to suspend when we complete + // a root, then we should also restart if we get an update or ping that + // might unsuspend it, and vice versa. The only reason to suspend is + // because you think you might want to restart before committing. However, + // it doesn't make sense to restart only while in the period we're suspended. + // + // Restarting too aggressively is also not good because it starves out any + // intermediate loading state. So we use heuristics to determine when. + // Suspense Heuristics + // + // If nothing threw a Promise or all the same fallbacks are already showing, + // then don't suspend/restart. + // + // If this is an initial render of a new tree of Suspense boundaries and + // those trigger a fallback, then don't suspend/restart. We want to ensure + // that we can show the initial loading state as quickly as possible. + // + // If we hit a "Delayed" case, such as when we'd switch from content back into + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. + // + // If we're already showing a fallback and it gets "retried", allowing us to show + // another level, but there's still an inner boundary that would show a fallback, + // then we suspend/restart for 500ms since the last time we showed a fallback + // anywhere in the tree. This effectively throttles progressive loading into a + // consistent train of commits. This also gives us an opportunity to restart to + // get to the completed state slightly earlier. + // + // If there's ambiguity due to batching it's resolved in preference of: + // 1) "delayed", 2) "initial render", 3) "retry". + // + // We want to ensure that a "busy" state doesn't get force committed. We want to + // ensure that new initial loading states can commit as soon as possible. - case SuspenseListComponent: - popSuspenseContext(interruptedWork); - break; + attachPingListener(root, wakeable, rootRenderLanes); + _workInProgress.flags |= ShouldCapture; + _workInProgress.lanes = rootRenderLanes; + return; + } // This boundary already captured during this render. Continue to the next + // boundary. - case ContextProvider: - popProvider(interruptedWork); - break; - } -} + _workInProgress = _workInProgress.return; + } while (_workInProgress !== null); // No boundary was found. Fallthrough to error mode. + // TODO: Use invariant so the message is stripped in prod? -function createCapturedValue(value, source) { - // If the value is an error, call this function immediately after it is thrown - // so the stack is accurate. - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source) - }; -} + value = new Error( + (getComponentName(sourceFiber.type) || "A React component") + + " suspended while rendering, but no fallback UI was specified.\n" + + "\n" + + "Add a component higher in the tree to " + + "provide a loading indicator or placeholder to display." + ); + } // We didn't find a boundary that could handle this type of exception. Start + // over and traverse parent path again, this time treating the exception + // as an error. -// Module provided by RN: + renderDidError(); + value = createCapturedValue(value, sourceFiber); + var workInProgress = returnFiber; -if ( - !( - typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog === - "function" - ) -) { - throw Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + do { + switch (workInProgress.tag) { + case HostRoot: { + var _errorInfo = value; + workInProgress.flags |= ShouldCapture; + var lane = pickArbitraryLane(rootRenderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); -function showErrorDialog(capturedError) { - return ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ); -} + var _update = createRootErrorUpdate(workInProgress, _errorInfo, lane); -function logCapturedError(capturedError) { - var logError = showErrorDialog(capturedError); // Allow injected showErrorDialog() to prevent default console.error logging. - // This enables renderers like ReactNative to better manage redbox behavior. + enqueueCapturedUpdate(workInProgress, _update); + return; + } - if (logError === false) { - return; - } + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; - var error = capturedError.error; + if ( + (workInProgress.flags & DidCapture) === NoFlags && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; - { - var componentName = capturedError.componentName, - componentStack = capturedError.componentStack, - errorBoundaryName = capturedError.errorBoundaryName, - errorBoundaryFound = capturedError.errorBoundaryFound, - willRetry = capturedError.willRetry; // Browsers support silencing uncaught errors by calling - // `preventDefault()` in window `error` handler. - // We record this information as an expando on the error. - - if (error != null && error._suppressLogging) { - if (errorBoundaryFound && willRetry) { - // The error is recoverable and was silenced. - // Ignore it and don't print the stack addendum. - // This is handy for testing error boundaries without noise. - return; - } // The error is fatal. Since the silencing might have - // been accidental, we'll surface it anyway. - // However, the browser would have silenced the original error - // so we'll print it first, and then print the stack addendum. + var _lane = pickArbitraryLane(rootRenderLanes); - console["error"](error); // Don't transform to our wrapper - // For a more detailed description of this block, see: - // https://github.com/facebook/react/pull/13384 - } + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state - var componentNameMessage = componentName - ? "The above error occurred in the <" + componentName + "> component:" - : "The above error occurred in one of your React components:"; - var errorBoundaryMessage; // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow. + var _update2 = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); - if (errorBoundaryFound && errorBoundaryName) { - if (willRetry) { - errorBoundaryMessage = - "React will try to recreate this component tree from scratch " + - ("using the error boundary you provided, " + errorBoundaryName + "."); - } else { - errorBoundaryMessage = - "This error was initially handled by the error boundary " + - errorBoundaryName + - ".\n" + - "Recreating the tree from scratch failed so React will unmount the tree."; - } - } else { - errorBoundaryMessage = - "Consider adding an error boundary to your tree to customize error handling behavior.\n" + - "Visit https://fb.me/react-error-boundaries to learn more about error boundaries."; + enqueueCapturedUpdate(workInProgress, _update2); + return; + } + + break; } - var combinedMessage = - "" + - componentNameMessage + - componentStack + - "\n\n" + - ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. - // We don't include the original error message and JS stack because the browser - // has already printed it. Even if the application swallows the error, it is still - // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. - - console["error"](combinedMessage); // Don't transform to our wrapper - } + workInProgress = workInProgress.return; + } while (workInProgress !== null); } var didWarnAboutUndefinedSnapshotBeforeUpdate = null; @@ -15191,54 +16033,14 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; } var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source; - var stack = errorInfo.stack; - - if (stack === null && source !== null) { - stack = getStackByFiberInDevAndProd(source); - } - - var capturedError = { - componentName: source !== null ? getComponentName(source.type) : null, - componentStack: stack !== null ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: false, - willRetry: false - }; - - if (boundary !== null && boundary.tag === ClassComponent) { - capturedError.errorBoundary = boundary.stateNode; - capturedError.errorBoundaryName = getComponentName(boundary.type); - capturedError.errorBoundaryFound = true; - capturedError.willRetry = true; - } - - try { - logCapturedError(capturedError); - } catch (e) { - // This method must not throw, or React internal state will get messed up. - // If console.error is overridden, or logCapturedError() shows a dialog that throws, - // we want to report this error outside of the normal stack as a last resort. - // https://github.com/facebook/react/issues/13188 - setTimeout(function() { - throw e; - }); - } -} var callComponentWillUnmountWithTimer = function(current, instance) { - startPhaseTimer(current, "componentWillUnmount"); instance.props = current.memoizedProps; instance.state = current.memoizedState; { instance.componentWillUnmount(); } - - stopPhaseTimer(); }; // Capture errors so they don't interrupt unmounting. function safelyCallComponentWillUnmount(current, instance) { @@ -15264,7 +16066,9 @@ function safelyDetachRef(current) { if (ref !== null) { if (typeof ref === "function") { { - invokeGuardedCallback(null, ref, null, null); + { + invokeGuardedCallback(null, ref, null, null); + } if (hasCaughtError()) { var refError = clearCaughtError(); @@ -15292,17 +16096,15 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { return; } case ClassComponent: { - if (finishedWork.effectTag & Snapshot) { + if (finishedWork.flags & Snapshot) { if (current !== null) { var prevProps = current.memoizedProps; var prevState = current.memoizedState; - startPhaseTimer(finishedWork, "getSnapshotBeforeUpdate"); var instance = finishedWork.stateNode; // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -15358,14 +16160,16 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } instance.__reactInternalSnapshotBeforeUpdate = snapshot; - stopPhaseTimer(); } } return; } - case HostRoot: + case HostRoot: { + return; + } + case HostComponent: case HostText: case HostPortal: @@ -15442,16 +16246,15 @@ function commitHookEffectListMount(tag, finishedWork) { " }\n" + " fetchData();\n" + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + - "Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching"; + "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; } else { addendum = " You returned: " + destroy; } error( "An effect function must not return anything besides a function, " + - "which is used for clean-up.%s%s", - addendum, - getStackByFiberInDevAndProd(finishedWork) + "which is used for clean-up.%s", + addendum ); } } @@ -15462,38 +16265,34 @@ function commitHookEffectListMount(tag, finishedWork) { } } -function commitPassiveHookEffects(finishedWork) { - if ((finishedWork.effectTag & Passive) !== NoEffect) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: - case Block: { - // TODO (#17945) We should call all passive destroy functions (for all fibers) - // before calling any create functions. The current approach only serializes - // these for a single fiber. - { - commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork); - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); - } +function schedulePassiveEffects(finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - break; + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + next = _effect.next, + tag = _effect.tag; + + if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) { + enqueuePendingPassiveHookEffectUnmount(finishedWork, effect); + enqueuePendingPassiveHookEffectMount(finishedWork, effect); } - } + + effect = next; + } while (effect !== firstEffect); } } -function commitLifeCycles( - finishedRoot, - current, - finishedWork, - committedExpirationTime -) { +function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // At this point layout effects have already been destroyed (during mutation phase). // This is done to prevent sibling component effects from interfering with each other, // e.g. a destroy function in one component should never override a ref set @@ -15502,18 +16301,18 @@ function commitLifeCycles( commitHookEffectListMount(Layout | HasEffect, finishedWork); } + schedulePassiveEffects(finishedWork); return; } case ClassComponent: { var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update) { + if (finishedWork.flags & Update) { if (current === null) { - startPhaseTimer(finishedWork, "componentDidMount"); // We could update instance props and state here, + // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. - { if ( finishedWork.type === finishedWork.elementType && @@ -15546,15 +16345,12 @@ function commitLifeCycles( { instance.componentDidMount(); } - - stopPhaseTimer(); } else { var prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps); - var prevState = current.memoizedState; - startPhaseTimer(finishedWork, "componentDidUpdate"); // We could update instance props and state here, + var prevState = current.memoizedState; // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -15594,10 +16390,9 @@ function commitLifeCycles( instance.__reactInternalSnapshotBeforeUpdate ); } - - stopPhaseTimer(); } - } + } // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. var updateQueue = finishedWork.updateQueue; @@ -15640,6 +16435,8 @@ function commitLifeCycles( } case HostRoot: { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. var _updateQueue = finishedWork.updateQueue; if (_updateQueue !== null) { @@ -15669,7 +16466,7 @@ function commitLifeCycles( // These effects should only be committed when components are first mounted, // aka when there is no current/alternate. - if (current === null && finishedWork.effectTag & Update) { + if (current === null && finishedWork.flags & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; commitMount(); @@ -15722,6 +16519,8 @@ function commitLifeCycles( case IncompleteClassComponent: case FundamentalComponent: case ScopeComponent: + case OffscreenComponent: + case LegacyHiddenComponent: return; } @@ -15749,15 +16548,16 @@ function commitAttachRef(finishedWork) { } // Moved outside to ensure DCE works with this flag if (typeof ref === "function") { - ref(instanceToUse); + { + ref(instanceToUse); + } } else { { if (!ref.hasOwnProperty("current")) { error( "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().%s", - getComponentName(finishedWork.type), - getStackByFiberInDevAndProd(finishedWork) + "Use either a ref-setter function or React.createRef().", + getComponentName(finishedWork.type) ); } } @@ -15772,7 +16572,9 @@ function commitDetachRef(current) { if (currentRef !== null) { if (typeof currentRef === "function") { - currentRef(null); + { + currentRef(null); + } } else { currentRef.current = null; } @@ -15788,8 +16590,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { var updateQueue = current.updateQueue; if (updateQueue !== null) { @@ -15797,42 +16598,25 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { if (lastEffect !== null) { var firstEffect = lastEffect.next; + var effect = firstEffect; - { - // When the owner fiber is deleted, the destroy function of a passive - // effect hook is called during the synchronous commit phase. This is - // a concession to implementation complexity. Calling it in the - // passive effect phase (like they usually are, when dependencies - // change during an update) would require either traversing the - // children of the deleted fiber again, or including unmount effects - // as part of the fiber effect list. - // - // Because this is during the sync commit phase, we need to change - // the priority. - // - // TODO: Reconsider this implementation trade off. - var priorityLevel = - renderPriorityLevel > NormalPriority - ? NormalPriority - : renderPriorityLevel; - runWithPriority(priorityLevel, function() { - var effect = firstEffect; - - do { - var _effect3 = effect, - _destroy = _effect3.destroy, - _tag = _effect3.tag; - - if (_destroy !== undefined) { - { - safelyCallDestroy(current, _destroy); - } + do { + var _effect2 = effect, + destroy = _effect2.destroy, + tag = _effect2.tag; + + if (destroy !== undefined) { + if ((tag & Passive$1) !== NoFlags$1) { + enqueuePendingPassiveHookEffectUnmount(current, effect); + } else { + { + safelyCallDestroy(current, destroy); } + } + } - effect = effect.next; - } while (effect !== firstEffect); - }); - } + effect = effect.next; + } while (effect !== firstEffect); } } @@ -15889,7 +16673,7 @@ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) { var node = root; while (true) { - commitUnmount(finishedRoot, node, renderPriorityLevel); // Visit children because they may contain more composite or host nodes. + commitUnmount(finishedRoot, node); // Visit children because they may contain more composite or host nodes. // Skip portals because commitUnmount() currently visits them recursively. if ( @@ -15902,508 +16686,223 @@ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) { continue; } - if (node === root) { - return; - } - - while (node.sibling === null) { - if (node.return === null || node.return === root) { - return; - } - - node = node.return; - } - - node.sibling.return = node.return; - node = node.sibling; - } -} - -function detachFiber(current) { - var alternate = current.alternate; // Cut off the return pointers to disconnect it from the tree. Ideally, we - // should clear the child pointer of the parent alternate to let this - // get GC:ed but we don't know which for sure which parent is the current - // one so we'll settle for GC:ing the subtree of this child. This child - // itself will be GC:ed when the parent updates the next time. - - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - - if (alternate !== null) { - detachFiber(alternate); - } -} - -function emptyPortalContainer(current) { - var portal = current.stateNode; - var containerInfo = portal.containerInfo; - var emptyChildSet = createContainerChildSet(containerInfo); -} - -function commitContainer(finishedWork) { - switch (finishedWork.tag) { - case ClassComponent: - case HostComponent: - case HostText: - case FundamentalComponent: { - return; - } - - case HostRoot: - case HostPortal: { - var portalOrRoot = finishedWork.stateNode; - var containerInfo = portalOrRoot.containerInfo, - pendingChildren = portalOrRoot.pendingChildren; - return; - } - } - - { - throw Error( - "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." - ); - } -} - -function commitDeletion(finishedRoot, current, renderPriorityLevel) { - { - // Detach refs and call componentWillUnmount() on the whole subtree. - commitNestedUnmounts(finishedRoot, current, renderPriorityLevel); - } - - detachFiber(current); -} - -function commitWork(current, finishedWork) { - { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case MemoComponent: - case SimpleMemoComponent: - case Block: { - // Layout effects are destroyed during the mutation phase so that all - // destroy functions for all fibers are called before any create functions. - // This prevents sibling component effects from interfering with each other, - // e.g. a destroy function in one component should never override a ref set - // by a create function in another component during the same commit. - { - commitHookEffectListUnmount(Layout | HasEffect, finishedWork); - } - - return; - } - - case Profiler: { - return; - } - - case SuspenseComponent: { - commitSuspenseComponent(finishedWork); - attachSuspenseRetryListeners(finishedWork); - return; - } - - case SuspenseListComponent: { - attachSuspenseRetryListeners(finishedWork); - return; - } - } - - commitContainer(finishedWork); - return; - } -} - -function commitSuspenseComponent(finishedWork) { - var newState = finishedWork.memoizedState; - var primaryChildParent = finishedWork; - - if (newState === null); - else { - primaryChildParent = finishedWork.child; - markCommitTimeOfFallback(); - } -} - -function attachSuspenseRetryListeners(finishedWork) { - // If this boundary just timed out, then it will have a set of thenables. - // For each thenable, attach a listener so that when it resolves, React - // attempts to re-render the boundary in the primary (pre-timeout) state. - var thenables = finishedWork.updateQueue; - - if (thenables !== null) { - finishedWork.updateQueue = null; - var retryCache = finishedWork.stateNode; - - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); - } - - thenables.forEach(function(thenable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); - - if (!retryCache.has(thenable)) { - { - if (thenable.__reactDoNotTraceInteractions !== true) { - retry = tracing.unstable_wrap(retry); - } - } - - retryCache.add(thenable); - thenable.then(retry, retry); - } - }); - } -} - -var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; - -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - var update = createUpdate(expirationTime, null); // Unmount the root by rendering null. - - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". - - update.payload = { - element: null - }; - var error = errorInfo.value; - - update.callback = function() { - onUncaughtError(error); - logError(fiber, errorInfo); - }; - - return update; -} - -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - var update = createUpdate(expirationTime, null); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; - - update.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error$1); - }; - } - - var inst = fiber.stateNode; - - if (inst !== null && typeof inst.componentDidCatch === "function") { - update.callback = function callback() { - { - markFailedErrorBoundaryForHotReloading(fiber); - } - - if (typeof getDerivedStateFromError !== "function") { - // To preserve the preexisting retry behavior of error boundaries, - // we keep track of which ones already failed during this batch. - // This gets reset before we yield back to the browser. - // TODO: Warn in strict mode if getDerivedStateFromError is - // not defined. - markLegacyErrorBoundaryAsFailed(this); // Only log here if componentDidCatch is the only error boundary method defined - - logError(fiber, errorInfo); + if (node === root) { + return; + } + + while (node.sibling === null) { + if (node.return === null || node.return === root) { + return; } - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + node = node.return; + } - { - if (typeof getDerivedStateFromError !== "function") { - // If componentDidCatch is the only error boundary method defined, - // then it needs to call setState to recover from errors. - // If no state update is scheduled then the boundary will swallow the error. - if (fiber.expirationTime !== Sync) { - error( - "%s: Error boundaries should implement getDerivedStateFromError(). " + - "In that method, return a state update to display an error message or fallback UI.", - getComponentName(fiber.type) || "Unknown" - ); - } - } - } - }; - } else { - update.callback = function() { - markFailedErrorBoundaryForHotReloading(fiber); - }; + node.sibling.return = node.return; + node = node.sibling; } +} - return update; +function detachFiberMutation(fiber) { + // Cut off the return pointers to disconnect it from the tree. Ideally, we + // should clear the child pointer of the parent alternate to let this + // get GC:ed but we don't know which for sure which parent is the current + // one so we'll settle for GC:ing the subtree of this child. This child + // itself will be GC:ed when the parent updates the next time. + // Note: we cannot null out sibling here, otherwise it can cause issues + // with findDOMNode and how it requires the sibling field to carry out + // traversal in a later effect. See PR #16820. We now clear the sibling + // field after effects, see: detachFiberAfterEffects. + // + // Don't disconnect stateNode now; it will be detached in detachFiberAfterEffects. + // It may be required if the current component is an error boundary, + // and one of its descendants throws while unmounting a passive effect. + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; + + { + fiber._debugOwner = null; + } } -function attachPingListener(root, renderExpirationTime, thenable) { - // Attach a listener to the promise to "ping" the root and retry. But - // only if one does not already exist for the current render expiration - // time (which acts like a "thread ID" here). - var pingCache = root.pingCache; - var threadIDs; +function emptyPortalContainer(current) { + var portal = current.stateNode; + var containerInfo = portal.containerInfo; + var emptyChildSet = createContainerChildSet(containerInfo); +} - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } else { - threadIDs = pingCache.get(thenable); +function commitContainer(finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: + case HostComponent: + case HostText: + case FundamentalComponent: { + return; + } - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); + case HostRoot: + case HostPortal: { + var portalOrRoot = finishedWork.stateNode; + var containerInfo = portalOrRoot.containerInfo, + pendingChildren = portalOrRoot.pendingChildren; + return; } } - if (!threadIDs.has(renderExpirationTime)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(renderExpirationTime); - var ping = pingSuspendedRoot.bind( - null, - root, - thenable, - renderExpirationTime + { + throw Error( + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); - thenable.then(ping, ping); } } -function throwException( - root, - returnFiber, - sourceFiber, - value, - renderExpirationTime -) { - // The source fiber did not complete. - sourceFiber.effectTag |= Incomplete; // Its effect list is no longer valid. +function commitDeletion(finishedRoot, current, renderPriorityLevel) { + { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitNestedUnmounts(finishedRoot, current); + } - sourceFiber.firstEffect = sourceFiber.lastEffect = null; + var alternate = current.alternate; + detachFiberMutation(current); - if ( - value !== null && - typeof value === "object" && - typeof value.then === "function" - ) { - // This is a thenable. - var thenable = value; + if (alternate !== null) { + detachFiberMutation(alternate); + } +} - if ((sourceFiber.mode & BlockingMode) === NoMode) { - // Reset the memoizedState to what it was before we attempted - // to render it. - var currentSource = sourceFiber.alternate; +function commitWork(current, finishedWork) { + { + switch (finishedWork.tag) { + case FunctionComponent: + case ForwardRef: + case MemoComponent: + case SimpleMemoComponent: { + // Layout effects are destroyed during the mutation phase so that all + // destroy functions for all fibers are called before any create functions. + // This prevents sibling component effects from interfering with each other, + // e.g. a destroy function in one component should never override a ref set + // by a create function in another component during the same commit. + { + commitHookEffectListUnmount(Layout | HasEffect, finishedWork); + } - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.expirationTime = currentSource.expirationTime; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; + return; } - } - - var hasInvisibleParentBoundary = hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ); // Schedule the nearest Suspense to re-render the timed out view. - - var _workInProgress = returnFiber; - - do { - if ( - _workInProgress.tag === SuspenseComponent && - shouldCaptureSuspense(_workInProgress, hasInvisibleParentBoundary) - ) { - // Found the nearest boundary. - // Stash the promise on the boundary fiber. If the boundary times out, we'll - // attach another listener to flip the boundary back to its normal state. - var thenables = _workInProgress.updateQueue; - - if (thenables === null) { - var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else { - thenables.add(thenable); - } // If the boundary is outside of blocking mode, we should *not* - // suspend the commit. Pretend as if the suspended component rendered - // null and keep rendering. In the commit phase, we'll schedule a - // subsequent synchronous update to re-render the Suspense. - // - // Note: It doesn't matter whether the component that suspended was - // inside a blocking mode tree. If the Suspense is outside of it, we - // should *not* suspend the commit. - - if ((_workInProgress.mode & BlockingMode) === NoMode) { - _workInProgress.effectTag |= DidCapture; // We're going to commit this fiber even though it didn't complete. - // But we shouldn't call any lifecycle methods or callbacks. Remove - // all lifecycle effect tags. - - sourceFiber.effectTag &= ~(LifecycleEffectMask | Incomplete); - - if (sourceFiber.tag === ClassComponent) { - var currentSourceFiber = sourceFiber.alternate; - - if (currentSourceFiber === null) { - // This is a new mount. Change the tag so it's not mistaken for a - // completed class component. For example, we should not call - // componentWillUnmount if it is deleted. - sourceFiber.tag = IncompleteClassComponent; - } else { - // When we try rendering again, we should not reuse the current fiber, - // since it's known to be in an inconsistent state. Use a force update to - // prevent a bail out. - var update = createUpdate(Sync, null); - update.tag = ForceUpdate; - enqueueUpdate(sourceFiber, update); - } - } // The source fiber did not complete. Mark it with Sync priority to - // indicate that it still has pending work. - sourceFiber.expirationTime = Sync; // Exit without suspending. + case Profiler: { + return; + } - return; - } // Confirmed that the boundary is in a concurrent mode tree. Continue - // with the normal suspend path. - // - // After this we'll use a set of heuristics to determine whether this - // render pass will run to completion or restart or "suspend" the commit. - // The actual logic for this is spread out in different places. - // - // This first principle is that if we're going to suspend when we complete - // a root, then we should also restart if we get an update or ping that - // might unsuspend it, and vice versa. The only reason to suspend is - // because you think you might want to restart before committing. However, - // it doesn't make sense to restart only while in the period we're suspended. - // - // Restarting too aggressively is also not good because it starves out any - // intermediate loading state. So we use heuristics to determine when. - // Suspense Heuristics - // - // If nothing threw a Promise or all the same fallbacks are already showing, - // then don't suspend/restart. - // - // If this is an initial render of a new tree of Suspense boundaries and - // those trigger a fallback, then don't suspend/restart. We want to ensure - // that we can show the initial loading state as quickly as possible. - // - // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. SuspenseConfig applies to - // this case. If none is defined, JND is used instead. - // - // If we're already showing a fallback and it gets "retried", allowing us to show - // another level, but there's still an inner boundary that would show a fallback, - // then we suspend/restart for 500ms since the last time we showed a fallback - // anywhere in the tree. This effectively throttles progressive loading into a - // consistent train of commits. This also gives us an opportunity to restart to - // get to the completed state slightly earlier. - // - // If there's ambiguity due to batching it's resolved in preference of: - // 1) "delayed", 2) "initial render", 3) "retry". - // - // We want to ensure that a "busy" state doesn't get force committed. We want to - // ensure that new initial loading states can commit as soon as possible. + case SuspenseComponent: { + commitSuspenseComponent(finishedWork); + attachSuspenseRetryListeners(finishedWork); + return; + } - attachPingListener(root, renderExpirationTime, thenable); - _workInProgress.effectTag |= ShouldCapture; - _workInProgress.expirationTime = renderExpirationTime; + case SuspenseListComponent: { + attachSuspenseRetryListeners(finishedWork); return; - } // This boundary already captured during this render. Continue to the next - // boundary. + } - _workInProgress = _workInProgress.return; - } while (_workInProgress !== null); // No boundary was found. Fallthrough to error mode. - // TODO: Use invariant so the message is stripped in prod? + case HostRoot: { + break; + } - value = new Error( - (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n" + - "\n" + - "Add a component higher in the tree to " + - "provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) - ); - } // We didn't find a boundary that could handle this type of exception. Start - // over and traverse parent path again, this time treating the exception - // as an error. + case OffscreenComponent: + case LegacyHiddenComponent: { + return; + } + } - renderDidError(); - value = createCapturedValue(value, sourceFiber); - var workInProgress = returnFiber; + commitContainer(finishedWork); + return; + } +} - do { - switch (workInProgress.tag) { - case HostRoot: { - var _errorInfo = value; - workInProgress.effectTag |= ShouldCapture; - workInProgress.expirationTime = renderExpirationTime; +function commitSuspenseComponent(finishedWork) { + var newState = finishedWork.memoizedState; - var _update = createRootErrorUpdate( - workInProgress, - _errorInfo, - renderExpirationTime - ); + if (newState !== null) { + markCommitTimeOfFallback(); + } +} - enqueueCapturedUpdate(workInProgress, _update); - return; - } +function attachSuspenseRetryListeners(finishedWork) { + // If this boundary just timed out, then it will have a set of wakeables. + // For each wakeable, attach a listener so that when it resolves, React + // attempts to re-render the boundary in the primary (pre-timeout) state. + var wakeables = finishedWork.updateQueue; - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; + if (wakeables !== null) { + finishedWork.updateQueue = null; + var retryCache = finishedWork.stateNode; - if ( - (workInProgress.effectTag & DidCapture) === NoEffect && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.effectTag |= ShouldCapture; - workInProgress.expirationTime = renderExpirationTime; // Schedule the error boundary to re-render using updated state + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } - var _update2 = createClassErrorUpdate( - workInProgress, - errorInfo, - renderExpirationTime - ); + wakeables.forEach(function(wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); - enqueueCapturedUpdate(workInProgress, _update2); - return; + if (!retryCache.has(wakeable)) { + { + if (wakeable.__reactDoNotTraceInteractions !== true) { + retry = tracing.unstable_wrap(retry); + } } - break; + retryCache.add(wakeable); + wakeable.then(retry, retry); + } + }); + } +} // This function detects when a Suspense boundary goes from visible to hidden. +// It returns false if the boundary is already hidden. +// TODO: Use an effect tag. + +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + if (current !== null) { + var oldState = current.memoizedState; + + if (oldState === null || oldState.dehydrated !== null) { + var newState = finishedWork.memoizedState; + return newState !== null && newState.dehydrated === null; } + } - workInProgress = workInProgress.return; - } while (workInProgress !== null); + return false; +} + +var COMPONENT_TYPE = 0; +var HAS_PSEUDO_CLASS_TYPE = 1; +var ROLE_TYPE = 2; +var TEST_NAME_TYPE = 3; +var TEXT_TYPE = 4; + +if (typeof Symbol === "function" && Symbol.for) { + var symbolFor$1 = Symbol.for; + COMPONENT_TYPE = symbolFor$1("selector.component"); + HAS_PSEUDO_CLASS_TYPE = symbolFor$1("selector.has_pseudo_class"); + ROLE_TYPE = symbolFor$1("selector.role"); + TEST_NAME_TYPE = symbolFor$1("selector.test_id"); + TEXT_TYPE = symbolFor$1("selector.text"); } var ceil = Math.ceil; -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, IsSomeRendererActing = ReactSharedInternals.IsSomeRendererActing; var NoContext = - /* */ + /* */ 0; var BatchedContext = /* */ @@ -16420,2608 +16919,3024 @@ var RenderContext = var CommitContext = /* */ 32; +var RetryAfterError = + /* */ + 64; var RootIncomplete = 0; var RootFatalErrored = 1; var RootErrored = 2; var RootSuspended = 3; var RootSuspendedWithDelay = 4; -var RootCompleted = 5; -// Describes where we are in the React execution stack +var RootCompleted = 5; // Describes where we are in the React execution stack + var executionContext = NoContext; // The root we're working on -var workInProgressRoot = null; // The fiber we're working on +var workInProgressRoot = null; // The fiber we're working on + +var workInProgress = null; // The lanes we're rendering + +var workInProgressRootRenderLanes = NoLanes; // Stack that allows components to change the render lanes for its subtree +// This is a superset of the lanes we started working on at the root. The only +// case where it's different from `workInProgressRootRenderLanes` is when we +// enter a subtree that is hidden and needs to be unhidden: Suspense and +// Offscreen component. +// +// Most things in the work loop should deal with workInProgressRootRenderLanes. +// Most things in begin/complete phases should deal with subtreeRenderLanes. + +var subtreeRenderLanes = NoLanes; +var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. + +var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown + +var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's +// slightly different than `renderLanes` because `renderLanes` can change as you +// enter and exit an Offscreen tree. This value is the combination of all render +// lanes for the entire render phase. + +var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only +// includes unprocessed updates, not work in bailed out children. + +var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. + +var workInProgressRootUpdatedLanes = NoLanes; // Lanes that were pinged (in an interleaved event) during this render. + +var workInProgressRootPingedLanes = NoLanes; +var mostRecentlyUpdatedRoot = null; // The most recent time we committed a fallback. This lets us ensure a train +// model where we don't commit new loading states in too quick succession. + +var globalMostRecentFallbackTime = 0; +var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering +// more and prefer CPU suspense heuristics instead. + +var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU +// suspense heuristics and opt out of rendering more content. + +var RENDER_TIMEOUT_MS = 500; + +function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; +} + +function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; +} +var nextEffect = null; +var hasUncaughtError = false; +var firstUncaughtError = null; +var legacyErrorBoundariesThatAlreadyFailed = null; +var rootDoesHavePassiveEffects = false; +var rootWithPendingPassiveEffects = null; +var pendingPassiveEffectsRenderPriority = NoPriority$1; +var pendingPassiveEffectsLanes = NoLanes; +var pendingPassiveHookEffectsMount = []; +var pendingPassiveHookEffectsUnmount = []; +var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates + +var NESTED_UPDATE_LIMIT = 50; +var nestedUpdateCount = 0; +var rootWithNestedUpdates = null; +var NESTED_PASSIVE_UPDATE_LIMIT = 50; +var nestedPassiveUpdateCount = 0; // Marks the need to reschedule pending interactions at these lanes +// during the commit phase. This enables them to be traced across components +// that spawn new work during render. E.g. hidden boundaries, suspended SSR +// hydration or SuspenseList. +// TODO: Can use a bitmask instead of an array + +var spawnedWorkDuringRender = null; // If two updates are scheduled within the same event, we should treat their +// event times as simultaneous, even if the actual clock time has advanced +// between the first and second call. + +var currentEventTime = NoTimestamp; +var currentEventWipLanes = NoLanes; +var currentEventPendingLanes = NoLanes; // Dev only flag that tracks if passive effects are currently being flushed. +// We warn about state updates for unmounted components differently in this case. + +var isFlushingPassiveEffects = false; +var focusedInstanceHandle = null; +var shouldFireAfterActiveInstanceBlur = false; +function getWorkInProgressRoot() { + return workInProgressRoot; +} +function requestEventTime() { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // We're inside React, so it's fine to read the actual time. + return now(); + } // We're not inside React, so we may be in the middle of a browser event. + + if (currentEventTime !== NoTimestamp) { + // Use the same start time for all updates until we enter React again. + return currentEventTime; + } // This is the first update since React yielded. Compute a new start time. + + currentEventTime = now(); + return currentEventTime; +} +function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; + + if ((mode & BlockingMode) === NoMode) { + return SyncLane; + } else if ((mode & ConcurrentMode) === NoMode) { + return getCurrentPriorityLevel() === ImmediatePriority$1 + ? SyncLane + : SyncBatchedLane; + } // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the inputs + // to the algorithm must be the same. For example, we use the `renderLanes` + // to avoid choosing a lane that is already in the middle of rendering. + // + // However, the "included" lanes could be mutated in between updates in the + // same event, like if you perform an update inside `flushSync`. Or any other + // code path that might call `prepareFreshStack`. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is over. + // Our heuristic for that is whenever we enter a concurrent work loop. + // + // We'll do the same for `currentEventPendingLanes` below. + + if (currentEventWipLanes === NoLanes) { + currentEventWipLanes = workInProgressRootIncludedLanes; + } + + var isTransition = requestCurrentTransition() !== NoTransition; + + if (isTransition) { + if (currentEventPendingLanes !== NoLanes) { + currentEventPendingLanes = + mostRecentlyUpdatedRoot !== null + ? mostRecentlyUpdatedRoot.pendingLanes + : NoLanes; + } + + return findTransitionLane(currentEventWipLanes, currentEventPendingLanes); + } // TODO: Remove this dependency on the Scheduler priority. + // To do that, we're replacing it with an update lane priority. + + var schedulerPriority = getCurrentPriorityLevel(); // The old behavior was using the priority level of the Scheduler. + // This couples React to the Scheduler internals, so we're replacing it + // with the currentUpdateLanePriority above. As an example of how this + // could be problematic, if we're not inside `Scheduler.runWithPriority`, + // then we'll get the priority of the current running Scheduler task, + // which is probably not what we want. + + var lane; + + if ( + // TODO: Temporary. We're removing the concept of discrete updates. + (executionContext & DiscreteEventContext) !== NoContext && + schedulerPriority === UserBlockingPriority$1 + ) { + lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes); + } else { + var schedulerLanePriority = schedulerPriorityToLanePriority( + schedulerPriority + ); + + lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes); + } + + return lane; +} + +function requestRetryLane(fiber) { + // This is a fork of `requestUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + // Special cases + var mode = fiber.mode; + + if ((mode & BlockingMode) === NoMode) { + return SyncLane; + } else if ((mode & ConcurrentMode) === NoMode) { + return getCurrentPriorityLevel() === ImmediatePriority$1 + ? SyncLane + : SyncBatchedLane; + } // See `requestUpdateLane` for explanation of `currentEventWipLanes` + + if (currentEventWipLanes === NoLanes) { + currentEventWipLanes = workInProgressRootIncludedLanes; + } + + return findRetryLane(currentEventWipLanes); +} + +function scheduleUpdateOnFiber(fiber, lane, eventTime) { + checkForNestedUpdates(); + warnAboutRenderPhaseUpdatesInDEV(fiber); + var root = markUpdateLaneFromFiberToRoot(fiber, lane); + + if (root === null) { + warnAboutUpdateOnUnmountedFiberInDEV(fiber); + return null; + } // Mark that the root has a pending update. + + markRootUpdated(root, lane, eventTime); + + if (root === workInProgressRoot) { + // Received an update to a tree that's in the middle of rendering. Mark + // that there was an interleaved update work on this root. Unless the + // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render + // phase update. In that case, we don't treat render phase updates as if + // they were interleaved, for backwards compat reasons. + { + workInProgressRootUpdatedLanes = mergeLanes( + workInProgressRootUpdatedLanes, + lane + ); + } + + if (workInProgressRootExitStatus === RootSuspendedWithDelay) { + // The root already suspended with a delay, which means this render + // definitely won't finish. Since we have a new update, let's mark it as + // suspended now, right before marking the incoming update. This has the + // effect of interrupting the current render and switching to the update. + // TODO: Make sure this doesn't override pings that happen while we've + // already started rendering. + markRootSuspended$1(root, workInProgressRootRenderLanes); + } + } // TODO: requestUpdateLanePriority also reads the priority. Pass the + // priority as an argument to that function and this one. + + var priorityLevel = getCurrentPriorityLevel(); + + if (lane === SyncLane) { + if ( + // Check if we're inside unbatchedUpdates + (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering + (executionContext & (RenderContext | CommitContext)) === NoContext + ) { + // Register pending interactions on the root to avoid losing traced interaction data. + schedulePendingInteractions(root, lane); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed + // root inside of batchedUpdates should be synchronous, but layout updates + // should be deferred until the end of the batch. + + performSyncWorkOnRoot(root); + } else { + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, lane); + + if (executionContext === NoContext) { + // Flush the synchronous work now, unless we're already working or inside + // a batch. This is intentionally inside scheduleUpdateOnFiber instead of + // scheduleCallbackForFiber to preserve the ability to schedule a callback + // without immediately flushing it. We only do this for user-initiated + // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); + flushSyncCallbackQueue(); + } + } + } else { + // Schedule a discrete update but only if it's not Sync. + if ( + (executionContext & DiscreteEventContext) !== NoContext && // Only updates at user-blocking priority or greater are considered + // discrete, even inside a discrete event. + (priorityLevel === UserBlockingPriority$1 || + priorityLevel === ImmediatePriority$1) + ) { + // This is the result of a discrete event. Track the lowest priority + // discrete update per root so we can flush them early, if needed. + if (rootsWithPendingDiscreteUpdates === null) { + rootsWithPendingDiscreteUpdates = new Set([root]); + } else { + rootsWithPendingDiscreteUpdates.add(root); + } + } // Schedule other updates after in case the callback is sync. + + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, lane); + } // We use this when assigning a lane for a transition inside + // `requestUpdateLane`. We assume it's the same as the root being updated, + // since in the common case of a single root app it probably is. If it's not + // the same root, then it's not a huge deal, we just might batch more stuff + // together more than necessary. + + mostRecentlyUpdatedRoot = root; +} // This is split into a separate function so we can mark a fiber with pending +// work without treating it as a typical update that originates from an event; +// e.g. retrying a Suspense boundary isn't an update, but it does schedule work +// on a fiber. + +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); + } + + { + if ( + alternate === null && + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } // Walk the parent path to the root and update the child expiration time. + + var node = sourceFiber; + var parent = sourceFiber.return; + + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; + + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); + } else { + { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } + } + + node = parent; + parent = parent.return; + } + + if (node.tag === HostRoot) { + var root = node.stateNode; + return root; + } else { + return null; + } +} // Use this function to schedule a task for a root. There's only one task per +// root; if a task was already scheduled, we'll check to make sure the priority +// of the existing task is the same as the priority of the next level that the +// root has work on. This function is called on every update, and right before +// exiting a task. + +function ensureRootIsScheduled(root, currentTime) { + var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. + + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. + + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); // This returns the priority level computed during the `getNextLanes` call. + + var newCallbackPriority = returnNextLanesPriority(); + + if (nextLanes === NoLanes) { + // Special case: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + root.callbackNode = null; + root.callbackPriority = NoLanePriority; + } + + return; + } // Check if there's an existing task. We may be able to reuse it. + + if (existingCallbackNode !== null) { + var existingCallbackPriority = root.callbackPriority; + + if (existingCallbackPriority === newCallbackPriority) { + // The priority hasn't changed. We can reuse the existing task. Exit. + return; + } // The priority changed. Cancel the existing callback. We'll schedule a new + // one below. + + cancelCallback(existingCallbackNode); + } // Schedule a new callback. + + var newCallbackNode; + + if (newCallbackPriority === SyncLanePriority) { + // Special case: Sync React callbacks are scheduled on a special + // internal queue + newCallbackNode = scheduleSyncCallback( + performSyncWorkOnRoot.bind(null, root) + ); + } else if (newCallbackPriority === SyncBatchedLanePriority) { + newCallbackNode = scheduleCallback( + ImmediatePriority$1, + performSyncWorkOnRoot.bind(null, root) + ); + } else { + var schedulerPriorityLevel = lanePriorityToSchedulerPriority( + newCallbackPriority + ); + newCallbackNode = scheduleCallback( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + } + + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; +} // This is the entry point for every concurrent task, i.e. anything that +// goes through Scheduler. + +function performConcurrentWorkOnRoot(root) { + // Since we know we're in a React event, we can clear the current + // event time. The next update will compute a new event time. + currentEventTime = NoTimestamp; + currentEventWipLanes = NoLanes; + currentEventPendingLanes = NoLanes; + + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); + } // Flush any pending passive effects before deciding which lanes to work on, + // in case they schedule additional work. + + var originalCallbackNode = root.callbackNode; + var didFlushPassiveEffects = flushPassiveEffects(); + + if (didFlushPassiveEffects) { + // Something in the passive effect phase may have canceled the current task. + // Check if the task node for this root was changed. + if (root.callbackNode !== originalCallbackNode) { + // The current task was canceled. Exit. We don't need to call + // `ensureRootIsScheduled` because the check above implies either that + // there's a new task, or that there's no remaining work on this root. + return null; + } + } // Determine the next expiration time to work on, using the fields stored + // on the root. + + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); -var workInProgress = null; // The expiration time we're rendering + if (lanes === NoLanes) { + // Defensive coding. This is never expected to happen. + return null; + } -var renderExpirationTime$1 = NoWork; // Whether to root completed, errored, suspended, etc. + var exitStatus = renderRootConcurrent(root, lanes); -var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown + if ( + includesSomeLane( + workInProgressRootIncludedLanes, + workInProgressRootUpdatedLanes + ) + ) { + // The render included lanes that were updated during the render phase. + // For example, when unhiding a hidden tree, we include all the lanes + // that were previously skipped when the tree was hidden. That set of + // lanes is a superset of the lanes we started rendering with. + // + // So we'll throw out the current work and restart. + prepareFreshStack(root, NoLanes); + } else if (exitStatus !== RootIncomplete) { + if (exitStatus === RootErrored) { + executionContext |= RetryAfterError; // If an error occurred during hydration, + // discard server response and fall back to client side render. -var workInProgressRootFatalError = null; // Most recent event time among processed updates during this render. -// This is conceptually a time stamp but expressed in terms of an ExpirationTime -// because we deal mostly with expiration times in the hot path, so this avoids -// the conversion happening in the hot path. + if (root.hydrate) { + root.hydrate = false; + clearContainer(root.containerInfo); + } // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. -var workInProgressRootLatestProcessedExpirationTime = Sync; -var workInProgressRootLatestSuspenseTimeout = Sync; -var workInProgressRootCanSuspendUsingConfig = null; // The work left over by components that were visited during this render. Only -// includes unprocessed updates, not work in bailed out children. + lanes = getLanesToRetrySynchronouslyOnError(root); -var workInProgressRootNextUnprocessedUpdateTime = NoWork; // If we're pinged while rendering we don't always restart immediately. -// This flag determines if it might be worthwhile to restart if an opportunity -// happens latere. + if (lanes !== NoLanes) { + exitStatus = renderRootSync(root, lanes); + } + } -var workInProgressRootHasPendingPing = false; // The most recent time we committed a fallback. This lets us ensure a train -// model where we don't commit new loading states in too quick succession. + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } // We now have a consistent tree. The next step is either to commit it, + // or, if something suspended, wait to commit it after a timeout. -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; -var nextEffect = null; -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsRenderPriority = NoPriority; -var pendingPassiveEffectsExpirationTime = NoWork; -var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + finishConcurrentRender(root, exitStatus, lanes); + } -var NESTED_UPDATE_LIMIT = 50; -var nestedUpdateCount = 0; -var rootWithNestedUpdates = null; -var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; -var interruptedBy = null; // Marks the need to reschedule pending interactions at these expiration times -// during the commit phase. This enables them to be traced across components -// that spawn new work during render. E.g. hidden boundaries, suspended SSR -// hydration or SuspenseList. + ensureRootIsScheduled(root, now()); -var spawnedWorkDuringRender = null; // Expiration times are computed by adding to the current time (the start -// time). However, if two updates are scheduled within the same event, we -// should treat their start times as simultaneous, even if the actual clock -// time has advanced between the first and second call. -// In other words, because expiration times determine how updates are batched, -// we want all updates of like priority that occur within the same event to -// receive the same expiration time. Otherwise we get tearing. + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } -var currentEventTime = NoWork; -function requestCurrentTimeForUpdate() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return msToExpirationTime(now()); - } // We're not inside React, so we may be in the middle of a browser event. + return null; +} - if (currentEventTime !== NoWork) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. +function finishConcurrentRender(root, exitStatus, lanes) { + switch (exitStatus) { + case RootIncomplete: + case RootFatalErrored: { + { + throw Error("Root did not complete. This is a bug in React."); + } + } + // Flow knows about invariant, so it complains if I add a break + // statement, but eslint doesn't know about invariant, so it complains + // if I do. eslint-disable-next-line no-fallthrough - currentEventTime = msToExpirationTime(now()); - return currentEventTime; -} -function getCurrentTime() { - return msToExpirationTime(now()); -} -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { - var mode = fiber.mode; + case RootErrored: { + // We should have already attempted to retry this tree. If we reached + // this point, it errored again. Commit it. + commitRoot(root); + break; + } - if ((mode & BlockingMode) === NoMode) { - return Sync; - } + case RootSuspended: { + markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we + // should immediately commit it or wait a bit. - var priorityLevel = getCurrentPriorityLevel(); + if ( + includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope + !shouldForceFlushFallbacksInDEV() + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. - if ((mode & ConcurrentMode) === NoMode) { - return priorityLevel === ImmediatePriority ? Sync : Batched; - } + if (msUntilTimeout > 10) { + var nextLanes = getNextLanes(root, NoLanes); - if ((executionContext & RenderContext) !== NoContext) { - // Use whatever time we're already rendering - // TODO: Should there be a way to opt out, like with `runWithPriority`? - return renderExpirationTime$1; - } + if (nextLanes !== NoLanes) { + // There's additional work on this root. + break; + } - var expirationTime; + var suspendedLanes = root.suspendedLanes; - if (suspenseConfig !== null) { - // Compute an expiration time based on the Suspense timeout. - expirationTime = computeSuspenseExpiration( - currentTime, - suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION - ); - } else { - // Compute an expiration time based on the Scheduler priority. - switch (priorityLevel) { - case ImmediatePriority: - expirationTime = Sync; - break; + if (!isSubsetOfLanes(suspendedLanes, lanes)) { + // We should prefer to render the fallback of at the last + // suspended level. Ping the last suspended level to try + // rendering it again. + // FIXME: What if the suspended lanes are Idle? Should not restart. + var eventTime = requestEventTime(); + markRootPinged(root, suspendedLanes); + break; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. - case UserBlockingPriority: - // TODO: Rename this to computeUserBlockingExpiration - expirationTime = computeInteractiveExpiration(currentTime); - break; + root.timeoutHandle = scheduleTimeout( + commitRoot.bind(null, root), + msUntilTimeout + ); + break; + } + } // The work expired. Commit immediately. - case NormalPriority: - case LowPriority: - // TODO: Handle LowPriority - // TODO: Rename this to... something better. - expirationTime = computeAsyncExpiration(currentTime); - break; + commitRoot(root); + break; + } - case IdlePriority: - expirationTime = Idle; - break; + case RootSuspendedWithDelay: { + markRootSuspended$1(root, lanes); - default: { - throw Error("Expected a valid priority level"); + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + break; } + + if (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. + var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; + + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. + + if (_msUntilTimeout > 10) { + // Instead of committing the fallback immediately, wait for more data + // to arrive. + root.timeoutHandle = scheduleTimeout( + commitRoot.bind(null, root), + _msUntilTimeout + ); + break; + } + } // Commit the placeholder. + + commitRoot(root); + break; } - } // If we're in the middle of rendering a tree, do not update at the same - // expiration time that is already rendering. - // TODO: We shouldn't have to do this if the update is on a different root. - // Refactor computeExpirationForFiber + scheduleUpdate so we have access to - // the root when we check for this condition. - if ( - workInProgressRoot !== null && - expirationTime === renderExpirationTime$1 - ) { - // This is a trick to move this update into a separate batch - expirationTime -= 1; - } + case RootCompleted: { + // The work completed. Ready to commit. + commitRoot(root); + break; + } - return expirationTime; + default: { + { + throw Error("Unknown root exit status."); + } + } + } } -function scheduleUpdateOnFiber(fiber, expirationTime) { - checkForNestedUpdates(); - warnAboutRenderPhaseUpdatesInDEV(fiber); - var root = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - if (root === null) { - warnAboutUpdateOnUnmountedFiberInDEV(fiber); - return; +function markRootSuspended$1(root, suspendedLanes) { + // When suspending, we should always exclude lanes that were pinged or (more + // rarely, since we try to avoid it) updated during the render phase. + // TODO: Lol maybe there's a better way to factor this besides this + // obnoxiously named function :) + suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); + suspendedLanes = removeLanes(suspendedLanes, workInProgressRootUpdatedLanes); + markRootSuspended(root, suspendedLanes); +} // This is the entry point for synchronous tasks that don't go +// through Scheduler + +function performSyncWorkOnRoot(root) { + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); } - checkForInterruption(fiber, expirationTime); - recordScheduleUpdate(); // TODO: computeExpirationForFiber also reads the priority. Pass the - // priority as an argument to that function and this one. + flushPassiveEffects(); + var lanes; + var exitStatus; - var priorityLevel = getCurrentPriorityLevel(); + if ( + root === workInProgressRoot && + includesSomeLane(root.expiredLanes, workInProgressRootRenderLanes) + ) { + // There's a partial tree, and at least one of its lanes has expired. Finish + // rendering it before rendering the rest of the expired work. + lanes = workInProgressRootRenderLanes; + exitStatus = renderRootSync(root, lanes); - if (expirationTime === Sync) { if ( - // Check if we're inside unbatchedUpdates - (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering - (executionContext & (RenderContext | CommitContext)) === NoContext + includesSomeLane( + workInProgressRootIncludedLanes, + workInProgressRootUpdatedLanes + ) ) { - // Register pending interactions on the root to avoid losing traced interaction data. - schedulePendingInteractions(root, expirationTime); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed - // root inside of batchedUpdates should be synchronous, but layout updates - // should be deferred until the end of the batch. + // The render included lanes that were updated during the render phase. + // For example, when unhiding a hidden tree, we include all the lanes + // that were previously skipped when the tree was hidden. That set of + // lanes is a superset of the lanes we started rendering with. + // + // Note that this only happens when part of the tree is rendered + // concurrently. If the whole tree is rendered synchronously, then there + // are no interleaved events. + lanes = getNextLanes(root, lanes); + exitStatus = renderRootSync(root, lanes); + } + } else { + lanes = getNextLanes(root, NoLanes); + exitStatus = renderRootSync(root, lanes); + } - performSyncWorkOnRoot(root); - } else { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, expirationTime); + if (root.tag !== LegacyRoot && exitStatus === RootErrored) { + executionContext |= RetryAfterError; // If an error occurred during hydration, + // discard server response and fall back to client side render. - if (executionContext === NoContext) { - // Flush the synchronous work now, unless we're already working or inside - // a batch. This is intentionally inside scheduleUpdateOnFiber instead of - // scheduleCallbackForFiber to preserve the ability to schedule a callback - // without immediately flushing it. We only do this for user-initiated - // updates, to preserve historical behavior of legacy mode. - flushSyncCallbackQueue(); - } + if (root.hydrate) { + root.hydrate = false; + clearContainer(root.containerInfo); + } // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. + + lanes = getLanesToRetrySynchronouslyOnError(root); + + if (lanes !== NoLanes) { + exitStatus = renderRootSync(root, lanes); } - } else { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, expirationTime); } - if ( - (executionContext & DiscreteEventContext) !== NoContext && // Only updates at user-blocking priority or greater are considered - // discrete, even inside a discrete event. - (priorityLevel === UserBlockingPriority || - priorityLevel === ImmediatePriority) - ) { - // This is the result of a discrete event. Track the lowest priority - // discrete update per root so we can flush them early, if needed. - if (rootsWithPendingDiscreteUpdates === null) { - rootsWithPendingDiscreteUpdates = new Map([[root, expirationTime]]); - } else { - var lastDiscreteTime = rootsWithPendingDiscreteUpdates.get(root); + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - if (lastDiscreteTime === undefined || lastDiscreteTime > expirationTime) { - rootsWithPendingDiscreteUpdates.set(root, expirationTime); - } + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot(root); // Before exiting, make sure there's a callback scheduled for the next + // pending level. + + ensureRootIsScheduled(root, now()); + return null; +} + +function batchedUpdates$1(fn, a) { + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; + + try { + return fn(a); + } finally { + executionContext = prevExecutionContext; + + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + resetRenderTimer(); + flushSyncCallbackQueue(); } } } -var scheduleWork = scheduleUpdateOnFiber; // This is split into a separate function so we can mark a fiber with pending -// work without treating it as a typical update that originates from an event; -// e.g. retrying a Suspense boundary isn't an update, but it does schedule work -// on a fiber. +function flushSync(fn, a) { + var prevExecutionContext = executionContext; + + if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) { + { + error( + "flushSync was called from inside a lifecycle method. React cannot " + + "flush when React is already rendering. Consider moving this call to " + + "a scheduler task or micro task." + ); + } -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - // Update the source fiber's expiration time - if (fiber.expirationTime < expirationTime) { - fiber.expirationTime = expirationTime; + return fn(a); } - var alternate = fiber.alternate; + executionContext |= BatchedContext; - if (alternate !== null && alternate.expirationTime < expirationTime) { - alternate.expirationTime = expirationTime; - } // Walk the parent path to the root and update the child expiration time. + { + try { + if (fn) { + return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); + } else { + return undefined; + } + } finally { + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - var node = fiber.return; - var root = null; + flushSyncCallbackQueue(); + } + } +} +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); + subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); + workInProgressRootIncludedLanes = mergeLanes( + workInProgressRootIncludedLanes, + lanes + ); +} +function popRenderLanes(fiber) { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor, fiber); +} - if (node === null && fiber.tag === HostRoot) { - root = fiber.stateNode; - } else { - while (node !== null) { - alternate = node.alternate; +function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; - if (node.childExpirationTime < expirationTime) { - node.childExpirationTime = expirationTime; + if (timeoutHandle !== noTimeout) { + // The root previous suspended and scheduled a timeout to commit a fallback + // state. Now that we have additional work, cancel the timeout. + root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above - if ( - alternate !== null && - alternate.childExpirationTime < expirationTime - ) { - alternate.childExpirationTime = expirationTime; - } - } else if ( - alternate !== null && - alternate.childExpirationTime < expirationTime - ) { - alternate.childExpirationTime = expirationTime; - } + cancelTimeout(timeoutHandle); + } - if (node.return === null && node.tag === HostRoot) { - root = node.stateNode; - break; - } + if (workInProgress !== null) { + var interruptedWork = workInProgress.return; - node = node.return; + while (interruptedWork !== null) { + unwindInterruptedWork(interruptedWork); + interruptedWork = interruptedWork.return; } } - if (root !== null) { - if (workInProgressRoot === root) { - // Received an update to a tree that's in the middle of rendering. Mark - // that's unprocessed work on this root. - markUnprocessedUpdateTime(expirationTime); - - if (workInProgressRootExitStatus === RootSuspendedWithDelay) { - // The root already suspended with a delay, which means this render - // definitely won't finish. Since we have a new update, let's mark it as - // suspended now, right before marking the incoming update. This has the - // effect of interrupting the current render and switching to the update. - // TODO: This happens to work when receiving an update during the render - // phase, because of the trick inside computeExpirationForFiber to - // subtract 1 from `renderExpirationTime` to move it into a - // separate bucket. But we should probably model it with an exception, - // using the same mechanism we use to force hydration of a subtree. - // TODO: This does not account for low pri updates that were already - // scheduled before the root started rendering. Need to track the next - // pending expiration time (perhaps by backtracking the return path) and - // then trigger a restart in the `renderDidSuspendDelayIfPossible` path. - markRootSuspendedAtTime(root, renderExpirationTime$1); - } - } // Mark that the root has a pending update. - - markRootUpdatedAtTime(root, expirationTime); + workInProgressRoot = root; + workInProgress = createWorkInProgress(root.current, null); + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = RootIncomplete; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + + { + spawnedWorkDuringRender = null; } - return root; + { + ReactStrictModeWarnings.discardPendingWarnings(); + } } -function getNextRootExpirationTimeToWorkOn(root) { - // Determines the next expiration time that the root should render, taking - // into account levels that may be suspended, or levels that may have - // received a ping. - var lastExpiredTime = root.lastExpiredTime; +function handleError(root, thrownValue) { + do { + var erroredWork = workInProgress; - if (lastExpiredTime !== NoWork) { - return lastExpiredTime; - } // "Pending" refers to any update that hasn't committed yet, including if it - // suspended. The "suspended" range is therefore a subset. + try { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksAfterThrow(); + resetCurrentFiber(); // TODO: I found and added this missing line while investigating a + // separate issue. Write a regression test using string refs. - var firstPendingTime = root.firstPendingTime; + ReactCurrentOwner$2.current = null; - if (!isRootSuspendedAtTime(root, firstPendingTime)) { - // The highest priority pending time is not suspended. Let's work on that. - return firstPendingTime; - } // If the first pending time is suspended, check if there's a lower priority - // pending level that we know about. Or check if we received a ping. Work - // on whichever is higher priority. + if (erroredWork === null || erroredWork.return === null) { + // Expected to be working on a non-root fiber. This is a fatal error + // because there's no ancestor that can handle it; the root is + // supposed to capture all errors that weren't caught by an error + // boundary. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. - var lastPingedTime = root.lastPingedTime; - var nextKnownPendingLevel = root.nextKnownPendingLevel; - var nextLevel = - lastPingedTime > nextKnownPendingLevel - ? lastPingedTime - : nextKnownPendingLevel; + workInProgress = null; + return; + } - if (nextLevel <= Idle && firstPendingTime !== nextLevel) { - // Don't work on Idle/Never priority unless everything else is committed. - return NoWork; - } + if (enableProfilerTimer && erroredWork.mode & ProfileMode) { + // Record the time spent rendering before an error was thrown. This + // avoids inaccurate Profiler durations in the case of a + // suspended render. + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); + } - return nextLevel; -} // Use this function to schedule a task for a root. There's only one task per -// root; if a task was already scheduled, we'll check to make sure the -// expiration time of the existing task is the same as the expiration time of -// the next level that the root has work on. This function is called on every -// update, and right before exiting a task. - -function ensureRootIsScheduled(root) { - var lastExpiredTime = root.lastExpiredTime; - - if (lastExpiredTime !== NoWork) { - // Special case: Expired work should flush synchronously. - root.callbackExpirationTime = Sync; - root.callbackPriority = ImmediatePriority; - root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - ); - return; - } + throwException( + root, + erroredWork.return, + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + completeUnitOfWork(erroredWork); + } catch (yetAnotherThrownValue) { + // Something in the return path also threw. + thrownValue = yetAnotherThrownValue; - var expirationTime = getNextRootExpirationTimeToWorkOn(root); - var existingCallbackNode = root.callbackNode; + if (workInProgress === erroredWork && erroredWork !== null) { + // If this boundary has already errored, then we had trouble processing + // the error. Bubble it to the next boundary. + erroredWork = erroredWork.return; + workInProgress = erroredWork; + } else { + erroredWork = workInProgress; + } - if (expirationTime === NoWork) { - // There's nothing to work on. - if (existingCallbackNode !== null) { - root.callbackNode = null; - root.callbackExpirationTime = NoWork; - root.callbackPriority = NoPriority; - } + continue; + } // Return to the normal work loop. return; - } // TODO: If this is an update, we already read the current time. Pass the - // time as an argument. + } while (true); +} - var currentTime = requestCurrentTimeForUpdate(); - var priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); // If there's an existing render task, confirm it has the correct priority and - // expiration time. Otherwise, we'll cancel it and schedule a new one. +function pushDispatcher() { + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; - if (existingCallbackNode !== null) { - var existingCallbackPriority = root.callbackPriority; - var existingCallbackExpirationTime = root.callbackExpirationTime; + if (prevDispatcher === null) { + // The React isomorphic package does not include a default dispatcher. + // Instead the first renderer will lazily attach one, in order to give + // nicer error messages. + return ContextOnlyDispatcher; + } else { + return prevDispatcher; + } +} - if ( - // Callback must have the exact same expiration time. - existingCallbackExpirationTime === expirationTime && // Callback must have greater or equal priority. - existingCallbackPriority >= priorityLevel - ) { - // Existing callback is sufficient. - return; - } // Need to schedule a new task. - // TODO: Instead of scheduling a new task, we should be able to change the - // priority of the existing one. +function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher$2.current = prevDispatcher; +} - cancelCallback(existingCallbackNode); +function pushInteractions(root) { + { + var prevInteractions = tracing.__interactionsRef.current; + tracing.__interactionsRef.current = root.memoizedInteractions; + return prevInteractions; } +} - root.callbackExpirationTime = expirationTime; - root.callbackPriority = priorityLevel; - var callbackNode; +function popInteractions(prevInteractions) { + { + tracing.__interactionsRef.current = prevInteractions; + } +} - if (expirationTime === Sync) { - // Sync React callbacks are scheduled on a special internal queue - callbackNode = scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); - } else { - callbackNode = scheduleCallback( - priorityLevel, - performConcurrentWorkOnRoot.bind(null, root), // Compute a task timeout based on the expiration time. This also affects - // ordering because tasks are processed in timeout order. - { - timeout: expirationTimeToMs(expirationTime) - now() - } - ); +function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now(); +} +function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); +} +function renderDidSuspend() { + if (workInProgressRootExitStatus === RootIncomplete) { + workInProgressRootExitStatus = RootSuspended; } +} +function renderDidSuspendDelayIfPossible() { + if ( + workInProgressRootExitStatus === RootIncomplete || + workInProgressRootExitStatus === RootSuspended + ) { + workInProgressRootExitStatus = RootSuspendedWithDelay; + } // Check if there are updates that we skipped tree that might have unblocked + // this render. - root.callbackNode = callbackNode; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. + if ( + workInProgressRoot !== null && + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootUpdatedLanes)) + ) { + // Mark the current render as suspended so that we switch to working on + // the updates that were skipped. Usually we only suspend at the end of + // the render phase. + // TODO: We should probably always mark the root as suspended immediately + // (inside this function), since by suspending at the end of the render + // phase introduces a potential mistake where we suspend lanes that were + // pinged or updated while we were rendering. + markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); + } +} +function renderDidError() { + if (workInProgressRootExitStatus !== RootCompleted) { + workInProgressRootExitStatus = RootErrored; + } +} // Called during render to determine if anything has suspended. +// Returns false if we're not sure. -function performConcurrentWorkOnRoot(root, didTimeout) { - // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - currentEventTime = NoWork; // Check if the render expired. +function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootIncomplete; +} - if (didTimeout) { - // The render task took too long to complete. Mark the current time as - // expired to synchronously render all expired work in a single batch. - var currentTime = requestCurrentTimeForUpdate(); - markRootExpiredAtTime(root, currentTime); // This will schedule a synchronous callback. +function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - ensureRootIsScheduled(root); - return null; - } // Determine the next expiration time to work on, using the fields stored - // on the root. + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + prepareFreshStack(root, lanes); + startWorkOnPendingInteractions(root, lanes); + } - var expirationTime = getNextRootExpirationTimeToWorkOn(root); + var prevInteractions = pushInteractions(root); - if (expirationTime === NoWork) { - return null; - } + do { + try { + workLoopSync(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); + } + } while (true); - var originalCallbackNode = root.callbackNode; + resetContextDependencies(); - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); + { + popInteractions(prevInteractions); } - flushPassiveEffects(); - var exitStatus = renderRootConcurrent(root, expirationTime); + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); - if (exitStatus !== RootIncomplete) { - if (exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll - // render synchronously to block concurrent data mutations, and we'll - // render at Idle (or lower) so that all pending updates are included. - // If it still fails after the second attempt, we'll give up and commit - // the resulting tree. - expirationTime = expirationTime > Idle ? Idle : expirationTime; - exitStatus = renderRootSync(root, expirationTime); + if (workInProgress !== null) { + // This is a sync render, so we should have finished the whole tree. + { + throw Error( + "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." + ); } + } - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, expirationTime); - markRootSuspendedAtTime(root, expirationTime); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. The next step is either to commit it, - // or, if something suspended, wait to commit it after a timeout. + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; + return workInProgressRootExitStatus; +} // The work loop is an extremely hot path. Tell Closure not to inline it. + +/** @noinline */ - var finishedWork = (root.finishedWork = root.current.alternate); - root.finishedExpirationTime = expirationTime; - finishConcurrentRender(root, finishedWork, exitStatus, expirationTime); +function workLoopSync() { + // Already timed out, so perform work without checking if we need to yield. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); } +} - ensureRootIsScheduled(root); +function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + resetRenderTimer(); + prepareFreshStack(root, lanes); + startWorkOnPendingInteractions(root, lanes); } - return null; -} - -function finishConcurrentRender( - root, - finishedWork, - exitStatus, - expirationTime -) { - switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: { - { - throw Error("Root did not complete. This is a bug in React."); - } - } - // Flow knows about invariant, so it complains if I add a break - // statement, but eslint doesn't know about invariant, so it complains - // if I do. eslint-disable-next-line no-fallthrough + var prevInteractions = pushInteractions(root); - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRoot(root); + do { + try { + workLoopConcurrent(); break; + } catch (thrownValue) { + handleError(root, thrownValue); } + } while (true); - case RootSuspended: { - markRootSuspendedAtTime(root, expirationTime); - var lastSuspendedTime = root.lastSuspendedTime; - - if (expirationTime === lastSuspendedTime) { - root.nextKnownPendingLevel = getRemainingExpirationTime(finishedWork); - } // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - // If we have processed new updates during this render, we may now - // have a new loading state ready. We want to ensure that we commit - // that as soon as possible. - - var hasNotProcessedNewUpdates = - workInProgressRootLatestProcessedExpirationTime === Sync; - - if ( - hasNotProcessedNewUpdates && // do not delay if we're inside an act() scope - !IsThisRendererActing.current - ) { - // If we have not processed any new updates during this pass, then - // this is either a retry of an existing fallback state or a - // hidden tree. Hidden trees shouldn't be batched with other work - // and after that's fixed it can only be a retry. We're going to - // throttle committing retries so that we don't show too many - // loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. + resetContextDependencies(); - if (msUntilTimeout > 10) { - if (workInProgressRootHasPendingPing) { - var lastPingedTime = root.lastPingedTime; - - if (lastPingedTime === NoWork || lastPingedTime >= expirationTime) { - // This render was pinged but we didn't get to restart - // earlier so try restarting now instead. - root.lastPingedTime = expirationTime; - prepareFreshStack(root, expirationTime); - break; - } - } + { + popInteractions(prevInteractions); + } - var nextTime = getNextRootExpirationTimeToWorkOn(root); + popDispatcher(prevDispatcher); + executionContext = prevExecutionContext; - if (nextTime !== NoWork && nextTime !== expirationTime) { - // There's additional work on this root. - break; - } + if (workInProgress !== null) { + return RootIncomplete; + } else { + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // Return the final exit status. - if ( - lastSuspendedTime !== NoWork && - lastSuspendedTime !== expirationTime - ) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - root.lastPingedTime = lastSuspendedTime; - break; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. + return workInProgressRootExitStatus; + } +} +/** @noinline */ - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. +function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + performUnitOfWork(workInProgress); + } +} - commitRoot(root); - break; - } +function performUnitOfWork(unitOfWork) { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; - case RootSuspendedWithDelay: { - markRootSuspendedAtTime(root, expirationTime); - var _lastSuspendedTime = root.lastSuspendedTime; + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + } - if (expirationTime === _lastSuspendedTime) { - root.nextKnownPendingLevel = getRemainingExpirationTime(finishedWork); - } + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; - { - // We're suspended in a state that should be avoided. We'll try to - // avoid committing it for as long as the timeouts let us. - if (workInProgressRootHasPendingPing) { - var _lastPingedTime = root.lastPingedTime; - - if (_lastPingedTime === NoWork || _lastPingedTime >= expirationTime) { - // This render was pinged but we didn't get to restart earlier - // so try restarting now instead. - root.lastPingedTime = expirationTime; - prepareFreshStack(root, expirationTime); - break; - } - } + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; + } - var _nextTime = getNextRootExpirationTimeToWorkOn(root); + ReactCurrentOwner$2.current = null; +} - if (_nextTime !== NoWork && _nextTime !== expirationTime) { - // There's additional work on this root. - break; - } +function completeUnitOfWork(unitOfWork) { + // Attempt to complete the current unit of work, then move to the next + // sibling. If there are no more siblings, return to the parent fiber. + var completedWork = unitOfWork; - if ( - _lastSuspendedTime !== NoWork && - _lastSuspendedTime !== expirationTime - ) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - root.lastPingedTime = _lastSuspendedTime; - break; - } + do { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = completedWork.alternate; + var returnFiber = completedWork.return; // Check if the work completed or if something threw. - var _msUntilTimeout; - - if (workInProgressRootLatestSuspenseTimeout !== Sync) { - // We have processed a suspense config whose expiration time we - // can use as the timeout. - _msUntilTimeout = - expirationTimeToMs(workInProgressRootLatestSuspenseTimeout) - now(); - } else if (workInProgressRootLatestProcessedExpirationTime === Sync) { - // This should never normally happen because only new updates - // cause delayed states, so we should have processed something. - // However, this could also happen in an offscreen tree. - _msUntilTimeout = 0; - } else { - // If we don't have a suspense config, we're going to use a - // heuristic to determine how long we can suspend. - var eventTimeMs = inferTimeFromExpirationTime( - workInProgressRootLatestProcessedExpirationTime - ); - var currentTimeMs = now(); - var timeUntilExpirationMs = - expirationTimeToMs(expirationTime) - currentTimeMs; - var timeElapsed = currentTimeMs - eventTimeMs; - - if (timeElapsed < 0) { - // We get this wrong some time since we estimate the time. - timeElapsed = 0; - } + if ((completedWork.flags & Incomplete) === NoFlags) { + setCurrentFiber(completedWork); + var next = void 0; - _msUntilTimeout = jnd(timeElapsed) - timeElapsed; // Clamp the timeout to the expiration time. TODO: Once the - // event time is exact instead of inferred from expiration time - // we don't need this. + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, subtreeRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. - if (timeUntilExpirationMs < _msUntilTimeout) { - _msUntilTimeout = timeUntilExpirationMs; - } - } // Don't bother with a very short suspense time. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); + } - if (_msUntilTimeout > 10) { - // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. + resetCurrentFiber(); - commitRoot(root); - break; - } + if (next !== null) { + // Completing this fiber spawned new work. Work on that next. + workInProgress = next; + return; + } + + resetChildLanes(completedWork); - case RootCompleted: { - // The work completed. Ready to commit. if ( - // do not delay if we're inside an act() scope - workInProgressRootLatestProcessedExpirationTime !== Sync && - workInProgressRootCanSuspendUsingConfig !== null + returnFiber !== null && // Do not append effects to parents if a sibling failed to complete + (returnFiber.flags & Incomplete) === NoFlags ) { - // If we have exceeded the minimum loading delay, which probably - // means we have shown a spinner already, we might have to suspend - // a bit longer to ensure that the spinner is shown for - // enough time. - var _msUntilTimeout2 = computeMsUntilSuspenseLoadingDelay( - workInProgressRootLatestProcessedExpirationTime, - expirationTime, - workInProgressRootCanSuspendUsingConfig - ); - - if (_msUntilTimeout2 > 10) { - markRootSuspendedAtTime(root, expirationTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout2 - ); - break; + // Append all the effects of the subtree and this fiber onto the effect + // list of the parent. The completion order of the children affects the + // side-effect order. + if (returnFiber.firstEffect === null) { + returnFiber.firstEffect = completedWork.firstEffect; } - } - commitRoot(root); - break; - } + if (completedWork.lastEffect !== null) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = completedWork.firstEffect; + } - default: { - { - throw Error("Unknown root exit status."); - } - } - } -} // This is the entry point for synchronous tasks that don't go -// through Scheduler + returnFiber.lastEffect = completedWork.lastEffect; + } // If this fiber had side-effects, we append it AFTER the children's + // side-effects. We can perform certain side-effects earlier if needed, + // by doing multiple passes over the effect list. We don't want to + // schedule our own side-effect on our own list because if end up + // reusing children we'll schedule this effect onto itself since we're + // at the end. -function performSyncWorkOnRoot(root) { - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); - } + var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect + // list. PerformedWork effect is read by React DevTools but shouldn't be + // committed. - flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - var expirationTime; + if (flags > PerformedWork) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = completedWork; + } else { + returnFiber.firstEffect = completedWork; + } - if (lastExpiredTime !== NoWork) { - // There's expired work on this root. Check if we have a partial tree - // that we can reuse. - if ( - root === workInProgressRoot && - renderExpirationTime$1 >= lastExpiredTime - ) { - // There's a partial tree with equal or greater than priority than the - // expired level. Finish rendering it before rendering the rest of the - // expired work. - expirationTime = renderExpirationTime$1; + returnFiber.lastEffect = completedWork; + } + } } else { - // Start a fresh tree. - expirationTime = lastExpiredTime; - } - } else { - // There's no expired work. This must be a new, synchronous render. - expirationTime = Sync; - } - - var exitStatus = renderRootSync(root, expirationTime); - - if (root.tag !== LegacyRoot && exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll - // render synchronously to block concurrent data mutations, and we'll - // render at Idle (or lower) so that all pending updates are included. - // If it still fails after the second attempt, we'll give up and commit - // the resulting tree. - expirationTime = expirationTime > Idle ? Idle : expirationTime; - exitStatus = renderRootSync(root, expirationTime); - } + // This fiber did not complete because something threw. Pop values off + // the stack without entering the complete phase. If this is a boundary, + // capture values if possible. + var _next = unwindWork(completedWork); // Because this fiber did not complete, don't reset its expiration time. - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, expirationTime); - markRootSuspendedAtTime(root, expirationTime); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. Because this is a sync render, we - // will commit it even if something suspended. + if (_next !== null) { + // If completing this work spawned new work, do that next. We'll come + // back here again. + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + _next.flags &= HostEffectMask; + workInProgress = _next; + return; + } - root.finishedWork = root.current.alternate; - root.finishedExpirationTime = expirationTime; - commitRoot(root); // Before exiting, make sure there's a callback scheduled for the next - // pending level. + if ((completedWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. - ensureRootIsScheduled(root); - return null; -} -function syncUpdates(fn, a, b, c) { - return runWithPriority(ImmediatePriority, fn.bind(null, a, b, c)); -} + var actualDuration = completedWork.actualDuration; + var child = completedWork.child; -function batchedUpdates$1(fn, a) { - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + while (child !== null) { + actualDuration += child.actualDuration; + child = child.sibling; + } - try { - return fn(a); - } finally { - executionContext = prevExecutionContext; + completedWork.actualDuration = actualDuration; + } - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); - } - } -} -function flushSync(fn, a) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - { - throw Error( - "flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering." - ); + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its effect list. + returnFiber.firstEffect = returnFiber.lastEffect = null; + returnFiber.flags |= Incomplete; + } } - } - - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; - - try { - return runWithPriority(ImmediatePriority, fn.bind(null, a)); - } finally { - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - flushSyncCallbackQueue(); - } -} - -function prepareFreshStack(root, expirationTime) { - root.finishedWork = null; - root.finishedExpirationTime = NoWork; - var timeoutHandle = root.timeoutHandle; + var siblingFiber = completedWork.sibling; - if (timeoutHandle !== noTimeout) { - // The root previous suspended and scheduled a timeout to commit a fallback - // state. Now that we have additional work, cancel the timeout. - root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent - cancelTimeout(timeoutHandle); - } + completedWork = returnFiber; // Update the next thing we're working on in case something throws. - if (workInProgress !== null) { - var interruptedWork = workInProgress.return; + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. - while (interruptedWork !== null) { - unwindInterruptedWork(interruptedWork); - interruptedWork = interruptedWork.return; - } + if (workInProgressRootExitStatus === RootIncomplete) { + workInProgressRootExitStatus = RootCompleted; } +} - workInProgressRoot = root; - workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; - workInProgressRootFatalError = null; - workInProgressRootLatestProcessedExpirationTime = Sync; - workInProgressRootLatestSuspenseTimeout = Sync; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = NoWork; - workInProgressRootHasPendingPing = false; - - { - spawnedWorkDuringRender = null; +function resetChildLanes(completedWork) { + if ( + // TODO: Move this check out of the hot path by moving `resetChildLanes` + // to switch statement in `completeWork`. + (completedWork.tag === LegacyHiddenComponent || + completedWork.tag === OffscreenComponent) && + completedWork.memoizedState !== null && + !includesSomeLane(subtreeRenderLanes, OffscreenLane) && + (completedWork.mode & ConcurrentMode) !== NoLanes + ) { + // The children of this component are hidden. Don't bubble their + // expiration times. + return; } - { - ReactStrictModeWarnings.discardPendingWarnings(); - } -} + var newChildLanes = NoLanes; // Bubble up the earliest expiration time. -function handleError(root, thrownValue) { - do { - try { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksAfterThrow(); - resetCurrentFiber(); + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var actualDuration = completedWork.actualDuration; + var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will + // only be updated if work is done on the fiber (i.e. it doesn't bailout). + // When work is done, it should bubble to the parent's actualDuration. If + // the fiber has not been cloned though, (meaning no work was done), then + // this value will reflect the amount of time spent working on a previous + // render. In that case it should not bubble. We determine whether it was + // cloned by comparing the child pointer. - if (workInProgress === null || workInProgress.return === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // interntionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. + var shouldBubbleActualDurations = + completedWork.alternate === null || + completedWork.child !== completedWork.alternate.child; + var child = completedWork.child; - workInProgress = null; - return null; - } + while (child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(child.lanes, child.childLanes) + ); - if (enableProfilerTimer && workInProgress.mode & ProfileMode) { - // Record the time spent rendering before an error was thrown. This - // avoids inaccurate Profiler durations in the case of a - // suspended render. - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, true); + if (shouldBubbleActualDurations) { + actualDuration += child.actualDuration; } - throwException( - root, - workInProgress.return, - workInProgress, - thrownValue, - renderExpirationTime$1 - ); - workInProgress = completeUnitOfWork(workInProgress); - } catch (yetAnotherThrownValue) { - // Something in the return path also threw. - thrownValue = yetAnotherThrownValue; - continue; - } // Return to the normal work loop. + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - return; - } while (true); -} + var isTimedOutSuspense = + completedWork.tag === SuspenseComponent && + completedWork.memoizedState !== null; -function pushDispatcher(root) { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = completedWork.child; - if (prevDispatcher === null) { - // The React isomorphic package does not include a default dispatcher. - // Instead the first renderer will lazily attach one, in order to give - // nicer error messages. - return ContextOnlyDispatcher; + if (primaryChildFragment !== null) { + treeBaseDuration -= primaryChildFragment.treeBaseDuration; + } + } + + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; } else { - return prevDispatcher; + var _child = completedWork.child; + + while (_child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child.lanes, _child.childLanes) + ); + _child = _child.sibling; + } } -} -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher$1.current = prevDispatcher; + completedWork.childLanes = newChildLanes; } -function pushInteractions(root) { - { - var prevInteractions = tracing.__interactionsRef.current; - tracing.__interactionsRef.current = root.memoizedInteractions; - return prevInteractions; - } +function commitRoot(root) { + var renderPriorityLevel = getCurrentPriorityLevel(); + runWithPriority( + ImmediatePriority$1, + commitRootImpl.bind(null, root, renderPriorityLevel) + ); + return null; } -function popInteractions(prevInteractions) { - { - tracing.__interactionsRef.current = prevInteractions; - } -} +function commitRootImpl(root, renderPriorityLevel) { + do { + // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which + // means `flushPassiveEffects` will sometimes result in additional + // passive effects. So we need to keep flushing in a loop until there are + // no more pending effects. + // TODO: Might be better if `flushPassiveEffects` did not automatically + // flush synchronous work at the end, to avoid factoring hazards like this. + flushPassiveEffects(); + } while (rootWithPendingPassiveEffects !== null); -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now(); -} -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - if ( - expirationTime < workInProgressRootLatestProcessedExpirationTime && - expirationTime > Idle - ) { - workInProgressRootLatestProcessedExpirationTime = expirationTime; + flushRenderPhaseStrictModeWarningsInDEV(); + + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); } - if (suspenseConfig !== null) { - if ( - expirationTime < workInProgressRootLatestSuspenseTimeout && - expirationTime > Idle - ) { - workInProgressRootLatestSuspenseTimeout = expirationTime; // Most of the time we only have one config and getting wrong is not bad. + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; - workInProgressRootCanSuspendUsingConfig = suspenseConfig; - } - } -} -function markUnprocessedUpdateTime(expirationTime) { - if (expirationTime > workInProgressRootNextUnprocessedUpdateTime) { - workInProgressRootNextUnprocessedUpdateTime = expirationTime; - } -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootIncomplete) { - workInProgressRootExitStatus = RootSuspended; + if (finishedWork === null) { + return null; } -} -function renderDidSuspendDelayIfPossible() { - if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended - ) { - workInProgressRootExitStatus = RootSuspendedWithDelay; - } // Check if there's a lower priority update somewhere else in the tree. - if ( - workInProgressRootNextUnprocessedUpdateTime !== NoWork && - workInProgressRoot !== null - ) { - // Mark the current render as suspended, and then mark that there's a - // pending update. - // TODO: This should immediately interrupt the current render, instead - // of waiting until the next time we yield. - markRootSuspendedAtTime(workInProgressRoot, renderExpirationTime$1); - markRootUpdatedAtTime( - workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime + root.finishedWork = null; + root.finishedLanes = NoLanes; + + if (!(finishedWork !== root.current)) { + throw Error( + "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - } -} -function renderDidError() { - if (workInProgressRootExitStatus !== RootCompleted) { - workInProgressRootExitStatus = RootErrored; - } -} // Called during render to determine if anything has suspended. -// Returns false if we're not sure. + } // commitRoot never returns a continuation; it always finishes synchronously. + // So we can clear these now to allow a new callback to be scheduled. -function renderHasNotSuspendedYet() { - // If something errored or completed, we can't really be sure, - // so those are false. - return workInProgressRootExitStatus === RootIncomplete; -} + root.callbackNode = null; // Update the first and last pending times on this root. The new first + // pending time is whatever is left on the root fiber. -function inferTimeFromExpirationTime(expirationTime) { - // We don't know exactly when the update was scheduled, but we can infer an - // approximate start time from the expiration time. - var earliestExpirationTimeMs = expirationTimeToMs(expirationTime); - return earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION; -} + var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); + markRootFinished(root, remainingLanes); // Clear already finished discrete updates in case that a later call of + // `flushDiscreteUpdates` starts a useless render pass which may cancels + // a scheduled timeout. -function inferTimeFromExpirationTimeWithSuspenseConfig( - expirationTime, - suspenseConfig -) { - // We don't know exactly when the update was scheduled, but we can infer an - // approximate start time from the expiration time by subtracting the timeout - // that was added to the event time. - var earliestExpirationTimeMs = expirationTimeToMs(expirationTime); - return ( - earliestExpirationTimeMs - - (suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION) - ); -} + if (rootsWithPendingDiscreteUpdates !== null) { + if ( + !hasDiscreteLanes(remainingLanes) && + rootsWithPendingDiscreteUpdates.has(root) + ) { + rootsWithPendingDiscreteUpdates.delete(root); + } + } -function renderRootSync(root, expirationTime) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // If the root or expiration time have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + if (root === workInProgressRoot) { + // We can reset these now that they are finished. + workInProgressRoot = null; + workInProgress = null; + workInProgressRootRenderLanes = NoLanes; + } // Get the list of effects. - if ( - root !== workInProgressRoot || - expirationTime !== renderExpirationTime$1 - ) { - prepareFreshStack(root, expirationTime); - startWorkOnPendingInteractions(root, expirationTime); + var firstEffect; + + if (finishedWork.flags > PerformedWork) { + // A fiber's effect list consists only of its children, not itself. So if + // the root has an effect, we need to add it to the end of the list. The + // resulting list is the set that would belong to the root's parent, if it + // had one; that is, all the effects in the tree including the root. + if (finishedWork.lastEffect !== null) { + finishedWork.lastEffect.nextEffect = finishedWork; + firstEffect = finishedWork.firstEffect; + } else { + firstEffect = finishedWork; + } + } else { + // There is no effect on the root. + firstEffect = finishedWork.firstEffect; } - var prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); + if (firstEffect !== null) { + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + var prevInteractions = pushInteractions(root); // Reset this to null before calling lifecycles - do { - try { - workLoopSync(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass + // of the effect list for each phase: all mutation effects come before all + // layout effects, and so on. + // The first phase a "before mutation" phase. We use this phase to read the + // state of the host tree right before we mutate it. This is where + // getSnapshotBeforeUpdate is called. - resetContextDependencies(); + focusedInstanceHandle = prepareForCommit(root.containerInfo); + shouldFireAfterActiveInstanceBlur = false; + nextEffect = firstEffect; - { - popInteractions(prevInteractions); - } + do { + { + invokeGuardedCallback(null, commitBeforeMutationEffects, null); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - if (workInProgress !== null) { - // This is a sync render, so we should have finished the whole tree. - { - throw Error( - "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." - ); - } - } + var error = clearCaughtError(); + captureCommitPhaseError(nextEffect, error); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); // We no longer need to track the active instance fiber - stopFinishedWorkLoopTimer(); // Set this to null to indicate there's no in-progress render. + focusedInstanceHandle = null; - workInProgressRoot = null; - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); + } // The next phase is the mutation phase, where we mutate the host tree. -/** @noinline */ + nextEffect = firstEffect; -function workLoopSync() { - // Already timed out, so perform work without checking if we need to yield. - while (workInProgress !== null) { - workInProgress = performUnitOfWork(workInProgress); - } -} + do { + { + invokeGuardedCallback( + null, + commitMutationEffects, + null, + root, + renderPriorityLevel + ); -function renderRootConcurrent(root, expirationTime) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // If the root or expiration time have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - if ( - root !== workInProgressRoot || - expirationTime !== renderExpirationTime$1 - ) { - prepareFreshStack(root, expirationTime); - startWorkOnPendingInteractions(root, expirationTime); - } + var _error = clearCaughtError(); - var prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); + captureCommitPhaseError(nextEffect, _error); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); - do { - try { - workLoopConcurrent(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after + // the mutation phase, so that the previous tree is still current during + // componentWillUnmount, but before the layout phase, so that the finished + // work is current during componentDidMount/Update. + + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + // the host tree after it's been mutated. The idiomatic use case for this is + // layout, but class component lifecycles also fire here for legacy reasons. - resetContextDependencies(); + nextEffect = firstEffect; - { - popInteractions(prevInteractions); - } + do { + { + invokeGuardedCallback(null, commitLayoutEffects, null, root, lanes); - popDispatcher(prevDispatcher); - executionContext = prevExecutionContext; // Check if the tree has completed. + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - if (workInProgress !== null) { - // Still work remaining. - stopInterruptedWorkLoopTimer(); - return RootIncomplete; - } else { - // Completed the tree. - stopFinishedWorkLoopTimer(); // Set this to null to indicate there's no in-progress render. + var _error2 = clearCaughtError(); - workInProgressRoot = null; // Return the final exit status. + captureCommitPhaseError(nextEffect, _error2); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); - return workInProgressRootExitStatus; - } -} -/** @noinline */ + nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an + // opportunity to paint. -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - workInProgress = performUnitOfWork(workInProgress); - } -} + requestPaint(); -function performUnitOfWork(unitOfWork) { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = unitOfWork.alternate; - startWorkTimer(unitOfWork); - setCurrentFiber(unitOfWork); - var next; + { + popInteractions(prevInteractions); + } - if ((unitOfWork.mode & ProfileMode) !== NoMode) { - startProfilerTimer(unitOfWork); - next = beginWork$1(current, unitOfWork, renderExpirationTime$1); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + executionContext = prevExecutionContext; } else { - next = beginWork$1(current, unitOfWork, renderExpirationTime$1); - } - - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; + // No effects. + root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were + // no effects. + // TODO: Maybe there's a better way to report this. - if (next === null) { - // If this doesn't spawn new work, complete the current work. - next = completeUnitOfWork(unitOfWork); + { + recordCommitTime(); + } } - ReactCurrentOwner$2.current = null; - return next; -} - -function completeUnitOfWork(unitOfWork) { - // Attempt to complete the current unit of work, then move to the next - // sibling. If there are no more siblings, return to the parent fiber. - workInProgress = unitOfWork; - - do { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = workInProgress.alternate; - var returnFiber = workInProgress.return; // Check if the work completed or if something threw. + var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - if ((workInProgress.effectTag & Incomplete) === NoEffect) { - setCurrentFiber(workInProgress); - var next = void 0; + if (rootDoesHavePassiveEffects) { + // This commit has passive effects. Stash a reference to them. But don't + // schedule a callback until after flushing layout work. + rootDoesHavePassiveEffects = false; + rootWithPendingPassiveEffects = root; + pendingPassiveEffectsLanes = lanes; + pendingPassiveEffectsRenderPriority = renderPriorityLevel; + } else { + // We are done with the effect chain at this point so let's clear the + // nextEffect pointers to assist with GC. If we have passive effects, we'll + // clear this in flushPassiveEffects. + nextEffect = firstEffect; - if ((workInProgress.mode & ProfileMode) === NoMode) { - next = completeWork(current, workInProgress, renderExpirationTime$1); - } else { - startProfilerTimer(workInProgress); - next = completeWork(current, workInProgress, renderExpirationTime$1); // Update render duration assuming we didn't error. + while (nextEffect !== null) { + var nextNextEffect = nextEffect.nextEffect; + nextEffect.nextEffect = null; - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false); + if (nextEffect.flags & Deletion) { + detachFiberAfterEffects(nextEffect); } - stopWorkTimer(workInProgress); - resetCurrentFiber(); - resetChildExpirationTime(workInProgress); + nextEffect = nextNextEffect; + } + } // Read this again, since an effect might have updated it - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - return next; - } + remainingLanes = root.pendingLanes; // Check if there's remaining work on this root - if ( - returnFiber !== null && // Do not append effects to parents if a sibling failed to complete - (returnFiber.effectTag & Incomplete) === NoEffect - ) { - // Append all the effects of the subtree and this fiber onto the effect - // list of the parent. The completion order of the children affects the - // side-effect order. - if (returnFiber.firstEffect === null) { - returnFiber.firstEffect = workInProgress.firstEffect; + if (remainingLanes !== NoLanes) { + { + if (spawnedWorkDuringRender !== null) { + var expirationTimes = spawnedWorkDuringRender; + spawnedWorkDuringRender = null; + + for (var i = 0; i < expirationTimes.length; i++) { + scheduleInteractions( + root, + expirationTimes[i], + root.memoizedInteractions + ); } + } - if (workInProgress.lastEffect !== null) { - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = workInProgress.firstEffect; - } + schedulePendingInteractions(root, remainingLanes); + } + } else { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } - returnFiber.lastEffect = workInProgress.lastEffect; - } // If this fiber had side-effects, we append it AFTER the children's - // side-effects. We can perform certain side-effects earlier if needed, - // by doing multiple passes over the effect list. We don't want to - // schedule our own side-effect on our own list because if end up - // reusing children we'll schedule this effect onto itself since we're - // at the end. + { + if (!rootDidHavePassiveEffects) { + // If there are no passive effects, then we can complete the pending interactions. + // Otherwise, we'll wait until after the passive effects are flushed. + // Wait to do this until after remaining work has been scheduled, + // so that we don't prematurely signal complete for interactions when there's e.g. hidden work. + finishPendingInteractions(root, lanes); + } + } - var effectTag = workInProgress.effectTag; // Skip both NoWork and PerformedWork tags when creating the effect - // list. PerformedWork effect is read by React DevTools but shouldn't be - // committed. + if (remainingLanes === SyncLane) { + // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; + } + } else { + nestedUpdateCount = 0; + } - if (effectTag > PerformedWork) { - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = workInProgress; - } else { - returnFiber.firstEffect = workInProgress; - } + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + // additional work on this root is scheduled. - returnFiber.lastEffect = workInProgress; - } - } - } else { - // This fiber did not complete because something threw. Pop values off - // the stack without entering the complete phase. If this is a boundary, - // capture values if possible. - var _next = unwindWork(workInProgress); // Because this fiber did not complete, don't reset its expiration time. + ensureRootIsScheduled(root, now()); - if ((workInProgress.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false); // Include the time spent working on failed children before continuing. + if (hasUncaughtError) { + hasUncaughtError = false; + var _error3 = firstUncaughtError; + firstUncaughtError = null; + throw _error3; + } - var actualDuration = workInProgress.actualDuration; - var child = workInProgress.child; + if ((executionContext & LegacyUnbatchedContext) !== NoContext) { + // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired + // synchronously, but layout updates should be deferred until the end + // of the batch. - while (child !== null) { - actualDuration += child.actualDuration; - child = child.sibling; - } + return null; + } // If layout work was scheduled, flush it now. - workInProgress.actualDuration = actualDuration; - } + flushSyncCallbackQueue(); - if (_next !== null) { - // If completing this work spawned new work, do that next. We'll come - // back here again. - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - // TODO: The name stopFailedWorkTimer is misleading because Suspense - // also captures and restarts. - stopFailedWorkTimer(workInProgress); - _next.effectTag &= HostEffectMask; - return _next; - } + return null; +} - stopWorkTimer(workInProgress); +function commitBeforeMutationEffects() { + while (nextEffect !== null) { + var current = nextEffect.alternate; - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its effect list. - returnFiber.firstEffect = returnFiber.lastEffect = null; - returnFiber.effectTag |= Incomplete; + if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { + if ((nextEffect.flags & Deletion) !== NoFlags) { + if (doesFiberContain(nextEffect, focusedInstanceHandle)) { + shouldFireAfterActiveInstanceBlur = true; + } + } else { + // TODO: Move this out of the hot path using a dedicated effect tag. + if ( + nextEffect.tag === SuspenseComponent && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) + ) { + shouldFireAfterActiveInstanceBlur = true; + } } } - var siblingFiber = workInProgress.sibling; + var flags = nextEffect.flags; - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - return siblingFiber; - } // Otherwise, return to the parent + if ((flags & Snapshot) !== NoFlags) { + setCurrentFiber(nextEffect); + commitBeforeMutationLifeCycles(current, nextEffect); + resetCurrentFiber(); + } - workInProgress = returnFiber; - } while (workInProgress !== null); // We've reached the root. + if ((flags & Passive) !== NoFlags) { + // If there are passive effects, schedule a callback to flush at + // the earliest opportunity. + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); + } + } - if (workInProgressRootExitStatus === RootIncomplete) { - workInProgressRootExitStatus = RootCompleted; + nextEffect = nextEffect.nextEffect; } - - return null; } -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - var childExpirationTime = fiber.childExpirationTime; - return updateExpirationTime > childExpirationTime - ? updateExpirationTime - : childExpirationTime; -} +function commitMutationEffects(root, renderPriorityLevel) { + // TODO: Should probably move the bulk of this function to commitWork. + while (nextEffect !== null) { + setCurrentFiber(nextEffect); + var flags = nextEffect.flags; -function resetChildExpirationTime(completedWork) { - if ( - renderExpirationTime$1 !== Never && - completedWork.childExpirationTime === Never - ) { - // The children of this component are hidden. Don't bubble their - // expiration times. - return; - } + if (flags & Ref) { + var current = nextEffect.alternate; - var newChildExpirationTime = NoWork; // Bubble up the earliest expiration time. + if (current !== null) { + commitDetachRef(current); + } + } // The following switch statement is only concerned about placement, + // updates, and deletions. To avoid needing to add a case for every possible + // bitmap value, we remove the secondary effects from the effect tag and + // switch on that value. - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var actualDuration = completedWork.actualDuration; - var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will - // only be updated if work is done on the fiber (i.e. it doesn't bailout). - // When work is done, it should bubble to the parent's actualDuration. If - // the fiber has not been cloned though, (meaning no work was done), then - // this value will reflect the amount of time spent working on a previous - // render. In that case it should not bubble. We determine whether it was - // cloned by comparing the child pointer. + var primaryFlags = flags & (Placement | Update | Deletion | Hydrating); + + switch (primaryFlags) { + case Placement: { + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. + + nextEffect.flags &= ~Placement; + break; + } - var shouldBubbleActualDurations = - completedWork.alternate === null || - completedWork.child !== completedWork.alternate.child; - var child = completedWork.child; + case PlacementAndUpdate: { + // inserted, before any life-cycles like componentDidMount gets called. - while (child !== null) { - var childUpdateExpirationTime = child.expirationTime; - var childChildExpirationTime = child.childExpirationTime; + nextEffect.flags &= ~Placement; // Update - if (childUpdateExpirationTime > newChildExpirationTime) { - newChildExpirationTime = childUpdateExpirationTime; + var _current = nextEffect.alternate; + commitWork(_current, nextEffect); + break; } - if (childChildExpirationTime > newChildExpirationTime) { - newChildExpirationTime = childChildExpirationTime; + case Hydrating: { + nextEffect.flags &= ~Hydrating; + break; } - if (shouldBubbleActualDurations) { - actualDuration += child.actualDuration; + case HydratingAndUpdate: { + nextEffect.flags &= ~Hydrating; // Update + + var _current2 = nextEffect.alternate; + commitWork(_current2, nextEffect); + break; } - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; + case Update: { + var _current3 = nextEffect.alternate; + commitWork(_current3, nextEffect); + break; + } + + case Deletion: { + commitDeletion(root, nextEffect); + break; + } } - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + resetCurrentFiber(); + nextEffect = nextEffect.nextEffect; + } +} - while (_child !== null) { - var _childUpdateExpirationTime = _child.expirationTime; - var _childChildExpirationTime = _child.childExpirationTime; +function commitLayoutEffects(root, committedLanes) { + while (nextEffect !== null) { + setCurrentFiber(nextEffect); + var flags = nextEffect.flags; - if (_childUpdateExpirationTime > newChildExpirationTime) { - newChildExpirationTime = _childUpdateExpirationTime; - } + if (flags & (Update | Callback)) { + var current = nextEffect.alternate; + commitLifeCycles(root, current, nextEffect); + } - if (_childChildExpirationTime > newChildExpirationTime) { - newChildExpirationTime = _childChildExpirationTime; + { + if (flags & Ref) { + commitAttachRef(nextEffect); } - - _child = _child.sibling; } - } - completedWork.childExpirationTime = newChildExpirationTime; + resetCurrentFiber(); + nextEffect = nextEffect.nextEffect; + } } -function commitRoot(root) { - var renderPriorityLevel = getCurrentPriorityLevel(); - runWithPriority( - ImmediatePriority, - commitRootImpl.bind(null, root, renderPriorityLevel) - ); - return null; -} +function flushPassiveEffects() { + // Returns whether passive effects were flushed. + if (pendingPassiveEffectsRenderPriority !== NoPriority$1) { + var priorityLevel = + pendingPassiveEffectsRenderPriority > NormalPriority$1 + ? NormalPriority$1 + : pendingPassiveEffectsRenderPriority; + pendingPassiveEffectsRenderPriority = NoPriority$1; -function commitRootImpl(root, renderPriorityLevel) { - do { - // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which - // means `flushPassiveEffects` will sometimes result in additional - // passive effects. So we need to keep flushing in a loop until there are - // no more pending effects. - // TODO: Might be better if `flushPassiveEffects` did not automatically - // flush synchronous work at the end, to avoid factoring hazards like this. - flushPassiveEffects(); - } while (rootWithPendingPassiveEffects !== null); + { + return runWithPriority(priorityLevel, flushPassiveEffectsImpl); + } + } - flushRenderPhaseStrictModeWarningsInDEV(); + return false; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); } +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); - var finishedWork = root.finishedWork; - var expirationTime = root.finishedExpirationTime; + { + fiber.flags |= PassiveUnmountPendingDev; + var alternate = fiber.alternate; - if (finishedWork === null) { - return null; + if (alternate !== null) { + alternate.flags |= PassiveUnmountPendingDev; + } } - root.finishedWork = null; - root.finishedExpirationTime = NoWork; - - if (!(finishedWork !== root.current)) { - throw Error( - "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." - ); - } // commitRoot never returns a continuation; it always finishes synchronously. - // So we can clear these now to allow a new callback to be scheduled. + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); + } +} - root.callbackNode = null; - root.callbackExpirationTime = NoWork; - root.callbackPriority = NoPriority; - root.nextKnownPendingLevel = NoWork; - startCommitTimer(); // Update the first and last pending times on this root. The new first - // pending time is whatever is left on the root fiber. +function invokePassiveEffectCreate(effect) { + var create = effect.create; + effect.destroy = create(); +} - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - markRootFinishedAtTime( - root, - expirationTime, - remainingExpirationTimeBeforeCommit - ); +function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } - if (root === workInProgressRoot) { - // We can reset these now that they are finished. - workInProgressRoot = null; - workInProgress = null; - renderExpirationTime$1 = NoWork; - } // This indicates that the last root we worked on is not the same one that - // we're committing now. This most commonly happens when a suspended root - // times out. - // Get the list of effects. + var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; + rootWithPendingPassiveEffects = null; + pendingPassiveEffectsLanes = NoLanes; - var firstEffect; + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Cannot flush passive effects while already rendering."); + } - if (finishedWork.effectTag > PerformedWork) { - // A fiber's effect list consists only of its children, not itself. So if - // the root has an effect, we need to add it to the end of the list. The - // resulting list is the set that would belong to the root's parent, if it - // had one; that is, all the effects in the tree including the root. - if (finishedWork.lastEffect !== null) { - finishedWork.lastEffect.nextEffect = finishedWork; - firstEffect = finishedWork.firstEffect; - } else { - firstEffect = finishedWork; - } - } else { - // There is no effect on the root. - firstEffect = finishedWork.firstEffect; + { + isFlushingPassiveEffects = true; } - if (firstEffect !== null) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root); // Reset this to null before calling lifecycles + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + var prevInteractions = pushInteractions(root); // It's important that ALL pending passive effect destroy functions are called + // before ANY passive effect create functions are called. + // Otherwise effects in sibling components might interfere with each other. + // e.g. a destroy function in one component may unintentionally override a ref + // value set by a create function in another component. + // Layout effects have the same constraint. + // First pass: Destroy stale passive effects. + + var unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + + for (var i = 0; i < unmountEffects.length; i += 2) { + var _effect = unmountEffects[i]; + var fiber = unmountEffects[i + 1]; + var destroy = _effect.destroy; + _effect.destroy = undefined; - ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass - // of the effect list for each phase: all mutation effects come before all - // layout effects, and so on. - // The first phase a "before mutation" phase. We use this phase to read the - // state of the host tree right before we mutate it. This is where - // getSnapshotBeforeUpdate is called. + { + fiber.flags &= ~PassiveUnmountPendingDev; + var alternate = fiber.alternate; - startCommitSnapshotEffectsTimer(); - prepareForCommit(root.containerInfo); - nextEffect = firstEffect; + if (alternate !== null) { + alternate.flags &= ~PassiveUnmountPendingDev; + } + } - do { + if (typeof destroy === "function") { { - invokeGuardedCallback(null, commitBeforeMutationEffects, null); + setCurrentFiber(fiber); + + { + invokeGuardedCallback(null, destroy, null); + } if (hasCaughtError()) { - if (!(nextEffect !== null)) { + if (!(fiber !== null)) { throw Error("Should be working on an effect."); } var error = clearCaughtError(); - captureCommitPhaseError(nextEffect, error); - nextEffect = nextEffect.nextEffect; + captureCommitPhaseError(fiber, error); } + + resetCurrentFiber(); } - } while (nextEffect !== null); + } + } // Second pass: Create new passive effects. - stopCommitSnapshotEffectsTimer(); + var mountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); - } // The next phase is the mutation phase, where we mutate the host tree. + for (var _i = 0; _i < mountEffects.length; _i += 2) { + var _effect2 = mountEffects[_i]; + var _fiber = mountEffects[_i + 1]; - startCommitHostEffectsTimer(); - nextEffect = firstEffect; + { + setCurrentFiber(_fiber); - do { { - invokeGuardedCallback( - null, - commitMutationEffects, - null, - root, - renderPriorityLevel - ); + invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2); + } - if (hasCaughtError()) { - if (!(nextEffect !== null)) { - throw Error("Should be working on an effect."); - } + if (hasCaughtError()) { + if (!(_fiber !== null)) { + throw Error("Should be working on an effect."); + } - var _error = clearCaughtError(); + var _error4 = clearCaughtError(); - captureCommitPhaseError(nextEffect, _error); - nextEffect = nextEffect.nextEffect; - } + captureCommitPhaseError(_fiber, _error4); } - } while (nextEffect !== null); - stopCommitHostEffectsTimer(); - resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after - // the mutation phase, so that the previous tree is still current during - // componentWillUnmount, but before the layout phase, so that the finished - // work is current during componentDidMount/Update. + resetCurrentFiber(); + } + } // Note: This currently assumes there are no passive effects on the root fiber + // because the root is not part of its own effect list. + // This could change in the future. - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - // the host tree after it's been mutated. The idiomatic use case for this is - // layout, but class component lifecycles also fire here for legacy reasons. + var effect = root.current.firstEffect; - startCommitLifeCyclesTimer(); - nextEffect = firstEffect; + while (effect !== null) { + var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC - do { - { - invokeGuardedCallback( - null, - commitLayoutEffects, - null, - root, - expirationTime - ); + effect.nextEffect = null; - if (hasCaughtError()) { - if (!(nextEffect !== null)) { - throw Error("Should be working on an effect."); - } + if (effect.flags & Deletion) { + detachFiberAfterEffects(effect); + } - var _error2 = clearCaughtError(); + effect = nextNextEffect; + } + + { + popInteractions(prevInteractions); + finishPendingInteractions(root, lanes); + } + + { + isFlushingPassiveEffects = false; + } + + executionContext = prevExecutionContext; + flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + + nestedPassiveUpdateCount = + rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; + return true; +} + +function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ); +} +function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); + } +} + +function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; + } +} + +var onUncaughtError = prepareToThrowUncaughtError; + +function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValue(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + enqueueUpdate(rootFiber, update); + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(rootFiber, SyncLane); - captureCommitPhaseError(nextEffect, _error2); - nextEffect = nextEffect.nextEffect; - } - } - } while (nextEffect !== null); + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, SyncLane); + } +} - stopCommitLifeCyclesTimer(); - nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an - // opportunity to paint. +function captureCommitPhaseError(sourceFiber, error) { + if (sourceFiber.tag === HostRoot) { + // Error was thrown at the root. There is no parent, so the root + // itself should capture it. + captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error); + return; + } - requestPaint(); + var fiber = sourceFiber.return; - { - popInteractions(prevInteractions); - } + while (fiber !== null) { + if (fiber.tag === HostRoot) { + captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error); + return; + } else if (fiber.tag === ClassComponent) { + var ctor = fiber.type; + var instance = fiber.stateNode; - executionContext = prevExecutionContext; - } else { - // No effects. - root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were - // no effects. - // TODO: Maybe there's a better way to report this. + if ( + typeof ctor.getDerivedStateFromError === "function" || + (typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance)) + ) { + var errorInfo = createCapturedValue(error, sourceFiber); + var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); + enqueueUpdate(fiber, update); + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(fiber, SyncLane); - startCommitSnapshotEffectsTimer(); - stopCommitSnapshotEffectsTimer(); + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, SyncLane); + } else { + // This component has already been unmounted. + // We can't schedule any follow up work for the root because the fiber is already unmounted, + // but we can still call the log-only boundary so the error isn't swallowed. + // + // TODO This is only a temporary bandaid for the old reconciler fork. + // We can delete this special case once the new fork is merged. + if ( + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance) + ) { + try { + instance.componentDidCatch(error, errorInfo); + } catch (errorToIgnore) { + // TODO Ignore this error? Rethrow it? + // This is kind of an edge case. + } + } + } - { - recordCommitTime(); + return; + } } - startCommitHostEffectsTimer(); - stopCommitHostEffectsTimer(); - startCommitLifeCyclesTimer(); - stopCommitLifeCyclesTimer(); + fiber = fiber.return; } +} +function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - stopCommitTimer(); - var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; + if (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); + } - if (rootDoesHavePassiveEffects) { - // This commit has passive effects. Stash a reference to them. But don't - // schedule a callback until after flushing layout work. - rootDoesHavePassiveEffects = false; - rootWithPendingPassiveEffects = root; - pendingPassiveEffectsExpirationTime = expirationTime; - pendingPassiveEffectsRenderPriority = renderPriorityLevel; - } else { - // We are done with the effect chain at this point so let's clear the - // nextEffect pointers to assist with GC. If we have passive effects, we'll - // clear this in flushPassiveEffects. - nextEffect = firstEffect; + var eventTime = requestEventTime(); + markRootPinged(root, pingedLanes); - while (nextEffect !== null) { - var nextNextEffect = nextEffect.nextEffect; - nextEffect.nextEffect = null; - nextEffect = nextNextEffect; + if ( + workInProgressRoot === root && + isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) + ) { + // Received a ping at the same priority level at which we're currently + // rendering. We might want to restart this render. This should mirror + // the logic of whether or not a root suspends once it completes. + // TODO: If we're rendering sync either due to Sync, Batched or expired, + // we should probably never restart. + // If we're suspended with delay, or if it's a retry, we'll always suspend + // so we can always restart. + if ( + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Restart from the root. + prepareFreshStack(root, NoLanes); + } else { + // Even though we can't restart right now, we might get an + // opportunity later. So we mark this render as having a ping. + workInProgressRootPingedLanes = mergeLanes( + workInProgressRootPingedLanes, + pingedLanes + ); } - } // Check if there's remaining work on this root + } - var remainingExpirationTime = root.firstPendingTime; + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, pingedLanes); +} - if (remainingExpirationTime !== NoWork) { - { - if (spawnedWorkDuringRender !== null) { - var expirationTimes = spawnedWorkDuringRender; - spawnedWorkDuringRender = null; +function retryTimedOutBoundary(boundaryFiber, retryLane) { + // The boundary fiber (a Suspense component or SuspenseList component) + // previously was rendered in its fallback state. One of the promises that + // suspended it has resolved, which means at least part of the tree was + // likely unblocked. Try rendering again, at a new expiration time. + if (retryLane === NoLane) { + retryLane = requestRetryLane(boundaryFiber); + } // TODO: Special case idle priority? - for (var i = 0; i < expirationTimes.length; i++) { - scheduleInteractions( - root, - expirationTimes[i], - root.memoizedInteractions - ); - } - } + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); - schedulePendingInteractions(root, remainingExpirationTime); - } - } else { - // If there's no remaining work, we can clear the set of already failed - // error boundaries. - legacyErrorBoundariesThatAlreadyFailed = null; + if (root !== null) { + markRootUpdated(root, retryLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, retryLane); } +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default + + var retryCache; { - if (!rootDidHavePassiveEffects) { - // If there are no passive effects, then we can complete the pending interactions. - // Otherwise, we'll wait until after the passive effects are flushed. - // Wait to do this until after remaining work has been scheduled, - // so that we don't prematurely signal complete for interactions when there's e.g. hidden work. - finishPendingInteractions(root, expirationTime); - } + retryCache = boundaryFiber.stateNode; } - if (remainingExpirationTime === Sync) { - // Count the number of times the root synchronously re-renders without - // finishing. If there are too many, it indicates an infinite update loop. - if (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; - } - } else { - nestedUpdateCount = 0; + if (retryCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(wakeable); } - onCommitRoot(finishedWork.stateNode, expirationTime); // Always call this before exiting `commitRoot`, to ensure that any - // additional work on this root is scheduled. + retryTimedOutBoundary(boundaryFiber, retryLane); +} // Computes the next Just Noticeable Difference (JND) boundary. +// The theory is that a person can't tell the difference between small differences in time. +// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable +// difference in the experience. However, waiting for longer might mean that we can avoid +// showing an intermediate loading state. The longer we have already waited, the harder it +// is to tell small differences in time. Therefore, the longer we've already waited, +// the longer we can wait additionally. At some point we have to give up though. +// We pick a train model where the next boundary commits at a consistent schedule. +// These particular numbers are vague estimates. We expect to adjust them based on research. + +function jnd(timeElapsed) { + return timeElapsed < 120 + ? 120 + : timeElapsed < 480 + ? 480 + : timeElapsed < 1080 + ? 1080 + : timeElapsed < 1920 + ? 1920 + : timeElapsed < 3000 + ? 3000 + : timeElapsed < 4320 + ? 4320 + : ceil(timeElapsed / 1960) * 1960; +} - ensureRootIsScheduled(root); +function checkForNestedUpdates() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + rootWithNestedUpdates = null; - if (hasUncaughtError) { - hasUncaughtError = false; - var _error3 = firstUncaughtError; - firstUncaughtError = null; - throw _error3; + { + throw Error( + "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." + ); + } } - if ((executionContext & LegacyUnbatchedContext) !== NoContext) { - // This is a legacy edge case. We just committed the initial mount of - // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired - // synchronously, but layout updates should be deferred until the end - // of the batch. - return null; - } // If layout work was scheduled, flush it now. + { + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; - flushSyncCallbackQueue(); - return null; + error( + "Maximum update depth exceeded. This can happen when a component " + + "calls setState inside useEffect, but useEffect either doesn't " + + "have a dependency array, or one of the dependencies changes on " + + "every render." + ); + } + } } -function commitBeforeMutationEffects() { - while (nextEffect !== null) { - var effectTag = nextEffect.effectTag; - - if ((effectTag & Snapshot) !== NoEffect) { - setCurrentFiber(nextEffect); - recordEffect(); - var current = nextEffect.alternate; - commitBeforeMutationLifeCycles(current, nextEffect); - resetCurrentFiber(); - } +function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); - if ((effectTag & Passive) !== NoEffect) { - // If there are passive effects, schedule a callback to flush at - // the earliest opportunity. - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(NormalPriority, function() { - flushPassiveEffects(); - return null; - }); - } + { + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); } - - nextEffect = nextEffect.nextEffect; } } -function commitMutationEffects(root, renderPriorityLevel) { - // TODO: Should probably move the bulk of this function to commitWork. - while (nextEffect !== null) { - setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; +var didWarnStateUpdateForNotYetMountedComponent = null; - if (effectTag & Ref) { - var current = nextEffect.alternate; +function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { + { + if ((executionContext & RenderContext) !== NoContext) { + // We let the other warning about render phase updates deal with this one. + return; + } - if (current !== null) { - commitDetachRef(current); - } - } // The following switch statement is only concerned about placement, - // updates, and deletions. To avoid needing to add a case for every possible - // bitmap value, we remove the secondary effects from the effect tag and - // switch on that value. + if (!(fiber.mode & (BlockingMode | ConcurrentMode))) { + return; + } + + var tag = fiber.tag; - var primaryEffectTag = - effectTag & (Placement | Update | Deletion | Hydrating); + if ( + tag !== IndeterminateComponent && + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. - switch (primaryEffectTag) { - case Placement: { - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. + var componentName = getComponentName(fiber.type) || "ReactComponent"; - nextEffect.effectTag &= ~Placement; - break; + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; } - case PlacementAndUpdate: { - // inserted, before any life-cycles like componentDidMount gets called. + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + } - nextEffect.effectTag &= ~Placement; // Update + var previousFiber = current; - var _current = nextEffect.alternate; - commitWork(_current, nextEffect); - break; - } + try { + setCurrentFiber(fiber); - case Hydrating: { - nextEffect.effectTag &= ~Hydrating; - break; + error( + "Can't perform a React state update on a component that hasn't mounted yet. " + + "This indicates that you have a side-effect in your render function that " + + "asynchronously later calls tries to update the component. Move this work to " + + "useEffect instead." + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); } + } + } +} - case HydratingAndUpdate: { - nextEffect.effectTag &= ~Hydrating; // Update +var didWarnStateUpdateForUnmountedComponent = null; - var _current2 = nextEffect.alternate; - commitWork(_current2, nextEffect); - break; - } +function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { + { + var tag = fiber.tag; - case Update: { - var _current3 = nextEffect.alternate; - commitWork(_current3, nextEffect); - break; - } + if ( + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // If there are pending passive effects unmounts for this Fiber, + // we can assume that they would have prevented this update. - case Deletion: { - commitDeletion(root, nextEffect, renderPriorityLevel); - break; - } - } // TODO: Only record a mutation effect if primaryEffectTag is non-zero. + if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) { + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. - recordEffect(); - resetCurrentFiber(); - nextEffect = nextEffect.nextEffect; - } -} + var componentName = getComponentName(fiber.type) || "ReactComponent"; -function commitLayoutEffects(root, committedExpirationTime) { - // TODO: Should probably move the bulk of this function to commitWork. - while (nextEffect !== null) { - setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + if (didWarnStateUpdateForUnmountedComponent !== null) { + if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { + return; + } - if (effectTag & (Update | Callback)) { - recordEffect(); - var current = nextEffect.alternate; - commitLifeCycles(root, current, nextEffect); + didWarnStateUpdateForUnmountedComponent.add(componentName); + } else { + didWarnStateUpdateForUnmountedComponent = new Set([componentName]); } - if (effectTag & Ref) { - recordEffect(); - commitAttachRef(nextEffect); - } + if (isFlushingPassiveEffects); + else { + var previousFiber = current; - resetCurrentFiber(); - nextEffect = nextEffect.nextEffect; - } -} + try { + setCurrentFiber(fiber); -function flushPassiveEffects() { - if (pendingPassiveEffectsRenderPriority !== NoPriority) { - var priorityLevel = - pendingPassiveEffectsRenderPriority > NormalPriority - ? NormalPriority - : pendingPassiveEffectsRenderPriority; - pendingPassiveEffectsRenderPriority = NoPriority; - return runWithPriority(priorityLevel, flushPassiveEffectsImpl); + error( + "Can't perform a React state update on an unmounted component. This " + + "is a no-op, but it indicates a memory leak in your application. To " + + "fix, cancel all subscriptions and asynchronous tasks in %s.", + tag === ClassComponent + ? "the componentWillUnmount method" + : "a useEffect cleanup function" + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } } -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } +var beginWork$1; - var root = rootWithPendingPassiveEffects; - var expirationTime = pendingPassiveEffectsExpirationTime; - rootWithPendingPassiveEffects = null; - pendingPassiveEffectsExpirationTime = NoWork; +{ + var dummyFiber = null; - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Cannot flush passive effects while already rendering."); - } + beginWork$1 = function(current, unitOfWork, lanes) { + // If a component throws an error, we replay it again in a synchronously + // dispatched event, so that the debugger will treat it as an uncaught + // error See ReactErrorUtils for more information. + // Before entering the begin phase, copy the work-in-progress onto a dummy + // fiber. If beginWork throws, we'll use this to reset the state. + var originalWorkInProgressCopy = assignFiberPropertiesInDEV( + dummyFiber, + unitOfWork + ); - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root); + try { + return beginWork(current, unitOfWork, lanes); + } catch (originalError) { + if ( + originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function" + ) { + // Don't replay promises. Treat everything else like an error. + throw originalError; + } // Keep this code in sync with handleError; any changes here must have + // corresponding changes there. - { - // Note: This currently assumes there are no passive effects on the root fiber - // because the root is not part of its own effect list. - // This could change in the future. - var _effect2 = root.current.firstEffect; + resetContextDependencies(); + resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame - while (_effect2 !== null) { - { - setCurrentFiber(_effect2); - invokeGuardedCallback(null, commitPassiveHookEffects, null, _effect2); + unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber. - if (hasCaughtError()) { - if (!(_effect2 !== null)) { - throw Error("Should be working on an effect."); - } + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - var _error5 = clearCaughtError(); + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. - captureCommitPhaseError(_effect2, _error5); - } + invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); - resetCurrentFiber(); + if (hasCaughtError()) { + var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`. + // Rethrow this error instead of the original one. + + throw replayError; + } else { + // This branch is reachable if the render phase is impure. + throw originalError; } + } + }; +} - var nextNextEffect = _effect2.nextEffect; // Remove nextEffect pointer to assist GC +var didWarnAboutUpdateInRender = false; +var didWarnAboutUpdateInRenderForAnotherComponent; - _effect2.nextEffect = null; - _effect2 = nextNextEffect; - } - } +{ + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); +} +function warnAboutRenderPhaseUpdatesInDEV(fiber) { { - popInteractions(prevInteractions); - finishPendingInteractions(root, expirationTime); - } - - executionContext = prevExecutionContext; - flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. + if ( + isRendering && + (executionContext & RenderContext) !== NoContext && + !getIsUpdatingOpaqueValueInRenderPhaseInDEV() + ) { + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + var renderingComponentName = + (workInProgress && getComponentName(workInProgress.type)) || + "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. - nestedPassiveUpdateCount = - rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; - return true; -} + var dedupeKey = renderingComponentName; -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentName(fiber.type) || "Unknown"; -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; - } -} + error( + "Cannot update a component (`%s`) while rendering a " + + "different component (`%s`). To locate the bad setState() call inside `%s`, " + + "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", + setStateComponentName, + renderingComponentName, + renderingComponentName + ); + } -var onUncaughtError = prepareToThrowUncaughtError; + break; + } -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValue(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, Sync); - enqueueUpdate(rootFiber, update); - var root = markUpdateTimeFromFiberToRoot(rootFiber, Sync); + case ClassComponent: { + if (!didWarnAboutUpdateInRender) { + error( + "Cannot update during an existing state transition (such as " + + "within `render`). Render methods should be a pure " + + "function of props and state." + ); - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, Sync); - } -} + didWarnAboutUpdateInRender = true; + } -function captureCommitPhaseError(sourceFiber, error) { - if (sourceFiber.tag === HostRoot) { - // Error was thrown at the root. There is no parent, so the root - // itself should capture it. - captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error); - return; + break; + } + } + } } +} // a 'shared' variable that changes when act() opens/closes in tests. - var fiber = sourceFiber.return; +var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked +// scheduler is the actual recommendation. The alternative could be a testing build, +// a new lib, or whatever; we dunno just yet. This message is for early adopters +// to get their tests right. - while (fiber !== null) { - if (fiber.tag === HostRoot) { - captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error); - return; - } else if (fiber.tag === ClassComponent) { - var ctor = fiber.type; - var instance = fiber.stateNode; +function warnIfUnmockedScheduler(fiber) { + { + if ( + didWarnAboutUnmockedScheduler === false && + Scheduler.unstable_flushAllWithoutAsserting === undefined + ) { + if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { + didWarnAboutUnmockedScheduler = true; - if ( - typeof ctor.getDerivedStateFromError === "function" || - (typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance)) - ) { - var errorInfo = createCapturedValue(error, sourceFiber); - var update = createClassErrorUpdate( - fiber, - errorInfo, // TODO: This is always sync - Sync + error( + 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + + "to guarantee consistent behaviour across tests and browsers. " + + "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. + "jest.mock('scheduler', () => require" + + "('scheduler/unstable_mock'));\n\n" + + "For more info, visit https://reactjs.org/link/mock-scheduler" ); - enqueueUpdate(fiber, update); - var root = markUpdateTimeFromFiberToRoot(fiber, Sync); - - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, Sync); - } - - return; } } - - fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { - var pingCache = root.pingCache; - - if (pingCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - pingCache.delete(thenable); - } - - if (workInProgressRoot === root && renderExpirationTime$1 === suspendedTime) { - // Received a ping at the same priority level at which we're currently - // rendering. We might want to restart this render. This should mirror - // the logic of whether or not a root suspends once it completes. - // TODO: If we're rendering sync either due to Sync, Batched or expired, - // we should probably never restart. - // If we're suspended with delay, we'll always suspend so we can always - // restart. If we're suspended without any updates, it might be a retry. - // If it's early in the retry we can restart. We can't know for sure - // whether we'll eventually process an update during this render pass, - // but it's somewhat unlikely that we get to a ping before that, since - // getting to the root most update is usually very fast. - if ( - workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - workInProgressRootLatestProcessedExpirationTime === Sync && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ) { - // Restart from the root. Don't need to schedule a ping because - // we're already working on this tree. - prepareFreshStack(root, renderExpirationTime$1); - } else { - // Even though we can't restart right now, we might get an - // opportunity later. So we mark this render as having a ping. - workInProgressRootHasPendingPing = true; - } - return; - } +function computeThreadID(root, lane) { + // Interaction threads are unique per root and expiration time. + // NOTE: Intentionally unsound cast. All that matters is that it's a number + // and it represents a batch of work. Could make a helper function instead, + // but meh this is fine for now. + return lane * 1000 + root.interactionThreadID; +} - if (!isRootSuspendedAtTime(root, suspendedTime)) { - // The root is no longer suspended at this time. - return; +function markSpawnedWork(lane) { + if (spawnedWorkDuringRender === null) { + spawnedWorkDuringRender = [lane]; + } else { + spawnedWorkDuringRender.push(lane); } +} - var lastPingedTime = root.lastPingedTime; +function scheduleInteractions(root, lane, interactions) { + if (interactions.size > 0) { + var pendingInteractionMap = root.pendingInteractionMap; + var pendingInteractions = pendingInteractionMap.get(lane); - if (lastPingedTime !== NoWork && lastPingedTime < suspendedTime) { - // There's already a lower priority ping scheduled. - return; - } // Mark the time at which this ping was scheduled. + if (pendingInteractions != null) { + interactions.forEach(function(interaction) { + if (!pendingInteractions.has(interaction)) { + // Update the pending async work count for previously unscheduled interaction. + interaction.__count++; + } - root.lastPingedTime = suspendedTime; - ensureRootIsScheduled(root); - schedulePendingInteractions(root, suspendedTime); -} + pendingInteractions.add(interaction); + }); + } else { + pendingInteractionMap.set(lane, new Set(interactions)); // Update the pending async work count for the current interactions. -function retryTimedOutBoundary(boundaryFiber, retryTime) { - // The boundary fiber (a Suspense component or SuspenseList component) - // previously was rendered in its fallback state. One of the promises that - // suspended it has resolved, which means at least part of the tree was - // likely unblocked. Try rendering again, at a new expiration time. - if (retryTime === NoWork) { - var suspenseConfig = null; // Retries don't carry over the already committed update. - - var currentTime = requestCurrentTimeForUpdate(); - retryTime = computeExpirationForFiber( - currentTime, - boundaryFiber, - suspenseConfig - ); - } // TODO: Special case idle priority? + interactions.forEach(function(interaction) { + interaction.__count++; + }); + } - var root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime); + var subscriber = tracing.__subscriberRef.current; - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, retryTime); + if (subscriber !== null) { + var threadID = computeThreadID(root, lane); + subscriber.onWorkScheduled(interactions, threadID); + } } } -function resolveRetryThenable(boundaryFiber, thenable) { - var retryTime = NoWork; // Default - var retryCache; +function schedulePendingInteractions(root, lane) { + scheduleInteractions(root, lane, tracing.__interactionsRef.current); +} - { - retryCache = boundaryFiber.stateNode; - } +function startWorkOnPendingInteractions(root, lanes) { + // we can accurately attribute time spent working on it, And so that cascading + // work triggered during the render phase will be associated with it. - if (retryCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(thenable); - } + var interactions = new Set(); + root.pendingInteractionMap.forEach(function( + scheduledInteractions, + scheduledLane + ) { + if (includesSomeLane(lanes, scheduledLane)) { + scheduledInteractions.forEach(function(interaction) { + return interactions.add(interaction); + }); + } + }); // Store the current set of interactions on the FiberRoot for a few reasons: + // We can re-use it in hot functions like performConcurrentWorkOnRoot() + // without having to recalculate it. We will also use it in commitWork() to + // pass to any Profiler onRender() hooks. This also provides DevTools with a + // way to access it when the onCommitRoot() hook is called. - retryTimedOutBoundary(boundaryFiber, retryTime); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. + root.memoizedInteractions = interactions; -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; -} + if (interactions.size > 0) { + var subscriber = tracing.__subscriberRef.current; -function computeMsUntilSuspenseLoadingDelay( - mostRecentEventTime, - committedExpirationTime, - suspenseConfig -) { - var busyMinDurationMs = suspenseConfig.busyMinDurationMs | 0; + if (subscriber !== null) { + var threadID = computeThreadID(root, lanes); - if (busyMinDurationMs <= 0) { - return 0; + try { + subscriber.onWorkStarted(interactions, threadID); + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } + } } +} - var busyDelayMs = suspenseConfig.busyDelayMs | 0; // Compute the time until this render pass would expire. +function finishPendingInteractions(root, committedLanes) { + var remainingLanesAfterCommit = root.pendingLanes; + var subscriber; - var currentTimeMs = now(); - var eventTimeMs = inferTimeFromExpirationTimeWithSuspenseConfig( - mostRecentEventTime, - suspenseConfig - ); - var timeElapsed = currentTimeMs - eventTimeMs; + try { + subscriber = tracing.__subscriberRef.current; - if (timeElapsed <= busyDelayMs) { - // If we haven't yet waited longer than the initial delay, we don't - // have to wait any additional time. - return 0; - } + if (subscriber !== null && root.memoizedInteractions.size > 0) { + // FIXME: More than one lane can finish in a single commit. + var threadID = computeThreadID(root, committedLanes); + subscriber.onWorkStopped(root.memoizedInteractions, threadID); + } + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } finally { + // Clear completed interactions from the pending Map. + // Unless the render was suspended or cascading work was scheduled, + // In which case– leave pending interactions until the subsequent render. + var pendingInteractionMap = root.pendingInteractionMap; + pendingInteractionMap.forEach(function(scheduledInteractions, lane) { + // Only decrement the pending interaction count if we're done. + // If there's still work at the current priority, + // That indicates that we are waiting for suspense data. + if (!includesSomeLane(remainingLanesAfterCommit, lane)) { + pendingInteractionMap.delete(lane); + scheduledInteractions.forEach(function(interaction) { + interaction.__count--; - var msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed; // This is the value that is passed to `setTimeout`. + if (subscriber !== null && interaction.__count === 0) { + try { + subscriber.onInteractionScheduledWorkCompleted(interaction); + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } + } + }); + } + }); + } +} // `act` testing API - return msUntilTimeout; +function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return actingUpdatesScopeDepth > 0; } +// so we can tell if any async act() calls try to run in parallel. -function checkForNestedUpdates() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - rootWithNestedUpdates = null; +var actingUpdatesScopeDepth = 0; - { - throw Error( - "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." - ); - } - } +function detachFiberAfterEffects(fiber) { + fiber.sibling = null; + fiber.stateNode = null; +} - { - if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { - nestedPassiveUpdateCount = 0; +var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. - error( - "Maximum update depth exceeded. This can happen when a component " + - "calls setState inside useEffect, but useEffect either doesn't " + - "have a dependency array, or one of the dependencies changes on " + - "every render." - ); - } +var failedBoundaries = null; +var setRefreshHandler = function(handler) { + { + resolveFamily = handler; } -} - -function flushRenderPhaseStrictModeWarningsInDEV() { +}; +function resolveFunctionForHotReloading(type) { { - ReactStrictModeWarnings.flushLegacyContextWarning(); - - { - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; } - } -} -function stopFinishedWorkLoopTimer() { - var didCompleteRoot = true; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} + var family = resolveFamily(type); -function stopInterruptedWorkLoopTimer() { - // TODO: Track which fiber caused the interruption. - var didCompleteRoot = false; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} + if (family === undefined) { + return type; + } // Use the latest known implementation. -function checkForInterruption(fiberThatReceivedUpdate, updateExpirationTime) { - if ( - workInProgressRoot !== null && - updateExpirationTime > renderExpirationTime$1 - ) { - interruptedBy = fiberThatReceivedUpdate; + return family.current; } } +function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); +} +function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } -var didWarnStateUpdateForUnmountedComponent = null; + var family = resolveFamily(type); -function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { - { - var tag = fiber.tag; + if (family === undefined) { + // Check if we're dealing with a real forwardRef. Don't want to crash early. + if ( + type !== null && + type !== undefined && + typeof type.render === "function" + ) { + // ForwardRef is special because its resolved .type is an object, + // but it's possible that we only have its inner render function in the map. + // If that inner render function is different, we'll build a new forwardRef type. + var currentRender = resolveFunctionForHotReloading(type.render); - if ( - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } - // the problematic code almost always lies inside that component. + if (type.render !== currentRender) { + var syntheticType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: currentRender + }; - var componentName = getComponentName(fiber.type) || "ReactComponent"; + if (type.displayName !== undefined) { + syntheticType.displayName = type.displayName; + } - if (didWarnStateUpdateForUnmountedComponent !== null) { - if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { - return; + return syntheticType; + } } - didWarnStateUpdateForUnmountedComponent.add(componentName); - } else { - didWarnStateUpdateForUnmountedComponent = new Set([componentName]); - } + return type; + } // Use the latest known implementation. - error( - "Can't perform a React state update on an unmounted component. This " + - "is a no-op, but it indicates a memory leak in your application. To " + - "fix, cancel all subscriptions and asynchronous tasks in %s.%s", - tag === ClassComponent - ? "the componentWillUnmount method" - : "a useEffect cleanup function", - getStackByFiberInDevAndProd(fiber) - ); + return family.current; } } +function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } -var beginWork$1; + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. -{ - var dummyFiber = null; + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - beginWork$1 = function(current, unitOfWork, expirationTime) { - // If a component throws an error, we replay it again in a synchronously - // dispatched event, so that the debugger will treat it as an uncaught - // error See ReactErrorUtils for more information. - // Before entering the begin phase, copy the work-in-progress onto a dummy - // fiber. If beginWork throws, we'll use this to reset the state. - var originalWorkInProgressCopy = assignFiberPropertiesInDEV( - dummyFiber, - unitOfWork - ); + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } - try { - return beginWork(current, unitOfWork, expirationTime); - } catch (originalError) { - if ( - originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function" - ) { - // Don't replay promises. Treat everything else like an error. - throw originalError; - } // Keep this code in sync with handleError; any changes here must have - // corresponding changes there. + break; + } - resetContextDependencies(); - resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + case FunctionComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + // We don't know the inner type yet. + // We're going to assume that the lazy inner type is stable, + // and so it is sufficient to avoid reconciling it away. + // We're not going to unwrap or actually use the new lazy type. + needsCompareFamilies = true; + } - unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber. + break; + } - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + break; + } - invokeGuardedCallback( - null, - beginWork, - null, - current, - unitOfWork, - expirationTime - ); + case MemoComponent: + case SimpleMemoComponent: { + if ($$typeofNextType === REACT_MEMO_TYPE) { + // TODO: if it was but can no longer be simple, + // we shouldn't set this. + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - if (hasCaughtError()) { - var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`. - // Rethrow this error instead of the original one. + break; + } - throw replayError; - } else { - // This branch is reachable if the render phase is impure. - throw originalError; + default: + return false; + } // Check if both types have a family and it's the same one. + + if (needsCompareFamilies) { + // Note: memo() and forwardRef() we'll compare outer rather than inner type. + // This means both of them need to be registered to preserve state. + // If we unwrapped and compared the inner types for wrappers instead, + // then we would risk falsely saying two separate memo(Foo) + // calls are equivalent because they wrap the same Foo function. + var prevFamily = resolveFamily(prevType); + + if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { + return true; } } - }; -} - -var didWarnAboutUpdateInRender = false; -function warnAboutRenderPhaseUpdatesInDEV(fiber) { + return false; + } +} +function markFailedErrorBoundaryForHotReloading(fiber) { { - if ((executionContext & RenderContext) !== NoContext) { - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - error( - "Cannot update a component from inside the function body of a " + - "different component." - ); - - break; - } + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } - case ClassComponent: { - if (isRendering && !didWarnAboutUpdateInRender) { - error( - "Cannot update during an existing state transition (such as " + - "within `render`). Render methods should be a pure " + - "function of props and state." - ); + if (typeof WeakSet !== "function") { + return; + } - didWarnAboutUpdateInRender = true; - break; - } - } - } + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); } + + failedBoundaries.add(fiber); } -} // a 'shared' variable that changes when act() opens/closes in tests. +} +var scheduleRefresh = function(root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } -var IsThisRendererActing = { - current: false + var staleFamilies = update.staleFamilies, + updatedFamilies = update.updatedFamilies; + flushPassiveEffects(); + flushSync(function() { + scheduleFibersWithFamiliesRecursively( + root.current, + updatedFamilies, + staleFamilies + ); + }); + } }; +var scheduleRoot = function(root, element) { + { + if (root.context !== emptyContextObject) { + // Super edge case: root has a legacy _renderSubtree context + // but we don't know the parentComponent so we can't pass it. + // Just ignore. We'll delete this with _renderSubtree code path later. + return; + } -var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked -// scheduler is the actual recommendation. The alternative could be a testing build, -// a new lib, or whatever; we dunno just yet. This message is for early adopters -// to get their tests right. + flushPassiveEffects(); + flushSync(function() { + updateContainer(element, root, null, null); + }); + } +}; -function warnIfUnmockedScheduler(fiber) { +function scheduleFibersWithFamiliesRecursively( + fiber, + updatedFamilies, + staleFamilies +) { { - if ( - didWarnAboutUnmockedScheduler === false && - Scheduler.unstable_flushAllWithoutAsserting === undefined - ) { - if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { - didWarnAboutUnmockedScheduler = true; + var alternate = fiber.alternate, + child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; - error( - 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + - "to guarantee consistent behaviour across tests and browsers. " + - "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. - "jest.mock('scheduler', () => require" + - "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" - ); - } + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; + + case ForwardRef: + candidateType = type.render; + break; } - } -} -function computeThreadID(root, expirationTime) { - // Interaction threads are unique per root and expiration time. - return expirationTime * 1000 + root.interactionThreadID; -} + if (resolveFamily === null) { + throw new Error("Expected resolveFamily to be set during hot reload."); + } -function markSpawnedWork(expirationTime) { - if (spawnedWorkDuringRender === null) { - spawnedWorkDuringRender = [expirationTime]; - } else { - spawnedWorkDuringRender.push(expirationTime); - } -} + var needsRender = false; + var needsRemount = false; -function scheduleInteractions(root, expirationTime, interactions) { - if (interactions.size > 0) { - var pendingInteractionMap = root.pendingInteractionMap; - var pendingInteractions = pendingInteractionMap.get(expirationTime); + if (candidateType !== null) { + var family = resolveFamily(candidateType); - if (pendingInteractions != null) { - interactions.forEach(function(interaction) { - if (!pendingInteractions.has(interaction)) { - // Update the pending async work count for previously unscheduled interaction. - interaction.__count++; + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } } + } + } - pendingInteractions.add(interaction); - }); - } else { - pendingInteractionMap.set(expirationTime, new Set(interactions)); // Update the pending async work count for the current interactions. + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; + } + } - interactions.forEach(function(interaction) { - interaction.__count++; - }); + if (needsRemount) { + fiber._debugNeedsRemount = true; } - var subscriber = tracing.__subscriberRef.current; + if (needsRemount || needsRender) { + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } - if (subscriber !== null) { - var threadID = computeThreadID(root, expirationTime); - subscriber.onWorkScheduled(interactions, threadID); + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); } - } -} -function schedulePendingInteractions(root, expirationTime) { - scheduleInteractions(root, expirationTime, tracing.__interactionsRef.current); + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } -function startWorkOnPendingInteractions(root, expirationTime) { - // we can accurately attribute time spent working on it, And so that cascading - // work triggered during the render phase will be associated with it. +var findHostInstancesForRefresh = function(root, families) { + { + var hostInstances = new Set(); + var types = new Set( + families.map(function(family) { + return family.current; + }) + ); + findHostInstancesForMatchingFibersRecursively( + root.current, + types, + hostInstances + ); + return hostInstances; + } +}; - var interactions = new Set(); - root.pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - if (scheduledExpirationTime >= expirationTime) { - scheduledInteractions.forEach(function(interaction) { - return interactions.add(interaction); - }); - } - }); // Store the current set of interactions on the FiberRoot for a few reasons: - // We can re-use it in hot functions like performConcurrentWorkOnRoot() - // without having to recalculate it. We will also use it in commitWork() to - // pass to any Profiler onRender() hooks. This also provides DevTools with a - // way to access it when the onCommitRoot() hook is called. +function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances +) { + { + var child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; - root.memoizedInteractions = interactions; + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if (interactions.size > 0) { - var subscriber = tracing.__subscriberRef.current; + case ForwardRef: + candidateType = type.render; + break; + } - if (subscriber !== null) { - var threadID = computeThreadID(root, expirationTime); + var didMatch = false; - try { - subscriber.onWorkStarted(interactions, threadID); - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; } } - } -} - -function finishPendingInteractions(root, committedExpirationTime) { - var earliestRemainingTimeAfterCommit = root.firstPendingTime; - var subscriber; - - try { - subscriber = tracing.__subscriberRef.current; - if (subscriber !== null && root.memoizedInteractions.size > 0) { - var threadID = computeThreadID(root, committedExpirationTime); - subscriber.onWorkStopped(root.memoizedInteractions, threadID); + if (didMatch) { + // We have a match. This only drills down to the closest host components. + // There's no need to search deeper because for the purpose of giving + // visual feedback, "flashing" outermost parent rectangles is sufficient. + findHostInstancesForFiberShallowly(fiber, hostInstances); + } else { + // If there's no match, maybe there will be one further down in the child tree. + if (child !== null) { + findHostInstancesForMatchingFibersRecursively( + child, + types, + hostInstances + ); + } } - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); - } finally { - // Clear completed interactions from the pending Map. - // Unless the render was suspended or cascading work was scheduled, - // In which case– leave pending interactions until the subsequent render. - var pendingInteractionMap = root.pendingInteractionMap; - pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - // Only decrement the pending interaction count if we're done. - // If there's still work at the current priority, - // That indicates that we are waiting for suspense data. - if (scheduledExpirationTime > earliestRemainingTimeAfterCommit) { - pendingInteractionMap.delete(scheduledExpirationTime); - scheduledInteractions.forEach(function(interaction) { - interaction.__count--; - if (subscriber !== null && interaction.__count === 0) { - try { - subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); - } - } - }); - } - }); + if (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); + } } } -var onScheduleFiberRoot = null; -var onCommitFiberRoot = null; -var onCommitFiberUnmount = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } +function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } + var node = fiber; - if (!hook.supportsFiber) { - { - error( - "The installed version of React DevTools is too old and will not work " + - "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" - ); - } // DevTools exists, even though it doesn't support Fiber. + while (true) { + switch (node.tag) { + case HostComponent: + hostInstances.add(node.stateNode); + return; - return true; - } + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; - try { - var rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - if (true) { - // Only used by Fast Refresh - if (typeof hook.onScheduleFiberRoot === "function") { - onScheduleFiberRoot = function(root, children) { - try { - hook.onScheduleFiberRoot(rendererID, root, children); - } catch (err) { - if (true && !hasLoggedError) { - hasLoggedError = true; - - error("React instrumentation encountered an error: %s", err); - } - } - }; + if (node.return === null) { + throw new Error("Expected to reach root first."); } - } - onCommitFiberRoot = function(root, expirationTime) { - try { - var didError = (root.current.effectTag & DidCapture) === DidCapture; + node = node.return; + } + } +} - if (enableProfilerTimer) { - var currentTime = getCurrentTime(); - var priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - hook.onCommitFiberRoot(rendererID, root, priorityLevel, didError); - } else { - hook.onCommitFiberRoot(rendererID, root, undefined, didError); - } - } catch (err) { - if (true) { - if (!hasLoggedError) { - hasLoggedError = true; +function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; - error("React instrumentation encountered an error: %s", err); - } - } + while (true) { + if (node.tag === HostComponent) { + // We got a match. + foundHostInstances = true; + hostInstances.add(node.stateNode); // There may still be more, so keep searching. + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - if (true) { - if (!hasLoggedError) { - hasLoggedError = true; + if (node === fiber) { + return foundHostInstances; + } - error("React instrumentation encountered an error: %s", err); - } + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; } + + node = node.return; } - }; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); - } - } // DevTools exists - return true; -} -function onScheduleRoot(root, children) { - if (typeof onScheduleFiberRoot === "function") { - onScheduleFiberRoot(root, children); - } -} -function onCommitRoot(root, expirationTime) { - if (typeof onCommitFiberRoot === "function") { - onCommitFiberRoot(root, expirationTime); - } -} -function onCommitUnmount(fiber) { - if (typeof onCommitFiberUnmount === "function") { - onCommitFiberUnmount(fiber); + node.sibling.return = node.return; + node = node.sibling; + } } + + return false; } var hasBadMapPolyfill; @@ -19031,13 +19946,11 @@ var hasBadMapPolyfill; try { var nonExtensibleObject = Object.preventExtensions({}); - var testMap = new Map([[nonExtensibleObject, null]]); - var testSet = new Set([nonExtensibleObject]); // This is necessary for Rollup to not consider these unused. - // https://github.com/rollup/rollup/issues/1771 - // TODO: we can remove these if Rollup fixes the bug. + /* eslint-disable no-new */ - testMap.set(0, 0); - testSet.add(0); + new Map([[nonExtensibleObject, null]]); + new Set([nonExtensibleObject]); + /* eslint-enable no-new */ } catch (e) { // TODO: Consider warning about bad polyfills hasBadMapPolyfill = true; @@ -19066,12 +19979,12 @@ function FiberNode(tag, pendingProps, key, mode) { this.dependencies = null; this.mode = mode; // Effects - this.effectTag = NoEffect; + this.flags = NoFlags; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null; - this.expirationTime = NoWork; - this.childExpirationTime = NoWork; + this.lanes = NoLanes; + this.childLanes = NoLanes; this.alternate = null; { @@ -19098,15 +20011,11 @@ function FiberNode(tag, pendingProps, key, mode) { this.actualStartTime = -1; this.selfBaseDuration = 0; this.treeBaseDuration = 0; - } // This is normally DEV-only except www when it adds listeners. - // TODO: remove the User Timing integration in favor of Root Events. - - { - this._debugID = debugCounter++; - this._debugIsCurrentlyTiming = false; } { + // This isn't directly used but is handy for debugging internals: + this._debugID = debugCounter++; this._debugSource = null; this._debugOwner = null; this._debugNeedsRemount = false; @@ -19186,10 +20095,7 @@ function createWorkInProgress(current, pendingProps) { { // DEV-only fields - { - workInProgress._debugID = current._debugID; - } - + workInProgress._debugID = current._debugID; workInProgress._debugSource = current._debugSource; workInProgress._debugOwner = current._debugOwner; workInProgress._debugHookTypes = current._debugHookTypes; @@ -19198,10 +20104,12 @@ function createWorkInProgress(current, pendingProps) { workInProgress.alternate = current; current.alternate = workInProgress; } else { - workInProgress.pendingProps = pendingProps; // We already have an alternate. + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + + workInProgress.type = current.type; // We already have an alternate. // Reset the effect tag. - workInProgress.effectTag = NoEffect; // The effect list is no longer valid. + workInProgress.flags = NoFlags; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -19217,8 +20125,8 @@ function createWorkInProgress(current, pendingProps) { } } - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -19230,9 +20138,8 @@ function createWorkInProgress(current, pendingProps) { currentDependencies === null ? null : { - expirationTime: currentDependencies.expirationTime, - firstContext: currentDependencies.firstContext, - responders: currentDependencies.responders + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext }; // These will be overridden during the parent's reconciliation workInProgress.sibling = current.sibling; @@ -19267,7 +20174,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } // Used to reuse a Fiber for a second pass. -function resetWorkInProgress(workInProgress, renderExpirationTime) { +function resetWorkInProgress(workInProgress, renderLanes) { // This resets the Fiber to what createFiber or createWorkInProgress would // have set the values to before during the first pass. Ideally this wouldn't // be necessary but unfortunately many code paths reads from the workInProgress @@ -19276,7 +20183,7 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { // avoid doing another reconciliation. // Reset the effect tag but keep any Placement tags, since that's something // that child fiber is setting, not the reconciliation. - workInProgress.effectTag &= Placement; // The effect list is no longer valid. + workInProgress.flags &= Placement; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -19285,13 +20192,14 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { if (current === null) { // Reset to createFiber's initial values. - workInProgress.childExpirationTime = NoWork; - workInProgress.expirationTime = renderExpirationTime; + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; workInProgress.child = null; workInProgress.memoizedProps = null; workInProgress.memoizedState = null; workInProgress.updateQueue = null; workInProgress.dependencies = null; + workInProgress.stateNode = null; { // Note: We don't reset the actualTime counts. It's useful to accumulate @@ -19301,12 +20209,14 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { } } else { // Reset to the cloned values that createWorkInProgress would've. - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so + workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. + + workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so // it cannot be shared with the current fiber. var currentDependencies = current.dependencies; @@ -19314,9 +20224,8 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { currentDependencies === null ? null : { - expirationTime: currentDependencies.expirationTime, - firstContext: currentDependencies.firstContext, - responders: currentDependencies.responders + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext }; { @@ -19355,9 +20264,8 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { - var fiber; var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. var resolvedType = type; @@ -19379,16 +20287,11 @@ function createFiberFromTypeAndProps( } else { getTag: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); + return createFiberFromFragment(pendingProps.children, mode, lanes, key); - case REACT_CONCURRENT_MODE_TYPE: + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = Mode; - mode |= ConcurrentMode | BlockingMode | StrictMode; + mode |= DebugTracingMode; break; case REACT_STRICT_MODE_TYPE: @@ -19397,18 +20300,23 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, expirationTime, key); + return createFiberFromProfiler(pendingProps, mode, lanes, key); case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, expirationTime, key); + return createFiberFromSuspense(pendingProps, mode, lanes, key); case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList( - pendingProps, - mode, - expirationTime, - key - ); + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + + case REACT_LEGACY_HIDDEN_TYPE: + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + + case REACT_SCOPE_TYPE: + + // eslint-disable-next-line no-fallthrough default: { if (typeof type === "object" && type !== null) { @@ -19439,10 +20347,6 @@ function createFiberFromTypeAndProps( fiberTag = LazyComponent; resolvedType = null; break getTag; - - case REACT_BLOCK_TYPE: - fiberTag = Block; - break getTag; } } @@ -19480,13 +20384,18 @@ function createFiberFromTypeAndProps( } } - fiber = createFiber(fiberTag, pendingProps, key, mode); + var fiber = createFiber(fiberTag, pendingProps, key, mode); fiber.elementType = type; fiber.type = resolvedType; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; + + { + fiber._debugOwner = owner; + } + return fiber; } -function createFiberFromElement(element, mode, expirationTime) { +function createFiberFromElement(element, mode, lanes) { var owner = null; { @@ -19502,7 +20411,7 @@ function createFiberFromElement(element, mode, expirationTime) { pendingProps, owner, mode, - expirationTime + lanes ); { @@ -19512,13 +20421,13 @@ function createFiberFromElement(element, mode, expirationTime) { return fiber; } -function createFiberFromFragment(elements, mode, expirationTime, key) { +function createFiberFromFragment(elements, mode, lanes, key) { var fiber = createFiber(Fragment, elements, key, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { +function createFiberFromProfiler(pendingProps, mode, lanes, key) { { if (typeof pendingProps.id !== "string") { error('Profiler must specify an "id" as a prop'); @@ -19529,7 +20438,7 @@ function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { fiber.elementType = REACT_PROFILER_TYPE; fiber.type = REACT_PROFILER_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; { fiber.stateNode = { @@ -19541,17 +20450,17 @@ function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { return fiber; } -function createFiberFromSuspense(pendingProps, mode, expirationTime, key) { +function createFiberFromSuspense(pendingProps, mode, lanes, key) { var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); // TODO: The SuspenseComponent fiber shouldn't have a type. It has a tag. // This needs to be fixed in getComponentName so that it relies on the tag // instead. fiber.type = REACT_SUSPENSE_TYPE; fiber.elementType = REACT_SUSPENSE_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromSuspenseList(pendingProps, mode, expirationTime, key) { +function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); { @@ -19562,18 +20471,44 @@ function createFiberFromSuspenseList(pendingProps, mode, expirationTime, key) { } fiber.elementType = REACT_SUSPENSE_LIST_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); // TODO: The OffscreenComponent fiber shouldn't have a type. It has a tag. + // This needs to be fixed in getComponentName so that it relies on the tag + // instead. + + { + fiber.type = REACT_OFFSCREEN_TYPE; + } + + fiber.elementType = REACT_OFFSCREEN_TYPE; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); // TODO: The LegacyHidden fiber shouldn't have a type. It has a tag. + // This needs to be fixed in getComponentName so that it relies on the tag + // instead. + + { + fiber.type = REACT_LEGACY_HIDDEN_TYPE; + } + + fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; + fiber.lanes = lanes; return fiber; } -function createFiberFromText(content, mode, expirationTime) { +function createFiberFromText(content, mode, lanes) { var fiber = createFiber(HostText, content, null, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromPortal(portal, mode, expirationTime) { +function createFiberFromPortal(portal, mode, lanes) { var pendingProps = portal.children !== null ? portal.children : []; var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; fiber.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -19610,12 +20545,12 @@ function assignFiberPropertiesInDEV(target, source) { target.memoizedState = source.memoizedState; target.dependencies = source.dependencies; target.mode = source.mode; - target.effectTag = source.effectTag; + target.flags = source.flags; target.nextEffect = source.nextEffect; target.firstEffect = source.firstEffect; target.lastEffect = source.lastEffect; - target.expirationTime = source.expirationTime; - target.childExpirationTime = source.childExpirationTime; + target.lanes = source.lanes; + target.childLanes = source.childLanes; target.alternate = source.alternate; { @@ -19625,11 +20560,7 @@ function assignFiberPropertiesInDEV(target, source) { target.treeBaseDuration = source.treeBaseDuration; } - { - target._debugID = source._debugID; - target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; - } - + target._debugID = source._debugID; target._debugSource = source._debugSource; target._debugOwner = source._debugOwner; target._debugNeedsRemount = source._debugNeedsRemount; @@ -19639,30 +20570,49 @@ function assignFiberPropertiesInDEV(target, source) { function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; this.pendingChildren = null; + this.current = null; this.pingCache = null; - this.finishedExpirationTime = NoWork; this.finishedWork = null; this.timeoutHandle = noTimeout; this.context = null; this.pendingContext = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = NoPriority; - this.firstPendingTime = NoWork; - this.firstSuspendedTime = NoWork; - this.lastSuspendedTime = NoWork; - this.nextKnownPendingLevel = NoWork; - this.lastPingedTime = NoWork; - this.lastExpiredTime = NoWork; + this.callbackPriority = NoLanePriority; + this.eventTimes = createLaneMap(NoLanes); + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.mutableReadLanes = NoLanes; + this.finishedLanes = NoLanes; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); { this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); } + + { + switch (tag) { + case BlockingRoot: + this._debugRootType = "createBlockingRoot()"; + break; + + case ConcurrentRoot: + this._debugRootType = "createRoot()"; + break; + + case LegacyRoot: + this._debugRootType = "createLegacyRoot()"; + break; + } + } } function createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks) { @@ -19675,95 +20625,22 @@ function createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks) { initializeUpdateQueue(uninitializedFiber); return root; } -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - var lastSuspendedTime = root.lastSuspendedTime; - return ( - firstSuspendedTime !== NoWork && - firstSuspendedTime >= expirationTime && - lastSuspendedTime <= expirationTime - ); -} -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - var lastSuspendedTime = root.lastSuspendedTime; - - if (firstSuspendedTime < expirationTime) { - root.firstSuspendedTime = expirationTime; - } - - if (lastSuspendedTime > expirationTime || firstSuspendedTime === NoWork) { - root.lastSuspendedTime = expirationTime; - } - - if (expirationTime <= root.lastPingedTime) { - root.lastPingedTime = NoWork; - } - - if (expirationTime <= root.lastExpiredTime) { - root.lastExpiredTime = NoWork; - } -} -function markRootUpdatedAtTime(root, expirationTime) { - // Update the range of pending times - var firstPendingTime = root.firstPendingTime; - - if (expirationTime > firstPendingTime) { - root.firstPendingTime = expirationTime; - } // Update the range of suspended times. Treat everything lower priority or - // equal to this update as unsuspended. - var firstSuspendedTime = root.firstSuspendedTime; - - if (firstSuspendedTime !== NoWork) { - if (expirationTime >= firstSuspendedTime) { - // The entire suspended range is now unsuspended. - root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork; - } else if (expirationTime >= root.lastSuspendedTime) { - root.lastSuspendedTime = expirationTime + 1; - } // This is a pending level. Check if it's higher priority than the next - // known pending level. - - if (expirationTime > root.nextKnownPendingLevel) { - root.nextKnownPendingLevel = expirationTime; - } - } -} -function markRootFinishedAtTime( - root, - finishedExpirationTime, - remainingExpirationTime +function createPortal( + children, + containerInfo, // TODO: figure out the API for cross-renderer implementation. + implementation ) { - // Update the range of pending times - root.firstPendingTime = remainingExpirationTime; // Update the range of suspended times. Treat everything higher priority or - // equal to this update as unsuspended. - - if (finishedExpirationTime <= root.lastSuspendedTime) { - // The entire suspended range is now unsuspended. - root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork; - } else if (finishedExpirationTime <= root.firstSuspendedTime) { - // Part of the suspended range is now unsuspended. Narrow the range to - // include everything between the unsuspended time (non-inclusive) and the - // last suspended time. - root.firstSuspendedTime = finishedExpirationTime - 1; - } - - if (finishedExpirationTime <= root.lastPingedTime) { - // Clear the pinged time - root.lastPingedTime = NoWork; - } - - if (finishedExpirationTime <= root.lastExpiredTime) { - // Clear the expired time - root.lastExpiredTime = NoWork; - } -} -function markRootExpiredAtTime(root, expirationTime) { - var lastExpiredTime = root.lastExpiredTime; - - if (lastExpiredTime === NoWork || lastExpiredTime > expirationTime) { - root.lastExpiredTime = expirationTime; - } + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } var didWarnAboutNestedUpdates; @@ -19823,31 +20700,42 @@ function findHostInstanceWithWarning(component, methodName) { if (!didWarnAboutFindNodeInStrictMode[componentName]) { didWarnAboutFindNodeInStrictMode[componentName] = true; + var previousFiber = current; - if (fiber.mode & StrictMode) { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which is inside StrictMode. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node%s", - methodName, - methodName, - componentName, - getStackByFiberInDevAndProd(hostFiber) - ); - } else { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which renders StrictMode children. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node%s", - methodName, - methodName, - componentName, - getStackByFiberInDevAndProd(hostFiber) - ); + try { + setCurrentFiber(hostFiber); + + if (fiber.mode & StrictMode) { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } else { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } + } finally { + // Ideally this should reset to previous but this shouldn't be called in + // render and there's another warning for that anyway. + if (previousFiber) { + setCurrentFiber(previousFiber); + } else { + resetCurrentFiber(); + } } } } @@ -19865,7 +20753,7 @@ function updateContainer(element, container, parentComponent, callback) { } var current$1 = container.current; - var currentTime = requestCurrentTimeForUpdate(); + var eventTime = requestEventTime(); { // $FlowExpectedError - jest isn't a global, and isn't recognized outside of tests @@ -19874,12 +20762,8 @@ function updateContainer(element, container, parentComponent, callback) { } } - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - current$1, - suspenseConfig - ); + var lane = requestUpdateLane(current$1); + var context = getContextForSubtree(parentComponent); if (container.context === null) { @@ -19902,7 +20786,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var update = createUpdate(expirationTime, suspenseConfig); // Caution: React DevTools currently depends on this property + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property // being called "element". update.payload = { @@ -19925,8 +20809,8 @@ function updateContainer(element, container, parentComponent, callback) { } enqueueUpdate(current$1, update); - scheduleWork(current$1, expirationTime); - return expirationTime; + scheduleUpdateOnFiber(current$1, lane, eventTime); + return lane; } function getPublicRootInstance(container) { var containerFiber = container.current; @@ -19952,28 +20836,102 @@ function shouldSuspend(fiber) { return shouldSuspendImpl(fiber); } var overrideHookState = null; +var overrideHookStateDeletePath = null; +var overrideHookStateRenamePath = null; var overrideProps = null; +var overridePropsDeletePath = null; +var overridePropsRenamePath = null; var scheduleUpdate = null; var setSuspenseHandler = null; { - var copyWithSetImpl = function(obj, path, idx, value) { - if (idx >= path.length) { + var copyWithDeleteImpl = function(obj, path, index) { + var key = path[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === path.length) { + if (Array.isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } + + return updated; + } // $FlowFixMe number or string is fine here + + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; + + var copyWithDelete = function(obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; + + var copyWithRenameImpl = function(obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here + + updated[newKey] = updated[oldKey]; + + if (Array.isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } + + return updated; + }; + + var copyWithRename = function(obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); + + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); + + return; + } + } + } + + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; + + var copyWithSetImpl = function(obj, path, index, value) { + if (index >= path.length) { return value; } - var key = path[idx]; + var key = path[index]; var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); // $FlowFixMe number or string is fine here - updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); return updated; }; var copyWithSet = function(obj, path, value) { return copyWithSetImpl(obj, path, 0, value); - }; // Support DevTools editable values for useState and useReducer. + }; - overrideHookState = function(fiber, id, path, value) { + var findHook = function(fiber, id) { // For now, the "id" of stateful hooks is just the stateful hook index. // This may change in the future with e.g. nested hooks. var currentHook = fiber.memoizedState; @@ -19983,17 +20941,57 @@ var setSuspenseHandler = null; id--; } - if (currentHook !== null) { - var newState = copyWithSet(currentHook.memoizedState, path, value); - currentHook.memoizedState = newState; - currentHook.baseState = newState; // We aren't actually adding an update to the queue, + return currentHook; + }; // Support DevTools editable values for useState and useReducer. + + overrideHookState = function(fiber, id, path, value) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateDeletePath = function(fiber, id, path) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, // because there is no update we can add for useReducer hooks that won't trigger an error. // (There's no appropriate action type for DevTools overrides.) // As a result though, React will see the scheduled update as a noop and bailout. // Shallow cloning props works as a workaround for now to bypass the bailout check. fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); } }; // Support DevTools props for function components, forwardRef, memo, host components, etc. @@ -20004,11 +21002,31 @@ var setSuspenseHandler = null; fiber.alternate.pendingProps = fiber.pendingProps; } - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsDeletePath = function(fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsRenamePath = function(fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; scheduleUpdate = function(fiber) { - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; setSuspenseHandler = function(newShouldSuspendImpl) { @@ -20016,6 +21034,24 @@ var setSuspenseHandler = null; }; } +function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); + + if (hostFiber === null) { + return null; + } + + return hostFiber.stateNode; +} + +function emptyFindFiberByHostInstance(instance) { + return null; +} + +function getCurrentFiberForDevTools() { + return current; +} + function injectIntoDevTools(devToolsConfig) { var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; @@ -20025,59 +21061,26 @@ function injectIntoDevTools(devToolsConfig) { rendererPackageName: devToolsConfig.rendererPackageName, rendererConfig: devToolsConfig.rendererConfig, overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, setSuspenseHandler: setSuspenseHandler, scheduleUpdate: scheduleUpdate, currentDispatcherRef: ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - var hostFiber = findCurrentHostFiber(fiber); - - if (hostFiber === null) { - return null; - } - - return hostFiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - if (!findFiberByHostInstance) { - // Might not be implemented by the renderer. - return null; - } - - return findFiberByHostInstance(instance); - }, + findHostInstanceByFiber: findHostInstanceByFiber, + findFiberByHostInstance: + findFiberByHostInstance || emptyFindFiberByHostInstance, // React Refresh findHostInstancesForRefresh: findHostInstancesForRefresh, scheduleRefresh: scheduleRefresh, scheduleRoot: scheduleRoot, setRefreshHandler: setRefreshHandler, // Enables DevTools to append owner stacks to error messages in DEV mode. - getCurrentFiber: function() { - return current; - } + getCurrentFiber: getCurrentFiberForDevTools }); } -var IsSomeRendererActing$1 = ReactSharedInternals.IsSomeRendererActing; - -function createPortal( - children, - containerInfo, // TODO: figure out the API for cross-renderer implementation. - implementation -) { - var key = - arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - return { - // This tag allow us to uniquely identify this as a React Portal - $$typeof: REACT_PORTAL_TYPE, - key: key == null ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; -} - -// TODO: this is special because it gets imported during build. -var ReactVersion = "16.13.0"; var instanceCache = new Map(); @@ -20314,7 +21317,7 @@ var getInspectorDataForViewAtPoint; ); } else { error( - "getInspectorDataForViewAtPoint expects to receieve a host component" + "getInspectorDataForViewAtPoint expects to receive a host component" ); return; diff --git a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js index 7eb73d4fd06fcb..035c6c10c7b3e8 100644 --- a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js @@ -919,7 +919,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_225 = { +var injectedNamesToPlugins$jscomp$inline_219 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -954,34 +954,34 @@ var injectedNamesToPlugins$jscomp$inline_225 = { } } }, - isOrderingDirty$jscomp$inline_226 = !1, - pluginName$jscomp$inline_227; -for (pluginName$jscomp$inline_227 in injectedNamesToPlugins$jscomp$inline_225) + isOrderingDirty$jscomp$inline_220 = !1, + pluginName$jscomp$inline_221; +for (pluginName$jscomp$inline_221 in injectedNamesToPlugins$jscomp$inline_219) if ( - injectedNamesToPlugins$jscomp$inline_225.hasOwnProperty( - pluginName$jscomp$inline_227 + injectedNamesToPlugins$jscomp$inline_219.hasOwnProperty( + pluginName$jscomp$inline_221 ) ) { - var pluginModule$jscomp$inline_228 = - injectedNamesToPlugins$jscomp$inline_225[pluginName$jscomp$inline_227]; + var pluginModule$jscomp$inline_222 = + injectedNamesToPlugins$jscomp$inline_219[pluginName$jscomp$inline_221]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_227) || - namesToPlugins[pluginName$jscomp$inline_227] !== - pluginModule$jscomp$inline_228 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_221) || + namesToPlugins[pluginName$jscomp$inline_221] !== + pluginModule$jscomp$inline_222 ) { - if (namesToPlugins[pluginName$jscomp$inline_227]) + if (namesToPlugins[pluginName$jscomp$inline_221]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_227 + + pluginName$jscomp$inline_221 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_227 - ] = pluginModule$jscomp$inline_228; - isOrderingDirty$jscomp$inline_226 = !0; + pluginName$jscomp$inline_221 + ] = pluginModule$jscomp$inline_222; + isOrderingDirty$jscomp$inline_220 = !0; } } -isOrderingDirty$jscomp$inline_226 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_220 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -1018,7 +1018,6 @@ var ReactSharedInternals = REACT_SUSPENSE_LIST_TYPE = 60120, REACT_MEMO_TYPE = 60115, REACT_LAZY_TYPE = 60116, - REACT_BLOCK_TYPE = 60121, REACT_DEBUG_TRACING_MODE_TYPE = 60129, REACT_OFFSCREEN_TYPE = 60130, REACT_LEGACY_HIDDEN_TYPE = 60131; @@ -1036,7 +1035,6 @@ if ("function" === typeof Symbol && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); symbolFor("react.scope"); REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); @@ -1083,8 +1081,6 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); case REACT_LAZY_TYPE: innerType = type._payload; type = type._init; @@ -1102,7 +1098,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1712,7 +1708,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1747,28 +1743,24 @@ var rendererID = null, injectedHook = null, Scheduler_now = Scheduler.unstable_now; Scheduler_now(); -var return_highestLanePriority = 10; +var return_highestLanePriority = 8; function getHighestPriorityLanes(lanes) { - if (0 !== (1 & lanes)) return (return_highestLanePriority = 17), 1; - if (0 !== (2 & lanes)) return (return_highestLanePriority = 16), 2; - if (0 !== (4 & lanes)) return (return_highestLanePriority = 15), 4; + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; var inputDiscreteLanes = 24 & lanes; - if (0 !== inputDiscreteLanes) - return (return_highestLanePriority = 14), inputDiscreteLanes; - if (0 !== (lanes & 32)) return (return_highestLanePriority = 13), 32; - inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 12), inputDiscreteLanes; - if (0 !== (lanes & 256)) return (return_highestLanePriority = 11), 256; - inputDiscreteLanes = 3584 & lanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 10), inputDiscreteLanes; - if (0 !== (lanes & 4096)) return (return_highestLanePriority = 9), 4096; - inputDiscreteLanes = 122880 & lanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 8), inputDiscreteLanes; - if (0 !== (lanes & 131072)) return (return_highestLanePriority = 7), 131072; - inputDiscreteLanes = 3932160 & lanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 6), inputDiscreteLanes; inputDiscreteLanes = 62914560 & lanes; @@ -1782,18 +1774,18 @@ function getHighestPriorityLanes(lanes) { return (return_highestLanePriority = 2), inputDiscreteLanes; if (0 !== (1073741824 & lanes)) return (return_highestLanePriority = 1), 1073741824; - return_highestLanePriority = 10; + return_highestLanePriority = 8; return lanes; } function schedulerPriorityToLanePriority(schedulerPriorityLevel) { switch (schedulerPriorityLevel) { case 99: - return 17; + return 15; case 98: - return 12; + return 10; case 97: case 96: - return 10; + return 8; case 95: return 2; default: @@ -1802,16 +1794,14 @@ function schedulerPriorityToLanePriority(schedulerPriorityLevel) { } function lanePriorityToSchedulerPriority(lanePriority) { switch (lanePriority) { - case 17: - case 16: - return 99; case 15: case 14: + return 99; case 13: case 12: - return 98; case 11: case 10: + return 98; case 9: case 8: case 7: @@ -1841,7 +1831,7 @@ function getNextLanes(root, wipLanes) { pingedLanes = root.pingedLanes; if (0 !== expiredLanes) (nextLanes = expiredLanes), - (nextLanePriority = return_highestLanePriority = 17); + (nextLanePriority = return_highestLanePriority = 15); else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; 0 !== nonIdleUnblockedLanes @@ -1880,42 +1870,31 @@ function getNextLanes(root, wipLanes) { (wipLanes &= ~nextLanePriority); return nextLanes; } -function getMostRecentEventTime(root, lanes) { - root = root.eventTimes; - for (var mostRecentEventTime = -1; 0 < lanes; ) { - var index$4 = 31 - clz32(lanes), - lane = 1 << index$4; - index$4 = root[index$4]; - index$4 > mostRecentEventTime && (mostRecentEventTime = index$4); - lanes &= ~lane; - } - return mostRecentEventTime; -} function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } function findUpdateLane(lanePriority, wipLanes) { switch (lanePriority) { - case 17: + case 15: return 1; - case 16: - return 2; case 14: + return 2; + case 12: return ( (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(12, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority ); - case 12: + case 10: return ( (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority ); - case 10: + case 8: return ( (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), 0 === lanePriority && - ((lanePriority = getHighestPriorityLane(4055040 & ~wipLanes)), + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), 0 === lanePriority && (lanePriority = 512)), lanePriority ); @@ -1933,8 +1912,9 @@ function findUpdateLane(lanePriority, wipLanes) { function getHighestPriorityLane(lanes) { return lanes & -lanes; } -function pickArbitraryLane(lanes) { - return lanes & -lanes; +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; @@ -2051,30 +2031,7 @@ function flushSyncCallbackQueueImpl() { } } } -function describeFiber(fiber) { - switch (fiber.tag) { - case 5: - return describeComponentFrame(fiber.type, null, null); - case 16: - return describeComponentFrame("Lazy", null, null); - case 13: - return describeComponentFrame("Suspense", null, null); - case 19: - return describeComponentFrame("SuspenseList", null, null); - case 0: - case 2: - case 15: - return describeFunctionComponentFrame(fiber.type, null); - case 11: - return describeFunctionComponentFrame(fiber.type.render, null); - case 22: - return describeFunctionComponentFrame(fiber.type._render, null); - case 1: - return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; - default: - return ""; - } -} +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -2100,6 +2057,28 @@ function shallowEqual(objA, objB) { return !1; return !0; } +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } +} function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { baseProps = Object.assign({}, baseProps); @@ -2193,11 +2172,10 @@ function cloneUpdateQueue(current, workInProgress) { effects: current.effects }); } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { return { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: 0, payload: null, callback: null, @@ -2230,7 +2208,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: queue.eventTime, lane: queue.lane, - suspenseConfig: queue.suspenseConfig, tag: queue.tag, payload: queue.payload, callback: queue.callback, @@ -2304,16 +2281,11 @@ function processUpdateQueue( (current = current.next = { eventTime: updateEventTime, lane: 0, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, next: null }); - markRenderEventTimeAndConfig( - updateEventTime, - firstBaseUpdate.suspenseConfig - ); a: { var workInProgress = workInProgress$jscomp$0, update = firstBaseUpdate; @@ -2333,8 +2305,7 @@ function processUpdateQueue( currentLastBaseUpdate = workInProgress; break a; case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; + workInProgress.flags = (workInProgress.flags & -8193) | 64; case 0: workInProgress = update.payload; pendingQueue = @@ -2357,7 +2328,7 @@ function processUpdateQueue( } } null !== firstBaseUpdate.callback && - ((workInProgress$jscomp$0.effectTag |= 32), + ((workInProgress$jscomp$0.flags |= 32), (pendingQueue = queue.effects), null === pendingQueue ? (queue.effects = [firstBaseUpdate]) @@ -2366,7 +2337,6 @@ function processUpdateQueue( (updateEventTime = { eventTime: updateEventTime, lane: pendingQueue, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, @@ -2418,8 +2388,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2445,41 +2414,32 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); } }; @@ -2572,7 +2532,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2587,7 +2547,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2621,7 +2581,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2645,7 +2605,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2677,16 +2637,16 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -3221,11 +3181,12 @@ function ChildReconciler(shouldTrackSideEffects) { switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3285,7 +3246,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3317,7 +3278,7 @@ var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3442,40 +3403,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var suspenseConfig = update.suspenseConfig, - updateLane = update.lane, - updateEventTime = update.eventTime; - (renderLanes & updateLane) === updateLane - ? (null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - eventTime: updateEventTime, - lane: 0, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }), - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig), - (current = - update.eagerReducer === reducer - ? update.eagerState - : reducer(current, update.action))) - : ((suspenseConfig = { - eventTime: updateEventTime, - lane: updateLane, - suspenseConfig: suspenseConfig, + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) + null !== newBaseQueueLast && + (newBaseQueueLast = newBaseQueueLast.next = { + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = suspenseConfig), - (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = suspenseConfig), - (currentlyRenderingFiber$1.lanes |= updateLane), - (workInProgressRootSkippedLanes |= updateLane)); + (current = + update.eagerReducer === reducer + ? update.eagerState + : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3560,10 +3515,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { maybeNewVersion = getSnapshot(source._source); objectIs(snapshot, maybeNewVersion) || (setSnapshot(maybeNewVersion), - (maybeNewVersion = requestUpdateLane( - fiber, - ReactCurrentBatchConfig.suspense - )), + (maybeNewVersion = requestUpdateLane(fiber)), (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); maybeNewVersion = root.mutableReadLanes; root.entangledLanes |= maybeNewVersion; @@ -3572,9 +3524,9 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { 0 < lanes; ) { - var index$12 = 31 - clz32(lanes), - lane = 1 << index$12; - entanglements[index$12] |= maybeNewVersion; + var index$11 = 31 - clz32(lanes), + lane = 1 << index$11; + entanglements[index$11] |= maybeNewVersion; lanes &= ~lane; } } @@ -3588,7 +3540,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { latestSetSnapshot = refs.setSnapshot; try { latestSetSnapshot(latestGetSnapshot(source._source)); - var lane = requestUpdateLane(fiber, ReactCurrentBatchConfig.suspense); + var lane = requestUpdateLane(fiber); root.mutableReadLanes |= lane & root.pendingLanes; } catch (error) { latestSetSnapshot(function() { @@ -3659,17 +3611,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3677,12 +3629,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3721,13 +3673,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3755,39 +3700,36 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(fiber, suspenseConfig); - suspenseConfig = { - eventTime: eventTime, - lane: lane, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || @@ -3803,8 +3745,8 @@ function dispatchAction(fiber, queue, action) { try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { @@ -3832,7 +3774,13 @@ var ContextOnlyDispatcher = { }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3878,36 +3826,30 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; }, useMutableSource: function(source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -3937,36 +3879,27 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -3988,36 +3921,27 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4059,11 +3983,11 @@ function updateForwardRef( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } @@ -4100,7 +4024,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -4117,7 +4041,7 @@ function updateMemoComponent( Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -4137,7 +4061,7 @@ function updateSimpleMemoComponent( current.ref === workInProgress.ref ) if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) - 0 !== (current.effectTag & 16384) && (didReceiveUpdate = !0); + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); else return ( (workInProgress.lanes = current.lanes), @@ -4192,7 +4116,7 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, @@ -4217,11 +4141,11 @@ function updateFunctionComponent( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } @@ -4241,7 +4165,7 @@ function updateClassComponent( null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -4307,9 +4231,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4317,7 +4241,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4390,17 +4314,17 @@ function updateClassComponent( oldContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) + (workInProgress.flags |= 256)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4410,11 +4334,11 @@ function updateClassComponent( : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (nextProps = !1)); } return finishClassComponent( @@ -4435,7 +4359,7 @@ function finishClassComponent( renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), @@ -4447,7 +4371,7 @@ function finishClassComponent( didCaptureError && "function" !== typeof Component.getDerivedStateFromError ? null : shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( workInProgress, @@ -4484,50 +4408,48 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = suspenseStackCursor.current, showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((showFallback = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { + current = nextProps.children; + suspenseContext = nextProps.fallback; if (showFallback) return ( - (current = nextProps.fallback), - (suspenseContext = workInProgress.mode), - (showFallback = workInProgress.child), - (nextProps = { mode: "hidden", children: nextProps.children }), - 0 === (suspenseContext & 2) && null !== showFallback - ? ((showFallback.childLanes = 0), - (showFallback.pendingProps = nextProps)) - : (showFallback = createFiberFromOffscreen( - nextProps, - suspenseContext, - 0, - null - )), - (current = createFiberFromFragment( + (current = mountSuspenseFallbackChildren( + workInProgress, current, suspenseContext, - renderLanes, - null + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current + ); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes )), - (showFallback.return = workInProgress), - (current.return = workInProgress), - (showFallback.sibling = current), - (workInProgress.child = showFallback), (workInProgress.child.memoizedState = { baseLanes: renderLanes }), (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), current ); renderLanes = createFiberFromOffscreen( - { mode: "visible", children: nextProps.children }, + { mode: "visible", children: current }, workInProgress.mode, renderLanes, null @@ -4545,13 +4467,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4573,13 +4495,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4592,6 +4514,36 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { workInProgress.memoizedState = null; return renderLanes; } +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren)) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} function updateSuspensePrimaryChildren( current, workInProgress, @@ -4609,7 +4561,7 @@ function updateSuspensePrimaryChildren( primaryChildren.sibling = null; null !== current && ((current.nextEffect = null), - (current.effectTag = 8), + (current.flags = 8), (workInProgress.firstEffect = workInProgress.lastEffect = current)); return (workInProgress.child = primaryChildren); } @@ -4646,7 +4598,7 @@ function updateSuspenseFallbackChildren( renderLanes, null )), - (fallbackChildren.effectTag |= 2)); + (fallbackChildren.flags |= 2)); fallbackChildren.return = workInProgress; primaryChildren.return = workInProgress; primaryChildren.sibling = fallbackChildren; @@ -4675,7 +4627,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4684,7 +4635,6 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } @@ -4695,9 +4645,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && @@ -4831,7 +4781,7 @@ appendAllChildren = function( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4884,7 +4834,7 @@ function appendAllChildrenToContainer( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4928,7 +4878,7 @@ updateHostContainer = function(workInProgress) { newChildSet = createChildNodeSet(container); appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); portalOrRoot.pendingChildren = newChildSet; - workInProgress.effectTag |= 4; + workInProgress.flags |= 4; completeRoot(container, newChildSet); } }; @@ -4966,7 +4916,7 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { }), (workInProgress.stateNode = type), current - ? (workInProgress.effectTag |= 4) + ? (workInProgress.flags |= 4) : appendAllChildren(type, workInProgress, !1, !1)); } }; @@ -4980,7 +4930,7 @@ updateHostText$1 = function(current, workInProgress, oldText, newText) { oldText, workInProgress )), - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : (workInProgress.stateNode = current.stateNode); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { @@ -5035,7 +4985,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.pendingContext = null)), (null !== current && null !== current.child) || newProps.hydrate || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -5053,8 +5003,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -5089,7 +5038,7 @@ function completeWork(current, workInProgress, renderLanes) { current = { node: rootContainerInstance, canonical: current }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -5118,7 +5067,7 @@ function completeWork(current, workInProgress, renderLanes) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return (workInProgress.lanes = renderLanes), workInProgress; newProps = null !== newProps; rootContainerInstance = !1; @@ -5146,7 +5095,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderLanes ); } - newProps && (workInProgress.effectTag |= 4); + newProps && (workInProgress.flags |= 4); return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -5158,24 +5107,24 @@ function completeWork(current, workInProgress, renderLanes) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.effectTag & 64)) + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; @@ -5183,7 +5132,7 @@ function completeWork(current, workInProgress, renderLanes) { for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (renderLanes = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), @@ -5225,6 +5174,12 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432)); } else { if (!rootContainerInstance) @@ -5232,12 +5187,12 @@ function completeWork(current, workInProgress, renderLanes) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -5250,12 +5205,13 @@ function completeWork(current, workInProgress, renderLanes) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.lanes = renderLanes)); + (workInProgress.lanes = 33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5266,9 +5222,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -5283,15 +5237,15 @@ function completeWork(current, workInProgress, renderLanes) { ), current) : null; + case 22: case 23: - case 24: return ( popRenderLanes(), null !== current && (null !== current.memoizedState) !== (null !== workInProgress.memoizedState) && "unstable-defer-without-hiding" !== newProps.mode && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), null ); } @@ -5305,32 +5259,30 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); resetWorkInProgressVersions(); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null ); case 19: @@ -5339,8 +5291,8 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: case 23: - case 24: return popRenderLanes(), null; default: return null; @@ -5383,7 +5335,7 @@ function logCapturedError(boundary, errorInfo) { } var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; @@ -5394,7 +5346,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { return lane; } function createClassErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { @@ -5437,10 +5389,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5470,7 +5421,6 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 0: case 11: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5501,7 +5451,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { return; case 1: finishedRoot = finishedWork.stateNode; - finishedWork.effectTag & 4 && + finishedWork.flags & 4 && (null === current ? finishedRoot.componentDidMount() : ((create$81 = @@ -5536,7 +5486,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { } return; case 5: - null === current && finishedWork.effectTag & 4 && shim(); + null === current && finishedWork.flags & 4 && shim(); return; case 6: return; @@ -5550,8 +5500,8 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: case 23: - case 24: return; } throw Error( @@ -5576,7 +5526,6 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5601,8 +5550,8 @@ function commitWork(current, finishedWork) { case 19: attachSuspenseRetryListeners(finishedWork); return; + case 22: case 23: - case 24: return; } a: { @@ -5654,14 +5603,13 @@ var ceil = Math.ceil, subtreeRenderLanesCursor = createCursor(0), workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestSuspenseTimeout = -1, - workInProgressRootCanSuspendUsingConfig = null, workInProgressRootIncludedLanes = 0, workInProgressRootSkippedLanes = 0, workInProgressRootUpdatedLanes = 0, workInProgressRootPingedLanes = 0, mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5686,46 +5634,33 @@ function requestEventTime() { ? currentEventTime : (currentEventTime = now()); } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; if (0 === (fiber & 2)) return 1; if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; 0 === currentEventWipLanes && (currentEventWipLanes = workInProgressRootIncludedLanes); - if (null !== suspenseConfig) { - suspenseConfig = suspenseConfig.timeoutMs; - fiber = void 0 === suspenseConfig || 1e4 > (suspenseConfig | 0) ? 8 : 6; + if (0 !== ReactCurrentBatchConfig.transition) { 0 !== currentEventPendingLanes && (currentEventPendingLanes = null !== mostRecentlyUpdatedRoot ? mostRecentlyUpdatedRoot.pendingLanes : 0); - suspenseConfig = currentEventWipLanes; - var pendingLanes = currentEventPendingLanes; - if (8 === fiber) - (fiber = pickArbitraryLane(122880 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(122880 & ~suspenseConfig)), - 0 === fiber && (fiber = 8192)), - (suspenseConfig = fiber); - else if (6 === fiber) - (fiber = pickArbitraryLane(3932160 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(3932160 & ~suspenseConfig)), - 0 === fiber && (fiber = 262144)), - (suspenseConfig = fiber); - else - throw Error( - "Invalid transition priority: " + fiber + ". This is a bug in React." - ); - return suspenseConfig; + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; } - suspenseConfig = getCurrentPriorityLevel(); - 0 !== (executionContext & 4) && 98 === suspenseConfig - ? (suspenseConfig = findUpdateLane(14, currentEventWipLanes)) - : ((suspenseConfig = schedulerPriorityToLanePriority(suspenseConfig)), - (suspenseConfig = findUpdateLane(suspenseConfig, currentEventWipLanes))); - return suspenseConfig; + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; } function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) @@ -5746,7 +5681,9 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) ? performSyncWorkOnRoot(fiber) : (ensureRootIsScheduled(fiber, eventTime), - 0 === executionContext && flushSyncCallbackQueue()) + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) : (0 === (executionContext & 4) || (98 !== priorityLevel && 99 !== priorityLevel) || (null === rootsWithPendingDiscreteUpdates @@ -5787,8 +5724,8 @@ function ensureRootIsScheduled(root, currentTime) { getHighestPriorityLanes(lane); var priority = return_highestLanePriority; expirationTimes[index$5] = - 12 <= priority - ? expirationTime + 1e3 + 10 <= priority + ? expirationTime + 250 : 6 <= priority ? expirationTime + 5e3 : -1; @@ -5813,7 +5750,7 @@ function ensureRootIsScheduled(root, currentTime) { existingCallbackNode !== fakeCallbackNode && Scheduler_cancelCallback(existingCallbackNode); } - 17 === currentTime + 15 === currentTime ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), null === syncQueue ? ((syncQueue = [existingCallbackNode]), @@ -5823,7 +5760,7 @@ function ensureRootIsScheduled(root, currentTime) { ))) : syncQueue.push(existingCallbackNode), (existingCallbackNode = fakeCallbackNode)) - : 16 === currentTime + : 14 === currentTime ? (existingCallbackNode = scheduleCallback( 99, performSyncWorkOnRoot.bind(null, root) @@ -5837,7 +5774,7 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { currentEventTime = -1; currentEventPendingLanes = currentEventWipLanes = 0; if (0 !== (executionContext & 48)) @@ -5850,19 +5787,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - if (didTimeout) - return ( - (root.expiredLanes |= lanes & root.pendingLanes), - ensureRootIsScheduled(root, now()), - null - ); - didTimeout = lanes; + var exitStatus = lanes; var prevExecutionContext = executionContext; executionContext |= 16; var prevDispatcher = pushDispatcher(); - (workInProgressRoot === root && - workInProgressRootRenderLanes === didTimeout) || - prepareFreshStack(root, didTimeout); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== exitStatus + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, exitStatus); do try { workLoopConcurrent(); @@ -5875,19 +5809,19 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ReactCurrentDispatcher$2.current = prevDispatcher; executionContext = prevExecutionContext; null !== workInProgress - ? (didTimeout = 0) + ? (exitStatus = 0) : ((workInProgressRoot = null), (workInProgressRootRenderLanes = 0), - (didTimeout = workInProgressRootExitStatus)); + (exitStatus = workInProgressRootExitStatus)); if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) prepareFreshStack(root, 0); - else if (0 !== didTimeout) { - 2 === didTimeout && + else if (0 !== exitStatus) { + 2 === exitStatus && ((executionContext |= 64), root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), (lanes = getLanesToRetrySynchronouslyOnError(root)), - 0 !== lanes && (didTimeout = renderRootSync(root, lanes))); - if (1 === didTimeout) + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), markRootSuspended$1(root, lanes), @@ -5895,7 +5829,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); @@ -5906,8 +5840,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ( (lanes & 62914560) === lanes && - ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; prevExecutionContext = root.suspendedLanes; @@ -5918,7 +5852,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - didTimeout + exitStatus ); break; } @@ -5926,33 +5860,31 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; case 4: markRootSuspended$1(root, lanes); - if (0 !== getNextLanes(root, 0)) break; - didTimeout = root.suspendedLanes; - if ((didTimeout & lanes) !== lanes) { - requestEventTime(); - root.pingedLanes |= root.suspendedLanes & didTimeout; - break; + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevExecutionContext = -1; 0 < lanes; ) { + var index$4 = 31 - clz32(lanes); + prevDispatcher = 1 << index$4; + index$4 = exitStatus[index$4]; + index$4 > prevExecutionContext && (prevExecutionContext = index$4); + lanes &= ~prevDispatcher; } - lanes = getMostRecentEventTime(root, lanes); - -1 !== workInProgressRootLatestSuspenseTimeout - ? (lanes = workInProgressRootLatestSuspenseTimeout - now()) - : -1 === lanes - ? (lanes = 0) - : ((lanes = now() - lanes), - (lanes = - (120 > lanes - ? 120 - : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes)); + lanes = prevExecutionContext; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), @@ -5963,30 +5895,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { commitRoot(root); break; case 5: - prevDispatcher = getMostRecentEventTime(root, lanes); - if ( - -1 !== prevDispatcher && - null !== workInProgressRootCanSuspendUsingConfig && - ((didTimeout = - workInProgressRootCanSuspendUsingConfig.busyMinDurationMs | 0), - 0 >= didTimeout - ? (didTimeout = 0) - : ((prevExecutionContext = - workInProgressRootCanSuspendUsingConfig.busyDelayMs | 0), - (prevDispatcher = now() - prevDispatcher), - (didTimeout = - prevDispatcher <= prevExecutionContext - ? 0 - : prevExecutionContext + didTimeout - prevDispatcher)), - 10 < didTimeout) - ) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - didTimeout - ); - break; - } commitRoot(root); break; default: @@ -6004,9 +5912,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$10 = 31 - clz32(suspendedLanes), - lane = 1 << index$10; - root[index$10] = -1; + var index$9 = 31 - clz32(suspendedLanes), + lane = 1 << index$9; + root[index$9] = -1; suspendedLanes &= ~lane; } } @@ -6089,8 +5997,8 @@ function prepareFreshStack(root, lanes) { case 10: popProvider(interruptedWork); break; + case 22: case 23: - case 24: popRenderLanes(); } timeoutHandle = timeoutHandle.return; @@ -6100,8 +6008,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = -1; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; } function handleError(root$jscomp$0, thrownValue) { @@ -6138,7 +6044,7 @@ function handleError(root$jscomp$0, thrownValue) { sourceFiber = erroredWork, value = thrownValue; thrownValue = workInProgressRootRenderLanes; - sourceFiber.effectTag |= 2048; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && @@ -6184,13 +6090,13 @@ function handleError(root$jscomp$0, thrownValue) { workInProgress$76.updateQueue = updateQueue; } else wakeables.add(wakeable); if (0 === (workInProgress$76.mode & 2)) { - workInProgress$76.effectTag |= 64; - sourceFiber.effectTag |= 16384; - sourceFiber.effectTag &= -2981; + workInProgress$76.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(-1, 1, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } @@ -6217,7 +6123,7 @@ function handleError(root$jscomp$0, thrownValue) { ); wakeable.then(ping, ping); } - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; workInProgress$76.lanes = thrownValue; break a; } @@ -6236,7 +6142,7 @@ function handleError(root$jscomp$0, thrownValue) { switch (workInProgress$76.tag) { case 3: root = value; - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; thrownValue &= -thrownValue; workInProgress$76.lanes |= thrownValue; var update$77 = createRootErrorUpdate( @@ -6251,14 +6157,14 @@ function handleError(root$jscomp$0, thrownValue) { var ctor = workInProgress$76.type, instance = workInProgress$76.stateNode; if ( - 0 === (workInProgress$76.effectTag & 64) && + 0 === (workInProgress$76.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; thrownValue &= -thrownValue; workInProgress$76.lanes |= thrownValue; var update$80 = createClassErrorUpdate( @@ -6289,13 +6195,6 @@ function pushDispatcher() { ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - null !== suspenseConfig && - ((eventTime += suspenseConfig.timeoutMs | 0 || 5e3), - eventTime > workInProgressRootLatestSuspenseTimeout && - ((workInProgressRootLatestSuspenseTimeout = eventTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig))); -} function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 16; @@ -6339,7 +6238,7 @@ function completeUnitOfWork(unitOfWork) { do { var current = completedWork.alternate; unitOfWork = completedWork.return; - if (0 === (completedWork.effectTag & 2048)) { + if (0 === (completedWork.flags & 4096)) { current = completeWork(current, completedWork, subtreeRenderLanes); if (null !== current) { workInProgress = current; @@ -6347,7 +6246,7 @@ function completeUnitOfWork(unitOfWork) { } current = completedWork; if ( - (24 !== current.tag && 23 !== current.tag) || + (23 !== current.tag && 22 !== current.tag) || null === current.memoizedState || 0 !== (subtreeRenderLanes & 1073741824) || 0 === (current.mode & 4) @@ -6358,14 +6257,14 @@ function completeUnitOfWork(unitOfWork) { current.childLanes = newChildLanes; } null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && (unitOfWork.firstEffect = completedWork.firstEffect), null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), (unitOfWork.lastEffect = completedWork.lastEffect)), - 1 < completedWork.effectTag && + 1 < completedWork.flags && (null !== unitOfWork.lastEffect ? (unitOfWork.lastEffect.nextEffect = completedWork) : (unitOfWork.firstEffect = completedWork), @@ -6373,13 +6272,13 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(completedWork); if (null !== current) { - current.effectTag &= 2047; + current.flags &= 4095; workInProgress = current; return; } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } completedWork = completedWork.sibling; if (null !== completedWork) { @@ -6424,11 +6323,11 @@ function commitRootImpl(root, renderPriorityLevel) { 0 < noLongerPendingLanes; ) { - var index$11 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$11; - remainingLanes$jscomp$0[index$11] = 0; - eventTimes[index$11] = -1; - expirationTimes[index$11] = -1; + var index$10 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$10; + remainingLanes$jscomp$0[index$10] = 0; + eventTimes[index$10] = -1; + expirationTimes[index$10] = -1; noLongerPendingLanes &= ~lane; } null !== rootsWithPendingDiscreteUpdates && @@ -6438,7 +6337,7 @@ function commitRootImpl(root, renderPriorityLevel) { root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - 1 < finishedWork.effectTag + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), (remainingLanes = finishedWork.firstEffect)) @@ -6464,8 +6363,8 @@ function commitRootImpl(root, renderPriorityLevel) { do try { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6475,19 +6374,19 @@ function commitRootImpl(root, renderPriorityLevel) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: @@ -6496,21 +6395,20 @@ function commitRootImpl(root, renderPriorityLevel) { case 8: eventTimes = nextEffect; a: for (noLongerPendingLanes = expirationTimes = eventTimes; ; ) { - index$11 = noLongerPendingLanes; + index$10 = noLongerPendingLanes; if ( injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount ) try { - injectedHook.onCommitFiberUnmount(rendererID, index$11); + injectedHook.onCommitFiberUnmount(rendererID, index$10); } catch (err) {} - switch (index$11.tag) { + switch (index$10.tag) { case 0: case 11: case 14: case 15: - case 22: - var updateQueue = index$11.updateQueue; + var updateQueue = index$10.updateQueue; if (null !== updateQueue) { var lastEffect = updateQueue.lastEffect; if (null !== lastEffect) { @@ -6523,11 +6421,11 @@ function commitRootImpl(root, renderPriorityLevel) { if (void 0 !== destroy) if (0 !== (tag & 4)) enqueuePendingPassiveHookEffectUnmount( - index$11, + index$10, lane ); else { - _effect2 = index$11; + _effect2 = index$10; try { destroy(); } catch (error) { @@ -6540,24 +6438,24 @@ function commitRootImpl(root, renderPriorityLevel) { } break; case 1: - safelyDetachRef(index$11); - var instance = index$11.stateNode; + safelyDetachRef(index$10); + var instance = index$10.stateNode; if ("function" === typeof instance.componentWillUnmount) try { - (lane = index$11), + (lane = index$10), (_effect2 = instance), (_effect2.props = lane.memoizedProps), (_effect2.state = lane.memoizedState), _effect2.componentWillUnmount(); } catch (unmountError) { - captureCommitPhaseError(index$11, unmountError); + captureCommitPhaseError(index$10, unmountError); } break; case 5: - safelyDetachRef(index$11); + safelyDetachRef(index$10); break; case 4: - createChildNodeSet(index$11.stateNode.containerInfo); + createChildNodeSet(index$10.stateNode.containerInfo); } if (null !== noLongerPendingLanes.child) (noLongerPendingLanes.child.return = noLongerPendingLanes), @@ -6583,9 +6481,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$92) { + } catch (error$87) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$92); + captureCommitPhaseError(nextEffect, error$87); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6593,11 +6491,11 @@ function commitRootImpl(root, renderPriorityLevel) { nextEffect = remainingLanes; do try { - for (effectTag = root; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6616,9 +6514,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$93) { + } catch (error$88) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$93); + captureCommitPhaseError(nextEffect, error$88); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6634,10 +6532,10 @@ function commitRootImpl(root, renderPriorityLevel) { for (nextEffect = remainingLanes; null !== nextEffect; ) (renderPriorityLevel = nextEffect.nextEffect), (nextEffect.nextEffect = null), - nextEffect.effectTag & 8 && - ((effectTag$jscomp$0 = nextEffect), - (effectTag$jscomp$0.sibling = null), - (effectTag$jscomp$0.stateNode = null)), + nextEffect.flags & 8 && + ((flags$jscomp$0 = nextEffect), + (flags$jscomp$0.sibling = null), + (flags$jscomp$0.stateNode = null)), (nextEffect = renderPriorityLevel); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); @@ -6653,7 +6551,7 @@ function commitRootImpl(root, renderPriorityLevel) { rendererID, finishedWork, void 0, - 64 === (finishedWork.current.effectTag & 64) + 64 === (finishedWork.current.flags & 64) ); } catch (err) {} ensureRootIsScheduled(root, now()); @@ -6671,17 +6569,16 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; shouldFireAfterActiveInstanceBlur || null === focusedInstanceHandle || - (0 !== (nextEffect.effectTag & 8) + (0 !== (nextEffect.flags & 8) ? doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0) : 13 === nextEffect.tag && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0)); - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(current, nextEffect); - 0 === (effectTag & 512) || + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6698,7 +6595,6 @@ function flushPassiveEffects() { ? 97 : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = 90; - schedulerPriorityToLanePriority(priorityLevel); return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } return !1; @@ -6732,10 +6628,10 @@ function flushPassiveEffectsImpl() { var unmountEffects = pendingPassiveHookEffectsUnmount; pendingPassiveHookEffectsUnmount = []; for (var i = 0; i < unmountEffects.length; i += 2) { - var effect$98 = unmountEffects[i], + var effect$93 = unmountEffects[i], fiber = unmountEffects[i + 1], - destroy = effect$98.destroy; - effect$98.destroy = void 0; + destroy = effect$93.destroy; + effect$93.destroy = void 0; if ("function" === typeof destroy) try { destroy(); @@ -6747,22 +6643,22 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsMount; pendingPassiveHookEffectsMount = []; for (i = 0; i < unmountEffects.length; i += 2) { - effect$98 = unmountEffects[i]; + effect$93 = unmountEffects[i]; fiber = unmountEffects[i + 1]; try { - var create$102 = effect$98.create; - effect$98.destroy = create$102(); - } catch (error$103) { + var create$97 = effect$93.create; + effect$93.destroy = create$97(); + } catch (error$98) { if (null === fiber) throw Error("Should be working on an effect."); - captureCommitPhaseError(fiber, error$103); + captureCommitPhaseError(fiber, error$98); } } - for (create$102 = root.current.firstEffect; null !== create$102; ) - (root = create$102.nextEffect), - (create$102.nextEffect = null), - create$102.effectTag & 8 && - ((create$102.sibling = null), (create$102.stateNode = null)), - (create$102 = root); + for (create$97 = root.current.firstEffect; null !== create$97; ) + (root = create$97.nextEffect), + (create$97.nextEffect = null), + create$97.flags & 8 && + ((create$97.sibling = null), (create$97.stateNode = null)), + (create$97 = root); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; @@ -6794,13 +6690,21 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1); - enqueueUpdate(fiber, sourceFiber); - sourceFiber = requestEventTime(); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); fiber = markUpdateLaneFromFiberToRoot(fiber, 1); - null !== fiber && - (markRootUpdated(fiber, 1, sourceFiber), - ensureRootIsScheduled(fiber, sourceFiber)); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } @@ -6853,7 +6757,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ) didReceiveUpdate = !0; else if (0 !== (renderLanes & updateLanes)) - didReceiveUpdate = 0 !== (current.effectTag & 16384) ? !0 : !1; + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { didReceiveUpdate = !1; switch (workInProgress.tag) { @@ -6899,14 +6803,14 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 19: updateLanes = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.effectTag & 64)) { + if (0 !== (current.flags & 64)) { if (updateLanes) return updateSuspenseListComponent( current, workInProgress, renderLanes ); - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; } context = workInProgress.memoizedState; null !== context && @@ -6916,8 +6820,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { push(suspenseStackCursor, suspenseStackCursor.current); if (updateLanes) break; else return null; + case 22: case 23: - case 24: return ( (workInProgress.lanes = 0), updateOffscreenComponent(current, workInProgress, renderLanes) @@ -6933,7 +6837,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); prepareToReadContext(workInProgress, renderLanes); @@ -6945,7 +6849,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context, renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -6995,7 +6899,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; hasContext = context._init; context = hasContext(context._payload); @@ -7238,8 +7142,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { 1 === context$jscomp$0.tag && ((dependency = createUpdate( -1, - renderLanes & -renderLanes, - null + renderLanes & -renderLanes )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); @@ -7301,7 +7204,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), (updateLanes = updateLanes(context)), - (workInProgress.effectTag |= 1), + (workInProgress.flags |= 1), reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); @@ -7342,7 +7245,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) @@ -7361,9 +7264,9 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 19: return updateSuspenseListComponent(current, workInProgress, renderLanes); - case 23: + case 22: return updateOffscreenComponent(current, workInProgress, renderLanes); - case 24: + case 23: return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( @@ -7381,7 +7284,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; this.childLanes = this.lanes = 0; this.alternate = null; @@ -7419,7 +7322,7 @@ function createWorkInProgress(current, pendingProps) { (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), (workInProgress.type = current.type), - (workInProgress.effectTag = 0), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null)); @@ -7490,7 +7393,7 @@ function createFiberFromTypeAndProps( return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: return ( - (type = createFiber(24, pendingProps, key, mode)), + (type = createFiber(23, pendingProps, key, mode)), (type.elementType = REACT_LEGACY_HIDDEN_TYPE), (type.lanes = lanes), type @@ -7514,9 +7417,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7536,7 +7436,7 @@ function createFiberFromFragment(elements, mode, lanes, key) { return elements; } function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps = createFiber(22, pendingProps, key, mode); pendingProps.elementType = REACT_OFFSCREEN_TYPE; pendingProps.lanes = lanes; return pendingProps; @@ -7570,10 +7470,10 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.hydrate = hydrate; this.callbackNode = null; this.callbackPriority = 0; - this.eventTimes = Array(31).fill(0); - this.expirationTimes = Array(31).fill(-1); + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; - this.entanglements = Array(31).fill(0); + this.entanglements = createLaneMap(0); } function createPortal(children, containerInfo, implementation) { var key = @@ -7602,8 +7502,7 @@ function findHostInstance(component) { function updateContainer(element, container, parentComponent, callback) { var current = container.current, eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(current, suspenseConfig); + lane = requestUpdateLane(current); a: if (parentComponent) { parentComponent = parentComponent._reactInternals; b: { @@ -7651,7 +7550,7 @@ function updateContainer(element, container, parentComponent, callback) { null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(eventTime, lane, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); @@ -7682,14 +7581,16 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - 0 === executionContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; var roots = new Map(), - devToolsConfig$jscomp$inline_891 = { + devToolsConfig$jscomp$inline_865 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "17.0.0-alpha.0", + version: "17.0.1-454c2211c", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -7704,13 +7605,17 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1074 = { - bundleType: devToolsConfig$jscomp$inline_891.bundleType, - version: devToolsConfig$jscomp$inline_891.version, - rendererPackageName: devToolsConfig$jscomp$inline_891.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_891.rendererConfig, +var internals$jscomp$inline_1054 = { + bundleType: devToolsConfig$jscomp$inline_865.bundleType, + version: devToolsConfig$jscomp$inline_865.version, + rendererPackageName: devToolsConfig$jscomp$inline_865.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_865.rendererConfig, overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, @@ -7719,7 +7624,7 @@ var internals$jscomp$inline_1074 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_891.findFiberByHostInstance || + devToolsConfig$jscomp$inline_865.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, @@ -7728,16 +7633,16 @@ var internals$jscomp$inline_1074 = { getCurrentFiber: null }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1075 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1055 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1075.isDisabled && - hook$jscomp$inline_1075.supportsFiber + !hook$jscomp$inline_1055.isDisabled && + hook$jscomp$inline_1055.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1075.inject( - internals$jscomp$inline_1074 + (rendererID = hook$jscomp$inline_1055.inject( + internals$jscomp$inline_1054 )), - (injectedHook = hook$jscomp$inline_1075); + (injectedHook = hook$jscomp$inline_1055); } catch (err) {} } exports.createPortal = function(children, containerTag) { @@ -7797,6 +7702,18 @@ exports.render = function(element, containerTag, callback) { else element = null; return element; }; +exports.sendAccessibilityEvent = function(handle, eventType) { + null != handle._nativeTag && + (handle._internalInstanceHandle + ? nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ) + : ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + )); +}; exports.stopSurface = function(containerTag) { var root = roots.get(containerTag); root && diff --git a/Libraries/Renderer/implementations/ReactFabric-prod.js b/Libraries/Renderer/implementations/ReactFabric-prod.js index 7df0e13f1f7fe1..0ef34f37bb0d1d 100644 --- a/Libraries/Renderer/implementations/ReactFabric-prod.js +++ b/Libraries/Renderer/implementations/ReactFabric-prod.js @@ -16,16 +16,6 @@ require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"), React = require("react"), Scheduler = require("scheduler"); -function getParent(inst) { - do inst = inst.return; - while (inst && 5 !== inst.tag); - return inst ? inst : null; -} -function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); - for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); -} function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -96,109 +86,6 @@ function executeDirectDispatch(event) { event._dispatchInstances = null; return dispatchListener; } -function getListener(inst, registrationName) { - var listener = inst.stateNode; - if (!listener) return null; - var props = getFiberCurrentPropsFromNode(listener); - if (!props) return null; - listener = props[registrationName]; - a: switch (registrationName) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - (props = !props.disabled) || - ((inst = inst.type), - (props = !( - "button" === inst || - "input" === inst || - "select" === inst || - "textarea" === inst - ))); - inst = !props; - break a; - default: - inst = !1; - } - if (inst) return null; - if (listener && "function" !== typeof listener) - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - return listener; -} -function accumulateInto(current, next) { - if (null == next) - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - if (null == current) return next; - if (Array.isArray(current)) { - if (Array.isArray(next)) return current.push.apply(current, next), current; - current.push(next); - return current; - } - return Array.isArray(next) ? [current].concat(next) : [current, next]; -} -function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); -} -function accumulateDirectionalDispatches(inst, phase, event) { - if ( - (phase = getListener( - inst, - event.dispatchConfig.phasedRegistrationNames[phase] - )) - ) - (event._dispatchListeners = accumulateInto( - event._dispatchListeners, - phase - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - )); -} -function accumulateTwoPhaseDispatchesSingle(event) { - event && - event.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); -} -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - targetInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); - } -} -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - var inst = event._targetInst; - if (inst && event && event.dispatchConfig.registrationName) { - var listener = getListener(inst, event.dispatchConfig.registrationName); - listener && - ((event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); - } - } -} function functionThatReturnsTrue() { return !0; } @@ -214,6 +101,7 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchInstances = this._dispatchListeners = null; dispatchConfig = this.constructor.Interface; for (var propName in dispatchConfig) dispatchConfig.hasOwnProperty(propName) && @@ -293,7 +181,12 @@ SyntheticEvent.extend = function(Interface) { return Class; }; addEventPoolingTo(SyntheticEvent); -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { if (this.eventPool.length) { var instance = this.eventPool.pop(); this.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); @@ -310,8 +203,8 @@ function releasePooledEvent(event) { 10 > this.eventPool.length && this.eventPool.push(event); } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ @@ -439,6 +332,22 @@ function accumulate(current, next) { ? [current].concat(next) : [current, next]; } +function accumulateInto(current, next) { + if (null == next) + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + if (null == current) return next; + if (Array.isArray(current)) { + if (Array.isArray(next)) return current.push.apply(current, next), current; + current.push(next); + return current; + } + return Array.isArray(next) ? [current].concat(next) : [current, next]; +} +function forEachAccumulated(arr, cb, scope) { + Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); +} var responderInst = null, trackedTouchCount = 0; function changeResponder(nextResponderInst, blockHostResponder) { @@ -452,65 +361,132 @@ function changeResponder(nextResponderInst, blockHostResponder) { ); } var eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: ["topScroll"] - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: ["topSelectionChange"] - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies - }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies + dependencies: startDependencies + }, + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] + dependencies: ["topScroll"] + }, + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" }, - responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] + dependencies: ["topSelectionChange"] + }, + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } + dependencies: moveDependencies + }, + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies + }, + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies }, - ResponderEventPlugin = { + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, + responderReject: { registrationName: "onResponderReject", dependencies: [] }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } +}; +function getParent(inst) { + do inst = inst.return; + while (inst && 5 !== inst.tag); + return inst ? inst : null; +} +function traverseTwoPhase(inst, fn, arg) { + for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); +} +function getListener(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +function accumulateDirectionalDispatches(inst, phase, event) { + if ( + (phase = getListener( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + targetInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); + } +} +function accumulateTwoPhaseDispatchesSingle(event) { + event && + event.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); +} +var ResponderEventPlugin = { _getResponder: function() { return responderInst; }, @@ -571,68 +547,70 @@ var eventTypes = { JSCompiler_temp = null; } else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp === responderInst; - JSCompiler_temp = ResponderSyntheticEvent.getPooled( + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( shouldSetEventType, - JSCompiler_temp, + targetInst, nativeEvent, nativeEventTarget ); - JSCompiler_temp.touchHistory = ResponderTouchHistoryStore.touchHistory; - targetInst + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp ? forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingleSkipTarget ) : forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingle ); b: { - shouldSetEventType = JSCompiler_temp._dispatchListeners; - targetInst = JSCompiler_temp._dispatchInstances; - if (Array.isArray(shouldSetEventType)) + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (Array.isArray(JSCompiler_temp)) for ( depthA = 0; - depthA < shouldSetEventType.length && - !JSCompiler_temp.isPropagationStopped(); + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); depthA++ ) { if ( - shouldSetEventType[depthA](JSCompiler_temp, targetInst[depthA]) + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - shouldSetEventType = targetInst[depthA]; + JSCompiler_temp = targetInst[depthA]; break b; } } else if ( - shouldSetEventType && - shouldSetEventType(JSCompiler_temp, targetInst) + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) ) { - shouldSetEventType = targetInst; + JSCompiler_temp = targetInst; break b; } - shouldSetEventType = null; + JSCompiler_temp = null; } - JSCompiler_temp._dispatchInstances = null; - JSCompiler_temp._dispatchListeners = null; - JSCompiler_temp.isPersistent() || - JSCompiler_temp.constructor.release(JSCompiler_temp); - if (shouldSetEventType && shouldSetEventType !== responderInst) + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) if ( - ((JSCompiler_temp = ResponderSyntheticEvent.getPooled( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderGrant, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), - (JSCompiler_temp.touchHistory = + (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateDirectDispatchesSingle ), - (targetInst = !0 === executeDirectDispatch(JSCompiler_temp)), + (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) ) if ( @@ -659,13 +637,13 @@ var eventTypes = { forEachAccumulated(depthA, accumulateDirectDispatchesSingle); var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - [JSCompiler_temp, depthA] + [shouldSetEventType, depthA] ); - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); } else (shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderReject, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), @@ -682,9 +660,9 @@ var eventTypes = { else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - JSCompiler_temp + shouldSetEventType )), - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); else JSCompiler_temp$jscomp$0 = null; } else JSCompiler_temp$jscomp$0 = null; shouldSetEventType = responderInst && isStartish(topLevelType); @@ -812,7 +790,6 @@ function recomputePluginOrdering() { for (var eventName in pluginIndex) { var JSCompiler_inline_result = void 0; var dispatchConfig = pluginIndex[eventName], - pluginModule$jscomp$0 = pluginModule, eventName$jscomp$0 = eventName; if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( @@ -829,7 +806,7 @@ function recomputePluginOrdering() { ) && publishRegistrationName( phasedRegistrationNames[JSCompiler_inline_result], - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ); JSCompiler_inline_result = !0; @@ -837,7 +814,7 @@ function recomputePluginOrdering() { dispatchConfig.registrationName ? (publishRegistrationName( dispatchConfig.registrationName, - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ), (JSCompiler_inline_result = !0)) @@ -865,13 +842,75 @@ function publishRegistrationName(registrationName, pluginModule) { } var plugins = [], eventNameDispatchConfigs = {}, - registrationNameModules = {}, - customBubblingEventTypes = + registrationNameModules = {}; +function getListener$1(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; +function accumulateDirectionalDispatches$1(inst, phase, event) { + if ( + (phase = getListener$1( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + for (var inst = event._targetInst, path = []; inst; ) { + path.push(inst); + do inst = inst.return; + while (inst && 5 !== inst.tag); + inst = inst ? inst : null; + } + for (inst = path.length; 0 < inst--; ) + accumulateDirectionalDispatches$1(path[inst], "captured", event); + for (inst = 0; inst < path.length; inst++) + accumulateDirectionalDispatches$1(path[inst], "bubbled", event); + } +} +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener$1(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} if (eventPluginOrder) throw Error( "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React." @@ -881,7 +920,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_92 = { +var injectedNamesToPlugins$jscomp$inline_219 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -905,42 +944,45 @@ var injectedNamesToPlugins$jscomp$inline_92 = { nativeEventTarget ); if (bubbleDispatchConfig) - forEachAccumulated(topLevelType, accumulateTwoPhaseDispatchesSingle); + forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle); + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); else return null; return topLevelType; } } }, - isOrderingDirty$jscomp$inline_93 = !1, - pluginName$jscomp$inline_94; -for (pluginName$jscomp$inline_94 in injectedNamesToPlugins$jscomp$inline_92) + isOrderingDirty$jscomp$inline_220 = !1, + pluginName$jscomp$inline_221; +for (pluginName$jscomp$inline_221 in injectedNamesToPlugins$jscomp$inline_219) if ( - injectedNamesToPlugins$jscomp$inline_92.hasOwnProperty( - pluginName$jscomp$inline_94 + injectedNamesToPlugins$jscomp$inline_219.hasOwnProperty( + pluginName$jscomp$inline_221 ) ) { - var pluginModule$jscomp$inline_95 = - injectedNamesToPlugins$jscomp$inline_92[pluginName$jscomp$inline_94]; + var pluginModule$jscomp$inline_222 = + injectedNamesToPlugins$jscomp$inline_219[pluginName$jscomp$inline_221]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_94) || - namesToPlugins[pluginName$jscomp$inline_94] !== - pluginModule$jscomp$inline_95 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_221) || + namesToPlugins[pluginName$jscomp$inline_221] !== + pluginModule$jscomp$inline_222 ) { - if (namesToPlugins[pluginName$jscomp$inline_94]) + if (namesToPlugins[pluginName$jscomp$inline_221]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_94 + + pluginName$jscomp$inline_221 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_94 - ] = pluginModule$jscomp$inline_95; - isOrderingDirty$jscomp$inline_93 = !0; + pluginName$jscomp$inline_221 + ] = pluginModule$jscomp$inline_222; + isOrderingDirty$jscomp$inline_220 = !0; } } -isOrderingDirty$jscomp$inline_93 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_220 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -964,31 +1006,42 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler({ } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher") || - (ReactSharedInternals.ReactCurrentDispatcher = { current: null }); -ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig") || - (ReactSharedInternals.ReactCurrentBatchConfig = { suspense: null }); -var hasSymbol = "function" === typeof Symbol && Symbol.for, - REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, - REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, - REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, - REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, - REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, - REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, - REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 60111, - REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, - REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 60120, - REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115, - REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116, - REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121, - MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + REACT_ELEMENT_TYPE = 60103, + REACT_PORTAL_TYPE = 60106, + REACT_FRAGMENT_TYPE = 60107, + REACT_STRICT_MODE_TYPE = 60108, + REACT_PROFILER_TYPE = 60114, + REACT_PROVIDER_TYPE = 60109, + REACT_CONTEXT_TYPE = 60110, + REACT_FORWARD_REF_TYPE = 60112, + REACT_SUSPENSE_TYPE = 60113, + REACT_SUSPENSE_LIST_TYPE = 60120, + REACT_MEMO_TYPE = 60115, + REACT_LAZY_TYPE = 60116, + REACT_DEBUG_TRACING_MODE_TYPE = 60129, + REACT_OFFSCREEN_TYPE = 60130, + REACT_LEGACY_HIDDEN_TYPE = 60131; +if ("function" === typeof Symbol && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + symbolFor("react.scope"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} +var MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "object" !== typeof maybeIterable) return null; maybeIterable = @@ -996,27 +1049,6 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } -function initializeLazyComponentType(lazyComponent) { - if (-1 === lazyComponent._status) { - var ctor = lazyComponent._result; - ctor || (ctor = lazyComponent._ctor); - ctor = ctor(); - lazyComponent._status = 0; - lazyComponent._result = ctor; - ctor.then( - function(moduleObject) { - 0 === lazyComponent._status && - ((moduleObject = moduleObject.default), - (lazyComponent._status = 1), - (lazyComponent._result = moduleObject)); - }, - function(error) { - 0 === lazyComponent._status && - ((lazyComponent._status = 2), (lazyComponent._result = error)); - } - ); - } -} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1050,11 +1082,12 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); case REACT_LAZY_TYPE: - if ((type = 1 === type._status ? type._result : null)) - return getComponentName(type); + innerType = type._payload; + type = type._init; + try { + return getComponentName(type(innerType)); + } catch (x) {} } return null; } @@ -1066,7 +1099,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1106,36 +1139,36 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { + for (var didFindChild = !1, child$0 = parentA.child; child$0; ) { + if (child$0 === a) { didFindChild = !0; a = parentA; b = parentB; break; } - if (_child === b) { + if (child$0 === b) { didFindChild = !0; b = parentA; a = parentB; break; } - _child = _child.sibling; + child$0 = child$0.sibling; } if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { + for (child$0 = parentB.child; child$0; ) { + if (child$0 === a) { didFindChild = !0; a = parentB; b = parentA; break; } - if (_child === b) { + if (child$0 === b) { didFindChild = !0; b = parentB; a = parentA; break; } - _child = _child.sibling; + child$0 = child$0.sibling; } if (!didFindChild) throw Error( @@ -1170,6 +1203,18 @@ function findCurrentHostFiber(parent) { } return null; } +function doesFiberContain(parentFiber, childFiber) { + for ( + var parentFiberAlternate = parentFiber.alternate; + null !== childFiber; + + ) { + if (childFiber === parentFiber || childFiber === parentFiberAlternate) + return !0; + childFiber = childFiber.return; + } + return !1; +} function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { return function() { if ( @@ -1383,19 +1428,19 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ), (removedKeys = null)); } - for (var _propKey in prevProps) - void 0 === nextProps[_propKey] && - (!(attributeConfig = validAttributes[_propKey]) || - (updatePayload && void 0 !== updatePayload[_propKey]) || - ((prevProp = prevProps[_propKey]), + for (var propKey$2 in prevProps) + void 0 === nextProps[propKey$2] && + (!(attributeConfig = validAttributes[propKey$2]) || + (updatePayload && void 0 !== updatePayload[propKey$2]) || + ((prevProp = prevProps[propKey$2]), void 0 !== prevProp && ("object" !== typeof attributeConfig || "function" === typeof attributeConfig.diff || "function" === typeof attributeConfig.process - ? (((updatePayload || (updatePayload = {}))[_propKey] = null), + ? (((updatePayload || (updatePayload = {}))[propKey$2] = null), removedKeys || (removedKeys = {}), - removedKeys[_propKey] || - ((removedKeys[_propKey] = !0), removedKeyCount++)) + removedKeys[propKey$2] || + ((removedKeys[propKey$2] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( updatePayload, prevProp, @@ -1443,37 +1488,49 @@ function dispatchEvent(target, topLevelType, nativeEvent) { null != stateNode && (eventTarget = stateNode.canonical); } batchedUpdates(function() { - var events = eventTarget; - for (var events$jscomp$0 = null, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; + var JSCompiler_inline_result = eventTarget; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; possiblePlugin && (possiblePlugin = possiblePlugin.extractEvents( topLevelType, target, nativeEvent, - events, - 1 + JSCompiler_inline_result )) && - (events$jscomp$0 = accumulateInto(events$jscomp$0, possiblePlugin)); + (events = accumulateInto(events, possiblePlugin)); } - events = events$jscomp$0; - null !== events && (eventQueue = accumulateInto(eventQueue, events)); - events = eventQueue; + JSCompiler_inline_result = events; + null !== JSCompiler_inline_result && + (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); + JSCompiler_inline_result = eventQueue; eventQueue = null; - if (events) { - forEachAccumulated(events, executeDispatchesAndReleaseTopLevel); + if (JSCompiler_inline_result) { + forEachAccumulated( + JSCompiler_inline_result, + executeDispatchesAndReleaseTopLevel + ); if (eventQueue) throw Error( "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." ); if (hasRethrowError) - throw ((events = rethrowError), + throw ((JSCompiler_inline_result = rethrowError), (hasRethrowError = !1), (rethrowError = null), - events); + JSCompiler_inline_result); } }); } +function shim() { + throw Error( + "The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue." + ); +} function shim$1() { throw Error( "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." @@ -1566,19 +1623,32 @@ var scheduleTimeout = setTimeout, cancelTimeout = clearTimeout; function cloneHiddenInstance(instance) { var node = instance.node; - var updatePayload = diffProperties( + var JSCompiler_inline_result = diffProperties( null, emptyObject, { style: { display: "none" } }, instance.canonical.viewConfig.validAttributes ); return { - node: cloneNodeWithNewProps(node, updatePayload), + node: cloneNodeWithNewProps(node, JSCompiler_inline_result), canonical: instance.canonical }; } -var valueStack = [], +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; +} +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; +} +var valueStack = [], index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} function pop(cursor) { 0 > index || ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); @@ -1589,8 +1659,8 @@ function push(cursor, value) { cursor.current = value; } var emptyContextObject = {}, - contextStackCursor = { current: emptyContextObject }, - didPerformWorkStackCursor = { current: !1 }, + contextStackCursor = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyContextObject; function getMaskedContext(workInProgress, unmaskedContext) { var contextTypes = workInProgress.type.contextTypes; @@ -1639,7 +1709,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1670,11 +1740,204 @@ function invalidateContextProvider(workInProgress, type, didChange) { : pop(didPerformWorkStackCursor); push(didPerformWorkStackCursor, didChange); } +var rendererID = null, + injectedHook = null, + Scheduler_now = Scheduler.unstable_now; +Scheduler_now(); +var return_highestLanePriority = 8; +function getHighestPriorityLanes(lanes) { + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; + var inputDiscreteLanes = 24 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 12), inputDiscreteLanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 10), inputDiscreteLanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 8), inputDiscreteLanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 6), inputDiscreteLanes; + inputDiscreteLanes = 62914560 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 5), inputDiscreteLanes; + if (lanes & 67108864) return (return_highestLanePriority = 4), 67108864; + if (0 !== (lanes & 134217728)) + return (return_highestLanePriority = 3), 134217728; + inputDiscreteLanes = 805306368 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 2), inputDiscreteLanes; + if (0 !== (1073741824 & lanes)) + return (return_highestLanePriority = 1), 1073741824; + return_highestLanePriority = 8; + return lanes; +} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case 99: + return 15; + case 98: + return 10; + case 97: + case 96: + return 8; + case 95: + return 2; + default: + return 0; + } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case 15: + case 14: + return 99; + case 13: + case 12: + case 11: + case 10: + return 98; + case 9: + case 8: + case 7: + case 6: + case 4: + case 5: + return 97; + case 3: + case 2: + case 1: + return 95; + case 0: + return 90; + default: + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} +function getNextLanes(root, wipLanes) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return (return_highestLanePriority = 0); + var nextLanes = 0, + nextLanePriority = 0, + expiredLanes = root.expiredLanes, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes; + if (0 !== expiredLanes) + (nextLanes = expiredLanes), + (nextLanePriority = return_highestLanePriority = 15); + else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { + var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; + 0 !== nonIdleUnblockedLanes + ? ((nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)), + (nextLanePriority = return_highestLanePriority)) + : ((pingedLanes &= expiredLanes), + 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority))); + } else + (expiredLanes = pendingLanes & ~suspendedLanes), + 0 !== expiredLanes + ? ((nextLanes = getHighestPriorityLanes(expiredLanes)), + (nextLanePriority = return_highestLanePriority)) + : 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority)); + if (0 === nextLanes) return 0; + nextLanes = 31 - clz32(nextLanes); + nextLanes = pendingLanes & (((0 > nextLanes ? 0 : 1 << nextLanes) << 1) - 1); + if ( + 0 !== wipLanes && + wipLanes !== nextLanes && + 0 === (wipLanes & suspendedLanes) + ) { + getHighestPriorityLanes(wipLanes); + if (nextLanePriority <= return_highestLanePriority) return wipLanes; + return_highestLanePriority = nextLanePriority; + } + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (nextLanePriority = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~nextLanePriority); + return nextLanes; +} +function getLanesToRetrySynchronouslyOnError(root) { + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; +} +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case 15: + return 1; + case 14: + return 2; + case 12: + return ( + (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + ); + case 10: + return ( + (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority + ); + case 8: + return ( + (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), + 0 === lanePriority && + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), + 0 === lanePriority && (lanePriority = 512)), + lanePriority + ); + case 2: + return ( + (wipLanes = getHighestPriorityLane(805306368 & ~wipLanes)), + 0 === wipLanes && (wipLanes = 268435456), + wipLanes + ); + } + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); +} +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + var higherPriorityLanes = updateLane - 1; + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, + log = Math.log, + LN2 = Math.LN2; +function clz32Fallback(lanes) { + return 0 === lanes ? 32 : (31 - ((log(lanes) / LN2) | 0)) | 0; +} var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, + Scheduler_shouldYield = Scheduler.unstable_shouldYield, Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, + Scheduler_now$1 = Scheduler.unstable_now, Scheduler_getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel, Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, @@ -1683,18 +1946,17 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_LowPriority = Scheduler.unstable_LowPriority, Scheduler_IdlePriority = Scheduler.unstable_IdlePriority, fakeCallbackNode = {}, - shouldYield = Scheduler.unstable_shouldYield, requestPaint = void 0 !== Scheduler_requestPaint ? Scheduler_requestPaint : function() {}, syncQueue = null, immediateQueueCallbackNode = null, isFlushingSyncQueue = !1, - initialTimeMs = Scheduler_now(), + initialTimeMs$1 = Scheduler_now$1(), now = - 1e4 > initialTimeMs - ? Scheduler_now + 1e4 > initialTimeMs$1 + ? Scheduler_now$1 : function() { - return Scheduler_now() - initialTimeMs; + return Scheduler_now$1() - initialTimeMs$1; }; function getCurrentPriorityLevel() { switch (Scheduler_getCurrentPriorityLevel()) { @@ -1736,16 +1998,6 @@ function scheduleCallback(reactPriorityLevel, callback, options) { reactPriorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); return Scheduler_scheduleCallback(reactPriorityLevel, callback, options); } -function scheduleSyncCallback(callback) { - null === syncQueue - ? ((syncQueue = [callback]), - (immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ))) - : syncQueue.push(callback); - return fakeCallbackNode; -} function flushSyncCallbackQueue() { if (null !== immediateQueueCallbackNode) { var node = immediateQueueCallbackNode; @@ -1780,6 +2032,7 @@ function flushSyncCallbackQueueImpl() { } } } +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -1805,42 +2058,27 @@ function shallowEqual(objA, objB) { return !1; return !0; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; -function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 3: - case 4: - case 6: - case 7: - case 10: - case 9: - var JSCompiler_inline_result = ""; - break a; - default: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource, - name = getComponentName(workInProgress.type); - JSCompiler_inline_result = null; - owner && (JSCompiler_inline_result = getComponentName(owner.type)); - owner = name; - name = ""; - source - ? (name = - " (at " + - source.fileName.replace(BEFORE_SLASH_RE, "") + - ":" + - source.lineNumber + - ")") - : JSCompiler_inline_result && - (name = " (created by " + JSCompiler_inline_result + ")"); - JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress.return; - } while (workInProgress); - return info; +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } } function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { @@ -1849,10 +2087,11 @@ function resolveDefaultProps(Component, baseProps) { for (var propName in Component) void 0 === baseProps[propName] && (baseProps[propName] = Component[propName]); + return baseProps; } return baseProps; } -var valueCursor = { current: null }, +var valueCursor = createCursor(null), currentlyRenderingFiber = null, lastContextDependency = null, lastContextWithAllBitsObserved = null; @@ -1864,31 +2103,29 @@ function popProvider(providerFiber) { pop(valueCursor); providerFiber.type._context._currentValue2 = currentValue; } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { +function scheduleWorkOnParentPath(parent, renderLanes) { for (; null !== parent; ) { var alternate = parent.alternate; - if (parent.childExpirationTime < renderExpirationTime) - (parent.childExpirationTime = renderExpirationTime), - null !== alternate && - alternate.childExpirationTime < renderExpirationTime && - (alternate.childExpirationTime = renderExpirationTime); - else if ( - null !== alternate && - alternate.childExpirationTime < renderExpirationTime - ) - alternate.childExpirationTime = renderExpirationTime; - else break; + if ((parent.childLanes & renderLanes) === renderLanes) + if ( + null === alternate || + (alternate.childLanes & renderLanes) === renderLanes + ) + break; + else alternate.childLanes |= renderLanes; + else + (parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes); parent = parent.return; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextWithAllBitsObserved = lastContextDependency = null; workInProgress = workInProgress.dependencies; null !== workInProgress && null !== workInProgress.firstContext && - (workInProgress.expirationTime >= renderExpirationTime && - (didReceiveUpdate = !0), + (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), (workInProgress.firstContext = null)); } function readContext(context, observedBits) { @@ -1907,7 +2144,7 @@ function readContext(context, observedBits) { ); lastContextDependency = observedBits; currentlyRenderingFiber.dependencies = { - expirationTime: 0, + lanes: 0, firstContext: observedBits, responders: null }; @@ -1919,7 +2156,8 @@ var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, effects: null }; @@ -1929,21 +2167,21 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue === current && (workInProgress.updateQueue = { baseState: current.baseState, - baseQueue: current.baseQueue, + firstBaseUpdate: current.firstBaseUpdate, + lastBaseUpdate: current.lastBaseUpdate, shared: current.shared, effects: current.effects }); } -function createUpdate(expirationTime, suspenseConfig) { - expirationTime = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, +function createUpdate(eventTime, lane) { + return { + eventTime: eventTime, + lane: lane, tag: 0, payload: null, callback: null, next: null }; - return (expirationTime.next = expirationTime); } function enqueueUpdate(fiber, update) { fiber = fiber.updateQueue; @@ -1956,132 +2194,177 @@ function enqueueUpdate(fiber, update) { fiber.pending = update; } } -function enqueueCapturedUpdate(workInProgress, update) { - var current = workInProgress.alternate; - null !== current && cloneUpdateQueue(current, workInProgress); - workInProgress = workInProgress.updateQueue; - current = workInProgress.baseQueue; - null === current - ? ((workInProgress.baseQueue = update.next = update), - (update.next = update)) - : ((update.next = current.next), (current.next = update)); +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + var queue = workInProgress.updateQueue, + current = workInProgress.alternate; + if ( + null !== current && + ((current = current.updateQueue), queue === current) + ) { + var newFirst = null, + newLast = null; + queue = queue.firstBaseUpdate; + if (null !== queue) { + do { + var clone = { + eventTime: queue.eventTime, + lane: queue.lane, + tag: queue.tag, + payload: queue.payload, + callback: queue.callback, + next: null + }; + null === newLast + ? (newFirst = newLast = clone) + : (newLast = newLast.next = clone); + queue = queue.next; + } while (null !== queue); + null === newLast + ? (newFirst = newLast = capturedUpdate) + : (newLast = newLast.next = capturedUpdate); + } else newFirst = newLast = capturedUpdate; + queue = { + baseState: current.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: current.shared, + effects: current.effects + }; + workInProgress.updateQueue = queue; + return; + } + workInProgress = queue.lastBaseUpdate; + null === workInProgress + ? (queue.firstBaseUpdate = capturedUpdate) + : (workInProgress.next = capturedUpdate); + queue.lastBaseUpdate = capturedUpdate; } function processUpdateQueue( workInProgress$jscomp$0, props, instance, - renderExpirationTime + renderLanes ) { var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; - var baseQueue = queue.baseQueue, + var firstBaseUpdate = queue.firstBaseUpdate, + lastBaseUpdate = queue.lastBaseUpdate, pendingQueue = queue.shared.pending; if (null !== pendingQueue) { - if (null !== baseQueue) { - var baseFirst = baseQueue.next; - baseQueue.next = pendingQueue.next; - pendingQueue.next = baseFirst; - } - baseQueue = pendingQueue; queue.shared.pending = null; - baseFirst = workInProgress$jscomp$0.alternate; - null !== baseFirst && - ((baseFirst = baseFirst.updateQueue), - null !== baseFirst && (baseFirst.baseQueue = pendingQueue)); + var lastPendingUpdate = pendingQueue, + firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; + null === lastBaseUpdate + ? (firstBaseUpdate = firstPendingUpdate) + : (lastBaseUpdate.next = firstPendingUpdate); + lastBaseUpdate = lastPendingUpdate; + var current = workInProgress$jscomp$0.alternate; + if (null !== current) { + current = current.updateQueue; + var currentLastBaseUpdate = current.lastBaseUpdate; + currentLastBaseUpdate !== lastBaseUpdate && + (null === currentLastBaseUpdate + ? (current.firstBaseUpdate = firstPendingUpdate) + : (currentLastBaseUpdate.next = firstPendingUpdate), + (current.lastBaseUpdate = lastPendingUpdate)); + } } - if (null !== baseQueue) { - baseFirst = baseQueue.next; - var newState = queue.baseState, - newExpirationTime = 0, - newBaseState = null, - newBaseQueueFirst = null, - newBaseQueueLast = null; - if (null !== baseFirst) { - var update = baseFirst; - do { - pendingQueue = update.expirationTime; - if (pendingQueue < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, + if (null !== firstBaseUpdate) { + currentLastBaseUpdate = queue.baseState; + lastBaseUpdate = 0; + current = firstPendingUpdate = lastPendingUpdate = null; + do { + pendingQueue = firstBaseUpdate.lane; + var updateEventTime = firstBaseUpdate.eventTime; + if ((renderLanes & pendingQueue) === pendingQueue) { + null !== current && + (current = current.next = { + eventTime: updateEventTime, + lane: 0, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, next: null - }; - null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone), - (newBaseState = newState)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - pendingQueue > newExpirationTime && - (newExpirationTime = pendingQueue); - } else { - null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }); - markRenderEventTimeAndConfig(pendingQueue, update.suspenseConfig); - a: { - var workInProgress = workInProgress$jscomp$0, - update$jscomp$0 = update; - pendingQueue = props; - clone = instance; - switch (update$jscomp$0.tag) { - case 1: - workInProgress = update$jscomp$0.payload; - if ("function" === typeof workInProgress) { - newState = workInProgress.call(clone, newState, pendingQueue); - break a; - } - newState = workInProgress; - break a; - case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; - case 0: - workInProgress = update$jscomp$0.payload; - pendingQueue = - "function" === typeof workInProgress - ? workInProgress.call(clone, newState, pendingQueue) - : workInProgress; - if (null === pendingQueue || void 0 === pendingQueue) break a; - newState = Object.assign({}, newState, pendingQueue); + }); + a: { + var workInProgress = workInProgress$jscomp$0, + update = firstBaseUpdate; + pendingQueue = props; + updateEventTime = instance; + switch (update.tag) { + case 1: + workInProgress = update.payload; + if ("function" === typeof workInProgress) { + currentLastBaseUpdate = workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ); break a; - case 2: - hasForceUpdate = !0; - } + } + currentLastBaseUpdate = workInProgress; + break a; + case 3: + workInProgress.flags = (workInProgress.flags & -8193) | 64; + case 0: + workInProgress = update.payload; + pendingQueue = + "function" === typeof workInProgress + ? workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ) + : workInProgress; + if (null === pendingQueue || void 0 === pendingQueue) break a; + currentLastBaseUpdate = Object.assign( + {}, + currentLastBaseUpdate, + pendingQueue + ); + break a; + case 2: + hasForceUpdate = !0; } - null !== update.callback && - ((workInProgress$jscomp$0.effectTag |= 32), - (pendingQueue = queue.effects), - null === pendingQueue - ? (queue.effects = [update]) - : pendingQueue.push(update)); } - update = update.next; - if (null === update || update === baseFirst) - if (((pendingQueue = queue.shared.pending), null === pendingQueue)) - break; - else - (update = baseQueue.next = pendingQueue.next), - (pendingQueue.next = baseFirst), - (queue.baseQueue = baseQueue = pendingQueue), - (queue.shared.pending = null); - } while (1); - } - null === newBaseQueueLast - ? (newBaseState = newState) - : (newBaseQueueLast.next = newBaseQueueFirst); - queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; - markUnprocessedUpdateTime(newExpirationTime); - workInProgress$jscomp$0.expirationTime = newExpirationTime; - workInProgress$jscomp$0.memoizedState = newState; + null !== firstBaseUpdate.callback && + ((workInProgress$jscomp$0.flags |= 32), + (pendingQueue = queue.effects), + null === pendingQueue + ? (queue.effects = [firstBaseUpdate]) + : pendingQueue.push(firstBaseUpdate)); + } else + (updateEventTime = { + eventTime: updateEventTime, + lane: pendingQueue, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, + next: null + }), + null === current + ? ((firstPendingUpdate = current = updateEventTime), + (lastPendingUpdate = currentLastBaseUpdate)) + : (current = current.next = updateEventTime), + (lastBaseUpdate |= pendingQueue); + firstBaseUpdate = firstBaseUpdate.next; + if (null === firstBaseUpdate) + if (((pendingQueue = queue.shared.pending), null === pendingQueue)) + break; + else + (firstBaseUpdate = pendingQueue.next), + (pendingQueue.next = null), + (queue.lastBaseUpdate = pendingQueue), + (queue.shared.pending = null); + } while (1); + null === current && (lastPendingUpdate = currentLastBaseUpdate); + queue.baseState = lastPendingUpdate; + queue.firstBaseUpdate = firstPendingUpdate; + queue.lastBaseUpdate = current; + workInProgressRootSkippedLanes |= lastBaseUpdate; + workInProgress$jscomp$0.lanes = lastBaseUpdate; + workInProgress$jscomp$0.memoizedState = currentLastBaseUpdate; } } function commitUpdateQueue(finishedWork, finishedQueue, instance) { @@ -2106,8 +2389,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2121,54 +2403,45 @@ function applyDerivedStateFromProps( ? ctor : Object.assign({}, ctor, getDerivedStateFromProps); workInProgress.memoizedState = getDerivedStateFromProps; - 0 === workInProgress.expirationTime && + 0 === workInProgress.lanes && (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { isMounted: function(component) { - return (component = component._reactInternalFiber) + return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, enqueueSetState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); } }; function checkShouldComponentUpdate( @@ -2206,7 +2479,7 @@ function constructClassInstance(workInProgress, ctor, props) { null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; ctor.updater = classComponentUpdater; workInProgress.stateNode = ctor; - ctor._reactInternalFiber = workInProgress; + ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), @@ -2227,12 +2500,7 @@ function callComponentWillReceiveProps( instance.state !== workInProgress && classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; instance.props = newProps; instance.state = workInProgress.memoizedState; @@ -2245,7 +2513,7 @@ function mountClassInstance( ? previousContext : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && @@ -2262,15 +2530,10 @@ function mountClassInstance( instance.UNSAFE_componentWillMount(), ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ), + processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2285,7 +2548,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2319,7 +2582,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2331,7 +2594,7 @@ function throwOnInvalidObjectType(returnFiber, newChild) { ("[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + "). If you meant to render a collection of children, use an array instead." ); } function ChildReconciler(shouldTrackSideEffects) { @@ -2343,7 +2606,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2375,26 +2638,22 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (null === current || 6 !== current.tag) return ( - (current = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromText(textContent, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2402,27 +2661,27 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (null !== current && current.elementType === element.type) return ( - (expirationTime = useFiber(current, element.props)), - (expirationTime.ref = coerceRef(returnFiber, current, element)), - (expirationTime.return = returnFiber), - expirationTime + (lanes = useFiber(current, element.props)), + (lanes.ref = coerceRef(returnFiber, current, element)), + (lanes.return = returnFiber), + lanes ); - expirationTime = createFiberFromTypeAndProps( + lanes = createFiberFromTypeAndProps( element.type, element.key, element.props, null, returnFiber.mode, - expirationTime + lanes ); - expirationTime.ref = coerceRef(returnFiber, current, element); - expirationTime.return = returnFiber; - return expirationTime; + lanes.ref = coerceRef(returnFiber, current, element); + lanes.return = returnFiber; + return lanes; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( null === current || 4 !== current.tag || @@ -2430,11 +2689,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) return ( - (current = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromPortal(portal, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2442,13 +2697,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (null === current || 7 !== current.tag) return ( (current = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key )), (current.return = returnFiber), @@ -2458,13 +2713,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (newChild = createFiberFromText( "" + newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2473,24 +2728,24 @@ function ChildReconciler(shouldTrackSideEffects) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: return ( - (expirationTime = createFiberFromTypeAndProps( + (lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef(returnFiber, null, newChild)), - (expirationTime.return = returnFiber), - expirationTime + (lanes.ref = coerceRef(returnFiber, null, newChild)), + (lanes.return = returnFiber), + lanes ); case REACT_PORTAL_TYPE: return ( (newChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2501,7 +2756,7 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null )), (newChild.return = returnFiber), @@ -2511,12 +2766,12 @@ function ChildReconciler(shouldTrackSideEffects) { } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { var key = null !== oldFiber ? oldFiber.key : null; if ("string" === typeof newChild || "number" === typeof newChild) return null !== key ? null - : updateTextNode(returnFiber, oldFiber, "" + newChild, expirationTime); + : updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: @@ -2526,26 +2781,20 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ) - : updateElement(returnFiber, oldFiber, newChild, expirationTime) + : updateElement(returnFiber, oldFiber, newChild, lanes) : null; case REACT_PORTAL_TYPE: return newChild.key === key - ? updatePortal(returnFiber, oldFiber, newChild, expirationTime) + ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; } if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null - : updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + : updateFragment(returnFiber, oldFiber, newChild, lanes, null); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2555,17 +2804,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateTextNode( - returnFiber, - existingChildren, - "" + newChild, - expirationTime - ) + updateTextNode(returnFiber, existingChildren, "" + newChild, lanes) ); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { @@ -2580,15 +2824,10 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, existingChildren, newChild.props.children, - expirationTime, + lanes, newChild.key ) - : updateElement( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + : updateElement(returnFiber, existingChildren, newChild, lanes) ); case REACT_PORTAL_TYPE: return ( @@ -2596,24 +2835,13 @@ function ChildReconciler(shouldTrackSideEffects) { existingChildren.get( null === newChild.key ? newIdx : newChild.key ) || null), - updatePortal( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + updatePortal(returnFiber, existingChildren, newChild, lanes) ); } if (isArray(newChild) || getIteratorFn(newChild)) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateFragment( - returnFiber, - existingChildren, - newChild, - expirationTime, - null - ) + updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); throwOnInvalidObjectType(returnFiber, newChild); } @@ -2623,7 +2851,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { for ( var resultingFirstChild = null, @@ -2641,7 +2869,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); @@ -2664,11 +2892,7 @@ function ChildReconciler(shouldTrackSideEffects) { ); if (null === oldFiber) { for (; newIdx < newChildren.length; newIdx++) - (oldFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - )), + (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && ((currentFirstChild = placeChild( oldFiber, @@ -2691,7 +2915,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes )), null !== nextOldFiber && (shouldTrackSideEffects && @@ -2718,7 +2942,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { var iteratorFn = getIteratorFn(newChildrenIterable); if ("function" !== typeof iteratorFn) @@ -2740,12 +2964,7 @@ function ChildReconciler(shouldTrackSideEffects) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) : (nextOldFiber = oldFiber.sibling); - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); break; @@ -2765,7 +2984,7 @@ function ChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) - (step = createChild(returnFiber, step.value, expirationTime)), + (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber @@ -2779,13 +2998,7 @@ function ChildReconciler(shouldTrackSideEffects) { !step.done; newIdx++, step = newChildrenIterable.next() ) - (step = updateFromMap( - oldFiber, - returnFiber, - newIdx, - step.value, - expirationTime - )), + (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && (shouldTrackSideEffects && null !== step.alternate && @@ -2801,7 +3014,7 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, expirationTime) { + return function(returnFiber, currentFirstChild, newChild, lanes) { var isUnkeyedTopLevelFragment = "object" === typeof newChild && null !== newChild && @@ -2867,26 +3080,26 @@ function ChildReconciler(shouldTrackSideEffects) { ? ((currentFirstChild = createFiberFromFragment( newChild.props.children, returnFiber.mode, - expirationTime, + lanes, newChild.key )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) - : ((expirationTime = createFiberFromTypeAndProps( + : ((lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef( + (lanes.ref = coerceRef( returnFiber, currentFirstChild, newChild )), - (expirationTime.return = returnFiber), - (returnFiber = expirationTime)); + (lanes.return = returnFiber), + (returnFiber = lanes)); } return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: @@ -2925,7 +3138,7 @@ function ChildReconciler(shouldTrackSideEffects) { currentFirstChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); currentFirstChild.return = returnFiber; returnFiber = currentFirstChild; @@ -2944,7 +3157,7 @@ function ChildReconciler(shouldTrackSideEffects) { (currentFirstChild = createFiberFromText( newChild, returnFiber.mode, - expirationTime + lanes )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)), @@ -2955,25 +3168,26 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); if (getIteratorFn(newChild)) return reconcileChildrenIterator( returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); isObject && throwOnInvalidObjectType(returnFiber, newChild); if ("undefined" === typeof newChild && !isUnkeyedTopLevelFragment) switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -2981,9 +3195,9 @@ function ChildReconciler(shouldTrackSideEffects) { var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), NO_CONTEXT = {}, - contextStackCursor$1 = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + contextStackCursor$1 = createCursor(NO_CONTEXT), + contextFiberStackCursor = createCursor(NO_CONTEXT), + rootInstanceStackCursor = createCursor(NO_CONTEXT); function requiredContext(c) { if (c === NO_CONTEXT) throw Error( @@ -3006,26 +3220,26 @@ function popHostContainer() { function pushHostContext(fiber) { requiredContext(rootInstanceStackCursor.current); var context = requiredContext(contextStackCursor$1.current); - var nextContext = fiber.type; - nextContext = - "AndroidTextInput" === nextContext || - "RCTMultilineTextInputView" === nextContext || - "RCTSinglelineTextInputView" === nextContext || - "RCTText" === nextContext || - "RCTVirtualText" === nextContext; - nextContext = - context.isInAParentText !== nextContext - ? { isInAParentText: nextContext } + var JSCompiler_inline_result = fiber.type; + JSCompiler_inline_result = + "AndroidTextInput" === JSCompiler_inline_result || + "RCTMultilineTextInputView" === JSCompiler_inline_result || + "RCTSinglelineTextInputView" === JSCompiler_inline_result || + "RCTText" === JSCompiler_inline_result || + "RCTVirtualText" === JSCompiler_inline_result; + JSCompiler_inline_result = + context.isInAParentText !== JSCompiler_inline_result + ? { isInAParentText: JSCompiler_inline_result } : context; - context !== nextContext && + context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, nextContext)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && (pop(contextStackCursor$1), pop(contextFiberStackCursor)); } -var suspenseStackCursor = { current: 0 }; +var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { for (var node = row; null !== node; ) { if (13 === node.tag) { @@ -3033,7 +3247,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3049,19 +3263,23 @@ function findFirstSuspended(row) { } return null; } -function createDeprecatedResponderListener(responder, props) { - return { responder: responder, props: props }; +var workInProgressSources = []; +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) + workInProgressSources[i]._workInProgressVersionSecondary = null; + workInProgressSources.length = 0; } -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig, - renderExpirationTime = 0, + renderLanes = 0, currentlyRenderingFiber$1 = null, currentHook = null, workInProgressHook = null, - didScheduleRenderPhaseUpdate = !1; + didScheduleRenderPhaseUpdate = !1, + didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3076,36 +3294,36 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = 0; - ReactCurrentDispatcher.current = + workInProgress.lanes = 0; + ReactCurrentDispatcher$1.current = null === current || null === current.memoizedState ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; current = Component(props, secondArg); - if (workInProgress.expirationTime === renderExpirationTime) { - nextRenderExpirationTime = 0; + if (didScheduleRenderPhaseUpdateDuringThisPass) { + nextRenderLanes = 0; do { - workInProgress.expirationTime = 0; - if (!(25 > nextRenderExpirationTime)) + didScheduleRenderPhaseUpdateDuringThisPass = !1; + if (!(25 > nextRenderLanes)) throw Error( "Too many re-renders. React limits the number of renders to prevent an infinite loop." ); - nextRenderExpirationTime += 1; + nextRenderLanes += 1; workInProgressHook = currentHook = null; workInProgress.updateQueue = null; - ReactCurrentDispatcher.current = HooksDispatcherOnRerender; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerender; current = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; workInProgress = null !== currentHook && null !== currentHook.next; - renderExpirationTime = 0; + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; didScheduleRenderPhaseUpdate = !1; if (workInProgress) @@ -3186,40 +3404,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var updateExpirationTime = update.expirationTime; - if (updateExpirationTime < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }; - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - updateExpirationTime > currentlyRenderingFiber$1.expirationTime && - ((currentlyRenderingFiber$1.expirationTime = updateExpirationTime), - markUnprocessedUpdateTime(updateExpirationTime)); - } else + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) null !== newBaseQueueLast && (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ), (current = update.eagerReducer === reducer ? update.eagerState : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3256,6 +3468,114 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + var getVersion = source._getVersion; + getVersion = getVersion(source._source); + var JSCompiler_inline_result = source._workInProgressVersionSecondary; + if (null !== JSCompiler_inline_result) + root = JSCompiler_inline_result === getVersion; + else if ( + ((root = root.mutableReadLanes), (root = (renderLanes & root) === root)) + ) + (source._workInProgressVersionSecondary = getVersion), + workInProgressSources.push(source); + if (root) return getSnapshot(source._source); + workInProgressSources.push(source); + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); +} +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + var getVersion = source._getVersion, + version = getVersion(source._source), + dispatcher = ReactCurrentDispatcher$1.current, + _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + setSnapshot = _dispatcher$useState[1], + snapshot = _dispatcher$useState[0]; + _dispatcher$useState = workInProgressHook; + var memoizedState = hook.memoizedState, + refs = memoizedState.refs, + prevGetSnapshot = refs.getSnapshot, + prevSource = memoizedState.source; + memoizedState = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { refs: refs, source: source, subscribe: subscribe }; + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; + refs.setSnapshot = setSnapshot; + var maybeNewVersion = getVersion(source._source); + if (!objectIs(version, maybeNewVersion)) { + maybeNewVersion = getSnapshot(source._source); + objectIs(snapshot, maybeNewVersion) || + (setSnapshot(maybeNewVersion), + (maybeNewVersion = requestUpdateLane(fiber)), + (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); + maybeNewVersion = root.mutableReadLanes; + root.entangledLanes |= maybeNewVersion; + for ( + var entanglements = root.entanglements, lanes = maybeNewVersion; + 0 < lanes; + + ) { + var index$11 = 31 - clz32(lanes), + lane = 1 << index$11; + entanglements[index$11] |= maybeNewVersion; + lanes &= ~lane; + } + } + }, + [getSnapshot, source, subscribe] + ); + dispatcher.useEffect( + function() { + return subscribe(source._source, function() { + var latestGetSnapshot = refs.getSnapshot, + latestSetSnapshot = refs.setSnapshot; + try { + latestSetSnapshot(latestGetSnapshot(source._source)); + var lane = requestUpdateLane(fiber); + root.mutableReadLanes |= lane & root.pendingLanes; + } catch (error) { + latestSetSnapshot(function() { + throw error; + }); + } + }); + }, + [source, subscribe] + ); + (objectIs(prevGetSnapshot, getSnapshot) && + objectIs(prevSource, source) && + objectIs(memoizedState, subscribe)) || + ((hook = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }), + (hook.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + hook + )), + (_dispatcher$useState.queue = hook), + (_dispatcher$useState.baseQueue = null), + (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); + return snapshot; +} +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} function mountState(initialState) { var hook = mountWorkInProgressHook(); "function" === typeof initialState && (initialState = initialState()); @@ -3292,17 +3612,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3310,12 +3630,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3354,13 +3674,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3388,65 +3701,60 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, fiber, suspenseConfig); - suspenseConfig = { - expirationTime: currentTime, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + var eventTime = requestEventTime(), + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || (null !== pending && pending === currentlyRenderingFiber$1) ) - (didScheduleRenderPhaseUpdate = !0), - (suspenseConfig.expirationTime = renderExpirationTime), - (currentlyRenderingFiber$1.expirationTime = renderExpirationTime); + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = !0; else { if ( - 0 === fiber.expirationTime && - (null === pending || 0 === pending.expirationTime) && + 0 === fiber.lanes && + (null === pending || 0 === pending.lanes) && ((pending = queue.lastRenderedReducer), null !== pending) ) try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { } - scheduleWork(fiber, currentTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function updateEventListener() {} var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -3459,14 +3767,21 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: !1 }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3512,39 +3827,44 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; + }, + useMutableSource: function(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { getSnapshot: getSnapshot, setSnapshot: null }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + throw Error("Not yet implemented"); }, - useEvent: function() {} + unstable_isNewReconciler: !1 }, HooksDispatcherOnUpdate = { readContext: readContext, @@ -3560,39 +3880,33 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; + }, + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return updateReducer(basicStateReducer)[0]; }, - useEvent: updateEventListener + unstable_isNewReconciler: !1 }, HooksDispatcherOnRerender = { readContext: readContext, @@ -3608,61 +3922,45 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; + }, + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return rerenderReducer(basicStateReducer)[0]; }, - useEvent: updateEventListener + unstable_isNewReconciler: !1 }, ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { workInProgress.child = null === current - ? mountChildFibers( - workInProgress, - null, - nextChildren, - renderExpirationTime - ) + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } function updateForwardRef( @@ -3670,33 +3968,28 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { Component = Component.render; var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, nextProps, ref, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, nextProps, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } function updateMemoComponent( @@ -3704,8 +3997,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (null === current) { var type = Component.type; @@ -3724,17 +4017,17 @@ function updateMemoComponent( workInProgress, type, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); current = createFiberFromTypeAndProps( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3742,19 +4035,14 @@ function updateMemoComponent( } type = current.child; if ( - updateExpirationTime < renderExpirationTime && - ((updateExpirationTime = type.memoizedProps), + 0 === (updateLanes & renderLanes) && + ((updateLanes = type.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps) && - current.ref === workInProgress.ref) + Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3765,26 +4053,63 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { - return null !== current && + if ( + null !== current && shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref && - ((didReceiveUpdate = !1), updateExpirationTime < renderExpirationTime) - ? ((workInProgress.expirationTime = current.expirationTime), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - )) - : updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderExpirationTime + current.ref === workInProgress.ref + ) + if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, + nextChildren = nextProps.children, + prevState = null !== current ? current.memoizedState : null; + if ( + "hidden" === nextProps.mode || + "unstable-defer-without-hiding" === nextProps.mode + ) + if (0 === (workInProgress.mode & 4)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes(workInProgress, renderLanes); + else if (0 !== (renderLanes & 1073741824)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes( + workInProgress, + null !== prevState ? prevState.baseLanes : renderLanes + ); + else + return ( + (current = + null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), + (workInProgress.lanes = workInProgress.childLanes = 1073741824), + (workInProgress.memoizedState = { baseLanes: current }), + pushRenderLanes(workInProgress, current), + null + ); + else + null !== prevState + ? ((nextProps = prevState.baseLanes | renderLanes), + (workInProgress.memoizedState = null)) + : (nextProps = renderLanes), + pushRenderLanes(workInProgress, nextProps); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } function markRef(current, workInProgress) { var ref = workInProgress.ref; @@ -3792,42 +4117,37 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { var context = isContextProvider(Component) ? previousContext : contextStackCursor.current; context = getMaskedContext(workInProgress, context); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); Component = renderWithHooks( current, workInProgress, Component, nextProps, context, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, Component, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } function updateClassComponent( @@ -3835,25 +4155,20 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (isContextProvider(Component)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ), + mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); else if (null === current) { var instance = workInProgress.stateNode, @@ -3884,12 +4199,7 @@ function updateClassComponent( hasForceUpdate = !1; var oldState = workInProgress.memoizedState; instance.state = oldState; - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -3922,9 +4232,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -3932,119 +4242,113 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); - } else - (instance = workInProgress.stateNode), - cloneUpdateQueue(current, workInProgress), - (oldProps = workInProgress.memoizedProps), - (instance.props = - workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps)), - (oldContext = instance.context), - (contextType = Component.contextType), - "object" === typeof contextType && null !== contextType - ? (contextType = readContext(contextType)) - : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), - (contextType = getMaskedContext(workInProgress, contextType))), - (getDerivedStateFromProps = Component.getDerivedStateFromProps), - (hasNewLifecycles = - "function" === typeof getDerivedStateFromProps || - "function" === typeof instance.getSnapshotBeforeUpdate) || - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || - ((oldProps !== nextProps || oldContext !== contextType) && - callComponentWillReceiveProps( + } else { + instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + oldProps = workInProgress.memoizedProps; + contextType = + workInProgress.type === workInProgress.elementType + ? oldProps + : resolveDefaultProps(workInProgress.type, oldProps); + instance.props = contextType; + hasNewLifecycles = workInProgress.pendingProps; + oldState = instance.context; + oldContext = Component.contextType; + "object" === typeof oldContext && null !== oldContext + ? (oldContext = readContext(oldContext)) + : ((oldContext = isContextProvider(Component) + ? previousContext + : contextStackCursor.current), + (oldContext = getMaskedContext(workInProgress, oldContext))); + var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; + (getDerivedStateFromProps = + "function" === typeof getDerivedStateFromProps$jscomp$0 || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || + ((oldProps !== hasNewLifecycles || oldState !== oldContext) && + callComponentWillReceiveProps( + workInProgress, + instance, + nextProps, + oldContext + )); + hasForceUpdate = !1; + oldState = workInProgress.memoizedState; + instance.state = oldState; + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + var newState = workInProgress.memoizedState; + oldProps !== hasNewLifecycles || + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate + ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && + (applyDerivedStateFromProps( workInProgress, - instance, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), + (newState = workInProgress.memoizedState)), + (contextType = + hasForceUpdate || + checkShouldComponentUpdate( + workInProgress, + Component, + contextType, nextProps, - contextType - )), - (hasForceUpdate = !1), - (oldContext = workInProgress.memoizedState), - (instance.state = oldContext), - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ), - (oldState = workInProgress.memoizedState), - oldProps !== nextProps || - oldContext !== oldState || - didPerformWorkStackCursor.current || - hasForceUpdate - ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), - (oldState = workInProgress.memoizedState)), - (getDerivedStateFromProps = - hasForceUpdate || - checkShouldComponentUpdate( - workInProgress, - Component, - oldProps, - nextProps, - oldContext, - oldState, - contextType - )) - ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - nextProps, - oldState, - contextType - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - oldState, - contextType - )), - "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), - "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (workInProgress.memoizedProps = nextProps), - (workInProgress.memoizedState = oldState)), - (instance.props = nextProps), - (instance.state = oldState), - (instance.context = contextType), - (nextProps = getDerivedStateFromProps)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (nextProps = !1)); + oldState, + newState, + oldContext + )) + ? (getDerivedStateFromProps || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), + "function" === typeof instance.UNSAFE_componentWillUpdate && + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), + "function" === typeof instance.componentDidUpdate && + (workInProgress.flags |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.flags |= 256)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (workInProgress.memoizedProps = nextProps), + (workInProgress.memoizedState = newState)), + (instance.props = nextProps), + (instance.state = newState), + (instance.context = oldContext), + (nextProps = contextType)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (nextProps = !1)); + } return finishClassComponent( current, workInProgress, Component, nextProps, hasContext, - renderExpirationTime + renderLanes ); } function finishClassComponent( @@ -4053,18 +4357,14 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); shouldUpdate = workInProgress.stateNode; ReactCurrentOwner$1.current = workInProgress; @@ -4072,26 +4372,21 @@ function finishClassComponent( didCaptureError && "function" !== typeof Component.getDerivedStateFromError ? null : shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( workInProgress, current.child, null, - renderExpirationTime + renderLanes )), (workInProgress.child = reconcileChildFibers( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ))) - : reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + : reconcileChildren(current, workInProgress, nextChildren, renderLanes); workInProgress.memoizedState = shouldUpdate.state; hasContext && invalidateContextProvider(workInProgress, Component, !0); return workInProgress.child; @@ -4108,155 +4403,214 @@ function pushHostRootContext(workInProgress) { pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } -var SUSPENDED_MARKER = { dehydrated: null, retryTime: 0 }; -function updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime -) { - var mode = workInProgress.mode, - nextProps = workInProgress.pendingProps, +var SUSPENDED_MARKER = { dehydrated: null, retryLane: 0 }; +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, - nextDidTimeout = !1, + showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = - 0 !== (suspenseContext & 2) && - (null === current || null !== current.memoizedState)); + null !== current && null === current.memoizedState + ? !1 + : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((nextDidTimeout = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + current = nextProps.children; + suspenseContext = nextProps.fallback; + if (showFallback) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - mode = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( - workInProgress, - null, - mode, - renderExpirationTime - )); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + current + ); + renderLanes = createFiberFromOffscreen( + { mode: "visible", children: current }, + workInProgress.mode, + renderLanes, + null + ); + renderLanes.return = workInProgress; + return (workInProgress.child = renderLanes); } if (null !== current.memoizedState) { - current = current.child; - mode = current.sibling; - if (nextDidTimeout) { - nextProps = nextProps.fallback; - renderExpirationTime = createWorkInProgress( - current, - current.pendingProps + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - if ( - 0 === (workInProgress.mode & 2) && - ((nextDidTimeout = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child), - nextDidTimeout !== current.child) - ) - for ( - renderExpirationTime.child = nextDidTimeout; - null !== nextDidTimeout; - - ) - (nextDidTimeout.return = renderExpirationTime), - (nextDidTimeout = nextDidTimeout.sibling); - mode = createWorkInProgress(mode, nextProps); - mode.return = workInProgress; - renderExpirationTime.sibling = mode; - renderExpirationTime.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = renderExpirationTime; - return mode; - } - renderExpirationTime = reconcileChildFibers( + renderLanes = updateSuspensePrimaryChildren( + current, workInProgress, - current.child, nextProps.children, - renderExpirationTime + renderLanes ); workInProgress.memoizedState = null; - return (workInProgress.child = renderExpirationTime); + return renderLanes; } - current = current.child; - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - nextProps.child = current; - null !== current && (current.return = nextProps); - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - renderExpirationTime.effectTag |= 2; - nextProps.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - workInProgress.memoizedState = null; - return (workInProgress.child = reconcileChildFibers( - workInProgress, + renderLanes = updateSuspensePrimaryChildren( current, + workInProgress, nextProps.children, - renderExpirationTime - )); + renderLanes + ); + workInProgress.memoizedState = null; + return renderLanes; +} +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren)) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; } -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - fiber.expirationTime < renderExpirationTime && - (fiber.expirationTime = renderExpirationTime); +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + mode: "visible", + children: primaryChildren + }); + 0 === (workInProgress.mode & 2) && (primaryChildren.lanes = renderLanes); + primaryChildren.return = workInProgress; + primaryChildren.sibling = null; + null !== current && + ((current.nextEffect = null), + (current.flags = 8), + (workInProgress.firstEffect = workInProgress.lastEffect = current)); + return (workInProgress.child = primaryChildren); +} +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + var primaryChildProps = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && workInProgress.child !== currentPrimaryChildFragment + ? ((primaryChildren = workInProgress.child), + (primaryChildren.childLanes = 0), + (primaryChildren.pendingProps = primaryChildProps), + (currentPrimaryChildFragment = primaryChildren.lastEffect), + null !== currentPrimaryChildFragment + ? ((workInProgress.firstEffect = primaryChildren.firstEffect), + (workInProgress.lastEffect = currentPrimaryChildFragment), + (currentPrimaryChildFragment.nextEffect = null)) + : (workInProgress.firstEffect = workInProgress.lastEffect = null)) + : (primaryChildren = createWorkInProgress( + currentPrimaryChildFragment, + primaryChildProps + )); + null !== current + ? (fallbackChildren = createWorkInProgress(current, fallbackChildren)) + : ((fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + )), + (fallbackChildren.flags |= 2)); + fallbackChildren.return = workInProgress; + primaryChildren.return = workInProgress; + primaryChildren.sibling = fallbackChildren; + workInProgress.child = primaryChildren; + return fallbackChildren; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes |= renderLanes; var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < renderExpirationTime && - (alternate.expirationTime = renderExpirationTime); - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + null !== alternate && (alternate.lanes |= renderLanes); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function initSuspenseListRenderState( workInProgress, @@ -4274,7 +4628,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4283,35 +4636,24 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, revealOrder = nextProps.revealOrder, tailMode = nextProps.tail; - reconcileChildren( - current, - workInProgress, - nextProps.children, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderExpirationTime); - else if (19 === current.tag) - scheduleWorkOnFiber(current, renderExpirationTime); + scheduleWorkOnFiber(current, renderLanes); + else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -4333,30 +4675,29 @@ function updateSuspenseListComponent( else switch (revealOrder) { case "forwards": - renderExpirationTime = workInProgress.child; - for (revealOrder = null; null !== renderExpirationTime; ) - (current = renderExpirationTime.alternate), + renderLanes = workInProgress.child; + for (revealOrder = null; null !== renderLanes; ) + (current = renderLanes.alternate), null !== current && null === findFirstSuspended(current) && - (revealOrder = renderExpirationTime), - (renderExpirationTime = renderExpirationTime.sibling); - renderExpirationTime = revealOrder; - null === renderExpirationTime + (revealOrder = renderLanes), + (renderLanes = renderLanes.sibling); + renderLanes = revealOrder; + null === renderLanes ? ((revealOrder = workInProgress.child), (workInProgress.child = null)) - : ((revealOrder = renderExpirationTime.sibling), - (renderExpirationTime.sibling = null)); + : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); initSuspenseListRenderState( workInProgress, !1, revealOrder, - renderExpirationTime, + renderLanes, tailMode, workInProgress.lastEffect ); break; case "backwards": - renderExpirationTime = null; + renderLanes = null; revealOrder = workInProgress.child; for (workInProgress.child = null; null !== revealOrder; ) { current = revealOrder.alternate; @@ -4365,14 +4706,14 @@ function updateSuspenseListComponent( break; } current = revealOrder.sibling; - revealOrder.sibling = renderExpirationTime; - renderExpirationTime = revealOrder; + revealOrder.sibling = renderLanes; + renderLanes = revealOrder; revealOrder = current; } initSuspenseListRenderState( workInProgress, !0, - renderExpirationTime, + renderLanes, null, tailMode, workInProgress.lastEffect @@ -4393,35 +4734,28 @@ function updateSuspenseListComponent( } return workInProgress.child; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); - var updateExpirationTime = workInProgress.expirationTime; - 0 !== updateExpirationTime && markUnprocessedUpdateTime(updateExpirationTime); - if (workInProgress.childExpirationTime < renderExpirationTime) return null; - if (null !== current && workInProgress.child !== current.child) - throw Error("Resuming work not yet implemented."); - if (null !== workInProgress.child) { - current = workInProgress.child; - renderExpirationTime = createWorkInProgress(current, current.pendingProps); - workInProgress.child = renderExpirationTime; - for ( - renderExpirationTime.return = workInProgress; - null !== current.sibling; - - ) - (current = current.sibling), - (renderExpirationTime = renderExpirationTime.sibling = createWorkInProgress( - current, - current.pendingProps - )), - (renderExpirationTime.return = workInProgress); - renderExpirationTime.sibling = null; + workInProgressRootSkippedLanes |= workInProgress.lanes; + if (0 !== (renderLanes & workInProgress.childLanes)) { + if (null !== current && workInProgress.child !== current.child) + throw Error("Resuming work not yet implemented."); + if (null !== workInProgress.child) { + current = workInProgress.child; + renderLanes = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes; + for (renderLanes.return = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (renderLanes = renderLanes.sibling = createWorkInProgress( + current, + current.pendingProps + )), + (renderLanes.return = workInProgress); + renderLanes.sibling = null; + } + return workInProgress.child; } - return workInProgress.child; + return null; } var appendAllChildren, updateHostContainer, @@ -4448,7 +4782,7 @@ appendAllChildren = function( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4501,7 +4835,7 @@ function appendAllChildrenToContainer( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4545,7 +4879,7 @@ updateHostContainer = function(workInProgress) { newChildSet = createChildNodeSet(container); appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); portalOrRoot.pendingChildren = newChildSet; - workInProgress.effectTag |= 4; + workInProgress.flags |= 4; completeRoot(container, newChildSet); } }; @@ -4583,7 +4917,7 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { }), (workInProgress.stateNode = type), current - ? (workInProgress.effectTag |= 4) + ? (workInProgress.flags |= 4) : appendAllChildren(type, workInProgress, !1, !1)); } }; @@ -4597,7 +4931,7 @@ updateHostText$1 = function(current, workInProgress, oldText, newText) { oldText, workInProgress )), - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : (workInProgress.stateNode = current.stateNode); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { @@ -4614,17 +4948,17 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var _lastTailNode = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (_lastTailNode = lastTailNode), + for (var lastTailNode$64 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$64 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === _lastTailNode + null === lastTailNode$64 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (_lastTailNode.sibling = null); + : (lastTailNode$64.sibling = null); } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { case 2: @@ -4645,10 +4979,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { popHostContainer(), pop(didPerformWorkStackCursor), pop(contextStackCursor), - (current = workInProgress.stateNode), - current.pendingContext && - ((current.context = current.pendingContext), - (current.pendingContext = null)), + resetWorkInProgressVersions(), + (newProps = workInProgress.stateNode), + newProps.pendingContext && + ((newProps.context = newProps.pendingContext), + (newProps.pendingContext = null)), + (null !== current && null !== current.child) || + newProps.hydrate || + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4657,17 +4995,16 @@ function completeWork(current, workInProgress, renderExpirationTime) { var rootContainerInstance = requiredContext( rootInstanceStackCursor.current ); - renderExpirationTime = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) updateHostComponent$1( current, workInProgress, - renderExpirationTime, + renderLanes, newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -4679,30 +5016,30 @@ function completeWork(current, workInProgress, renderExpirationTime) { requiredContext(contextStackCursor$1.current); current = nextReactTag; nextReactTag += 2; - renderExpirationTime = getViewConfigForType(renderExpirationTime); + renderLanes = getViewConfigForType(renderLanes); var updatePayload = diffProperties( null, emptyObject, newProps, - renderExpirationTime.validAttributes + renderLanes.validAttributes ); rootContainerInstance = createNode( current, - renderExpirationTime.uiViewClassName, + renderLanes.uiViewClassName, rootContainerInstance, updatePayload, workInProgress ); current = new ReactFabricHostComponent( current, - renderExpirationTime, + renderLanes, newProps, workInProgress ); current = { node: rootContainerInstance, canonical: current }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -4731,52 +5068,35 @@ function completeWork(current, workInProgress, renderExpirationTime) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) - return ( - (workInProgress.expirationTime = renderExpirationTime), workInProgress - ); + if (0 !== (workInProgress.flags & 64)) + return (workInProgress.lanes = renderLanes), workInProgress; newProps = null !== newProps; rootContainerInstance = !1; null !== current && - ((renderExpirationTime = current.memoizedState), - (rootContainerInstance = null !== renderExpirationTime), - newProps || - null === renderExpirationTime || - ((renderExpirationTime = current.child.sibling), - null !== renderExpirationTime && - ((updatePayload = workInProgress.firstEffect), - null !== updatePayload - ? ((workInProgress.firstEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = updatePayload)) - : ((workInProgress.firstEffect = workInProgress.lastEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = null)), - (renderExpirationTime.effectTag = 8)))); + (rootContainerInstance = null !== current.memoizedState); if (newProps && !rootContainerInstance && 0 !== (workInProgress.mode & 2)) if ( (null === current && !0 !== workInProgress.memoizedProps.unstable_avoidThisFallback) || 0 !== (suspenseStackCursor.current & 1) ) - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootSuspended); + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3); else { if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended + 0 === workInProgressRootExitStatus || + 3 === workInProgressRootExitStatus ) - workInProgressRootExitStatus = RootSuspendedWithDelay; - 0 !== workInProgressRootNextUnprocessedUpdateTime && - null !== workInProgressRoot && - (markRootSuspendedAtTime( + workInProgressRootExitStatus = 4; + null === workInProgressRoot || + (0 === (workInProgressRootSkippedLanes & 134217727) && + 0 === (workInProgressRootUpdatedLanes & 134217727)) || + markRootSuspended$1( workInProgressRoot, - renderExpirationTime$1 - ), - markRootUpdatedAtTime( - workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime - )); + workInProgressRootRenderLanes + ); } - newProps && (workInProgress.effectTag |= 4); + newProps && (workInProgress.flags |= 4); return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -4788,48 +5108,48 @@ function completeWork(current, workInProgress, renderExpirationTime) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( - workInProgressRootExitStatus !== RootIncomplete || - (null !== current && 0 !== (current.effectTag & 64)) + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; - current = renderExpirationTime; + current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), - (renderExpirationTime = current), - (rootContainerInstance.effectTag &= 2), + (renderLanes = current), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), (updatePayload = rootContainerInstance.alternate), null === updatePayload - ? ((rootContainerInstance.childExpirationTime = 0), - (rootContainerInstance.expirationTime = renderExpirationTime), + ? ((rootContainerInstance.childLanes = 0), + (rootContainerInstance.lanes = renderLanes), (rootContainerInstance.child = null), (rootContainerInstance.memoizedProps = null), (rootContainerInstance.memoizedState = null), (rootContainerInstance.updateQueue = null), - (rootContainerInstance.dependencies = null)) - : ((rootContainerInstance.childExpirationTime = - updatePayload.childExpirationTime), - (rootContainerInstance.expirationTime = - updatePayload.expirationTime), + (rootContainerInstance.dependencies = null), + (rootContainerInstance.stateNode = null)) + : ((rootContainerInstance.childLanes = + updatePayload.childLanes), + (rootContainerInstance.lanes = updatePayload.lanes), (rootContainerInstance.child = updatePayload.child), (rootContainerInstance.memoizedProps = updatePayload.memoizedProps), @@ -4837,15 +5157,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { updatePayload.memoizedState), (rootContainerInstance.updateQueue = updatePayload.updateQueue), - (renderExpirationTime = updatePayload.dependencies), + (rootContainerInstance.type = updatePayload.type), + (renderLanes = updatePayload.dependencies), (rootContainerInstance.dependencies = - null === renderExpirationTime + null === renderLanes ? null : { - expirationTime: - renderExpirationTime.expirationTime, - firstContext: renderExpirationTime.firstContext, - responders: renderExpirationTime.responders + lanes: renderLanes.lanes, + firstContext: renderLanes.firstContext })), (newProps = newProps.sibling); push( @@ -4856,6 +5175,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432)); } else { if (!rootContainerInstance) @@ -4863,12 +5188,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -4881,13 +5206,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && - 1 < renderExpirationTime && - ((workInProgress.effectTag |= 64), + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.expirationTime = workInProgress.childExpirationTime = - renderExpirationTime - 1)); + (workInProgress.lanes = 33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -4898,9 +5223,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -4915,6 +5238,17 @@ function completeWork(current, workInProgress, renderExpirationTime) { ), current) : null; + case 22: + case 23: + return ( + popRenderLanes(), + null !== current && + (null !== current.memoizedState) !== + (null !== workInProgress.memoizedState) && + "unstable-defer-without-hiding" !== newProps.mode && + (workInProgress.flags |= 4), + null + ); } throw Error( "Unknown unit of work tag (" + @@ -4926,31 +5260,30 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + resetWorkInProgressVersions(); + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null ); case 19: @@ -4959,16 +5292,25 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: + case 23: + return popRenderLanes(), null; default: return null; } } function createCapturedValue(value, source) { - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source) - }; + try { + var info = "", + node = source; + do (info += describeFiber(node)), (node = node.return); + while (node); + var JSCompiler_inline_result = info; + } catch (x) { + JSCompiler_inline_result = + "\nError generating stack: " + x.message + "\n" + x.stack; + } + return { value: value, source: source, stack: JSCompiler_inline_result }; } if ( "function" !== @@ -4977,51 +5319,61 @@ if ( throw Error( "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); -function logCapturedError(capturedError) { - !1 !== - ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ) && console.error(capturedError.error); -} -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source, - stack = errorInfo.stack; - null === stack && - null !== source && - (stack = getStackByFiberInDevAndProd(source)); - errorInfo = { - componentName: null !== source ? getComponentName(source.type) : null, - componentStack: null !== stack ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: !1, - willRetry: !1 - }; - null !== boundary && - 1 === boundary.tag && - ((errorInfo.errorBoundary = boundary.stateNode), - (errorInfo.errorBoundaryName = getComponentName(boundary.type)), - (errorInfo.errorBoundaryFound = !0), - (errorInfo.willRetry = !0)); +function logCapturedError(boundary, errorInfo) { try { - logCapturedError(errorInfo); + !1 !== + ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog({ + componentStack: null !== errorInfo.stack ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + null !== boundary && 1 === boundary.tag ? boundary.stateNode : null + }) && console.error(errorInfo.value); } catch (e) { setTimeout(function() { throw e; }); } } -function safelyCallComponentWillUnmount(current, instance) { - try { - (instance.props = current.memoizedProps), - (instance.state = current.memoizedState), - instance.componentWillUnmount(); - } catch (unmountError) { - captureCommitPhaseError(current, unmountError); +var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; +function createRootErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + lane.payload = { element: null }; + var error = errorInfo.value; + lane.callback = function() { + hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); + logCapturedError(fiber, errorInfo); + }; + return lane; +} +function createClassErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if ("function" === typeof getDerivedStateFromError) { + var error = errorInfo.value; + lane.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error); + }; } + var inst = fiber.stateNode; + null !== inst && + "function" === typeof inst.componentDidCatch && + (lane.callback = function() { + "function" !== typeof getDerivedStateFromError && + (null === legacyErrorBoundariesThatAlreadyFailed + ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) + : legacyErrorBoundariesThatAlreadyFailed.add(this), + logCapturedError(fiber, errorInfo)); + var stack = errorInfo.stack; + this.componentDidCatch(errorInfo.value, { + componentStack: null !== stack ? stack : "" + }); + }); + return lane; } +var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; function safelyDetachRef(current) { var ref = current.ref; if (null !== ref) @@ -5038,10 +5390,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5055,6 +5406,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } return; case 3: + return; case 5: case 6: case 4: @@ -5065,58 +5417,56 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitHookEffectListUnmount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var destroy = effect.destroy; - effect.destroy = void 0; - void 0 !== destroy && destroy(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} -function commitHookEffectListMount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var create = effect.create; - effect.destroy = create(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} function commitLifeCycles(finishedRoot, current, finishedWork) { switch (finishedWork.tag) { case 0: case 11: case 15: - case 22: - commitHookEffectListMount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + if (3 === (finishedRoot.tag & 3)) { + var create$81 = finishedRoot.create; + finishedRoot.destroy = create$81(); + } + finishedRoot = finishedRoot.next; + } while (finishedRoot !== current); + } + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + var _effect = finishedRoot; + create$81 = _effect.next; + _effect = _effect.tag; + 0 !== (_effect & 4) && + 0 !== (_effect & 1) && + (enqueuePendingPassiveHookEffectUnmount(finishedWork, finishedRoot), + enqueuePendingPassiveHookEffectMount(finishedWork, finishedRoot)); + finishedRoot = create$81; + } while (finishedRoot !== current); + } return; case 1: finishedRoot = finishedWork.stateNode; - if (finishedWork.effectTag & 4) - if (null === current) finishedRoot.componentDidMount(); - else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - finishedRoot.componentDidUpdate( - prevProps, - current.memoizedState, - finishedRoot.__reactInternalSnapshotBeforeUpdate - ); - } + finishedWork.flags & 4 && + (null === current + ? finishedRoot.componentDidMount() + : ((create$81 = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps( + finishedWork.type, + current.memoizedProps + )), + finishedRoot.componentDidUpdate( + create$81, + current.memoizedState, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ))); current = finishedWork.updateQueue; null !== current && commitUpdateQueue(finishedWork, current, finishedRoot); @@ -5137,10 +5487,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { } return; case 5: - if (null === current && finishedWork.effectTag & 4) - throw Error( - "The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue." - ); + null === current && finishedWork.flags & 4 && shim(); return; case 6: return; @@ -5154,74 +5501,25 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: + case 23: return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitUnmount(finishedRoot, current$jscomp$0, renderPriorityLevel) { - "function" === typeof onCommitFiberUnmount && - onCommitFiberUnmount(current$jscomp$0); - switch (current$jscomp$0.tag) { - case 0: - case 11: - case 14: - case 15: - case 22: - finishedRoot = current$jscomp$0.updateQueue; - if ( - null !== finishedRoot && - ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) - ) { - var firstEffect = finishedRoot.next; - runWithPriority( - 97 < renderPriorityLevel ? 97 : renderPriorityLevel, - function() { - var effect = firstEffect; - do { - var _destroy = effect.destroy; - if (void 0 !== _destroy) { - var current = current$jscomp$0; - try { - _destroy(); - } catch (error) { - captureCommitPhaseError(current, error); - } - } - effect = effect.next; - } while (effect !== firstEffect); - } - ); - } - break; - case 1: - safelyDetachRef(current$jscomp$0); - renderPriorityLevel = current$jscomp$0.stateNode; - "function" === typeof renderPriorityLevel.componentWillUnmount && - safelyCallComponentWillUnmount(current$jscomp$0, renderPriorityLevel); - break; - case 5: - safelyDetachRef(current$jscomp$0); - break; - case 4: - createChildNodeSet(current$jscomp$0.stateNode.containerInfo); - } -} -function detachFiber(current) { - var alternate = current.alternate; - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - null !== alternate && detachFiber(alternate); +function detachFiberMutation(fiber) { + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; } function commitWork(current, finishedWork) { switch (finishedWork.tag) { @@ -5229,8 +5527,19 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: - commitHookEffectListUnmount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedWork = current = current.next; + do { + if (3 === (finishedWork.tag & 3)) { + var destroy = finishedWork.destroy; + finishedWork.destroy = void 0; + void 0 !== destroy && destroy(); + } + finishedWork = finishedWork.next; + } while (finishedWork !== current); + } return; case 12: return; @@ -5242,6 +5551,9 @@ function commitWork(current, finishedWork) { case 19: attachSuspenseRetryListeners(finishedWork); return; + case 22: + case 23: + return; } a: { switch (finishedWork.tag) { @@ -5260,84 +5572,45 @@ function commitWork(current, finishedWork) { } } function attachSuspenseRetryListeners(finishedWork) { - var thenables = finishedWork.updateQueue; - if (null !== thenables) { + var wakeables = finishedWork.updateQueue; + if (null !== wakeables) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - thenables.forEach(function(thenable) { - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); - retryCache.has(thenable) || - (retryCache.add(thenable), thenable.then(retry, retry)); + wakeables.forEach(function(wakeable) { + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + retryCache.has(wakeable) || + (retryCache.add(wakeable), wakeable.then(retry, retry)); }); } } -var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - expirationTime.payload = { element: null }; - var error = errorInfo.value; - expirationTime.callback = function() { - hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); - logError(fiber, errorInfo); - }; - return expirationTime; -} -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - if ("function" === typeof getDerivedStateFromError) { - var error = errorInfo.value; - expirationTime.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error); - }; - } - var inst = fiber.stateNode; - null !== inst && - "function" === typeof inst.componentDidCatch && - (expirationTime.callback = function() { - "function" !== typeof getDerivedStateFromError && - (null === legacyErrorBoundariesThatAlreadyFailed - ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) - : legacyErrorBoundariesThatAlreadyFailed.add(this), - logError(fiber, errorInfo)); - var stack = errorInfo.stack; - this.componentDidCatch(errorInfo.value, { - componentStack: null !== stack ? stack : "" - }); - }); - return expirationTime; +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + return null !== current && + ((current = current.memoizedState), + null === current || null !== current.dehydrated) + ? ((finishedWork = finishedWork.memoizedState), + null !== finishedWork && null === finishedWork.dehydrated) + : !1; } var ceil = Math.ceil, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - NoContext = 0, - LegacyUnbatchedContext = 8, - RenderContext = 16, - CommitContext = 32, - RootIncomplete = 0, - RootFatalErrored = 1, - RootErrored = 2, - RootSuspended = 3, - RootSuspendedWithDelay = 4, - RootCompleted = 5, - executionContext = NoContext, + executionContext = 0, workInProgressRoot = null, workInProgress = null, - renderExpirationTime$1 = 0, - workInProgressRootExitStatus = RootIncomplete, + workInProgressRootRenderLanes = 0, + subtreeRenderLanes = 0, + subtreeRenderLanesCursor = createCursor(0), + workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestProcessedExpirationTime = 1073741823, - workInProgressRootLatestSuspenseTimeout = 1073741823, - workInProgressRootCanSuspendUsingConfig = null, - workInProgressRootNextUnprocessedUpdateTime = 0, - workInProgressRootHasPendingPing = !1, + workInProgressRootIncludedLanes = 0, + workInProgressRootSkippedLanes = 0, + workInProgressRootUpdatedLanes = 0, + workInProgressRootPingedLanes = 0, + mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, - FALLBACK_THROTTLE_MS = 500, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5345,205 +5618,186 @@ var ceil = Math.ceil, rootDoesHavePassiveEffects = !1, rootWithPendingPassiveEffects = null, pendingPassiveEffectsRenderPriority = 90, + pendingPassiveHookEffectsMount = [], + pendingPassiveHookEffectsUnmount = [], rootsWithPendingDiscreteUpdates = null, nestedUpdateCount = 0, rootWithNestedUpdates = null, - currentEventTime = 0; -function requestCurrentTimeForUpdate() { - return (executionContext & (RenderContext | CommitContext)) !== NoContext - ? 1073741821 - ((now() / 10) | 0) - : 0 !== currentEventTime + currentEventTime = -1, + currentEventWipLanes = 0, + currentEventPendingLanes = 0, + focusedInstanceHandle = null, + shouldFireAfterActiveInstanceBlur = !1; +function requestEventTime() { + return 0 !== (executionContext & 48) + ? now() + : -1 !== currentEventTime ? currentEventTime - : (currentEventTime = 1073741821 - ((now() / 10) | 0)); + : (currentEventTime = now()); } -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; - if (0 === (fiber & 2)) return 1073741823; - var priorityLevel = getCurrentPriorityLevel(); - if (0 === (fiber & 4)) return 99 === priorityLevel ? 1073741823 : 1073741822; - if ((executionContext & RenderContext) !== NoContext) - return renderExpirationTime$1; - if (null !== suspenseConfig) - currentTime = - 1073741821 - - 25 * - ((((1073741821 - - currentTime + - (suspenseConfig.timeoutMs | 0 || 5e3) / 10) / - 25) | - 0) + - 1); - else - switch (priorityLevel) { - case 99: - currentTime = 1073741823; - break; - case 98: - currentTime = - 1073741821 - 10 * ((((1073741821 - currentTime + 15) / 10) | 0) + 1); - break; - case 97: - case 96: - currentTime = - 1073741821 - 25 * ((((1073741821 - currentTime + 500) / 25) | 0) + 1); - break; - case 95: - currentTime = 2; - break; - default: - throw Error("Expected a valid priority level"); - } - null !== workInProgressRoot && - currentTime === renderExpirationTime$1 && - --currentTime; - return currentTime; -} -function scheduleWork(fiber, expirationTime) { + if (0 === (fiber & 2)) return 1; + if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; + 0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes); + if (0 !== ReactCurrentBatchConfig.transition) { + 0 !== currentEventPendingLanes && + (currentEventPendingLanes = + null !== mostRecentlyUpdatedRoot + ? mostRecentlyUpdatedRoot.pendingLanes + : 0); + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; + } + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; +} +function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), (rootWithNestedUpdates = null), Error( "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." )); - fiber = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - if (null !== fiber) { - var priorityLevel = getCurrentPriorityLevel(); - 1073741823 === expirationTime - ? (executionContext & LegacyUnbatchedContext) !== NoContext && - (executionContext & (RenderContext | CommitContext)) === NoContext - ? performSyncWorkOnRoot(fiber) - : (ensureRootIsScheduled(fiber), - executionContext === NoContext && flushSyncCallbackQueue()) - : ensureRootIsScheduled(fiber); - (executionContext & 4) === NoContext || - (98 !== priorityLevel && 99 !== priorityLevel) || - (null === rootsWithPendingDiscreteUpdates - ? (rootsWithPendingDiscreteUpdates = new Map([[fiber, expirationTime]])) - : ((priorityLevel = rootsWithPendingDiscreteUpdates.get(fiber)), - (void 0 === priorityLevel || priorityLevel > expirationTime) && - rootsWithPendingDiscreteUpdates.set(fiber, expirationTime))); - } -} -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - fiber.expirationTime < expirationTime && - (fiber.expirationTime = expirationTime); - var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < expirationTime && - (alternate.expirationTime = expirationTime); - var node = fiber.return, - root = null; - if (null === node && 3 === fiber.tag) root = fiber.stateNode; - else - for (; null !== node; ) { - alternate = node.alternate; - node.childExpirationTime < expirationTime && - (node.childExpirationTime = expirationTime); - null !== alternate && - alternate.childExpirationTime < expirationTime && - (alternate.childExpirationTime = expirationTime); - if (null === node.return && 3 === node.tag) { - root = node.stateNode; - break; + fiber = markUpdateLaneFromFiberToRoot(fiber, lane); + if (null === fiber) return null; + markRootUpdated(fiber, lane, eventTime); + fiber === workInProgressRoot && + ((workInProgressRootUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(fiber, workInProgressRootRenderLanes)); + var priorityLevel = getCurrentPriorityLevel(); + 1 === lane + ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) + ? performSyncWorkOnRoot(fiber) + : (ensureRootIsScheduled(fiber, eventTime), + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) + : (0 === (executionContext & 4) || + (98 !== priorityLevel && 99 !== priorityLevel) || + (null === rootsWithPendingDiscreteUpdates + ? (rootsWithPendingDiscreteUpdates = new Set([fiber])) + : rootsWithPendingDiscreteUpdates.add(fiber)), + ensureRootIsScheduled(fiber, eventTime)); + mostRecentlyUpdatedRoot = fiber; +} +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + sourceFiber.lanes |= lane; + var alternate = sourceFiber.alternate; + null !== alternate && (alternate.lanes |= lane); + alternate = sourceFiber; + for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + (sourceFiber.childLanes |= lane), + (alternate = sourceFiber.alternate), + null !== alternate && (alternate.childLanes |= lane), + (alternate = sourceFiber), + (sourceFiber = sourceFiber.return); + return 3 === alternate.tag ? alternate.stateNode : null; +} +function ensureRootIsScheduled(root, currentTime) { + for ( + var existingCallbackNode = root.callbackNode, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; + 0 < lanes; + + ) { + var index$5 = 31 - clz32(lanes), + lane = 1 << index$5, + expirationTime = expirationTimes[index$5]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) { + expirationTime = currentTime; + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; + expirationTimes[index$5] = + 10 <= priority + ? expirationTime + 250 + : 6 <= priority + ? expirationTime + 5e3 + : -1; } - node = node.return; - } - null !== root && - (workInProgressRoot === root && - (markUnprocessedUpdateTime(expirationTime), - workInProgressRootExitStatus === RootSuspendedWithDelay && - markRootSuspendedAtTime(root, renderExpirationTime$1)), - markRootUpdatedAtTime(root, expirationTime)); - return root; -} -function getNextRootExpirationTimeToWorkOn(root) { - var lastExpiredTime = root.lastExpiredTime; - if (0 !== lastExpiredTime) return lastExpiredTime; - lastExpiredTime = root.firstPendingTime; - if (!isRootSuspendedAtTime(root, lastExpiredTime)) return lastExpiredTime; - var lastPingedTime = root.lastPingedTime; - root = root.nextKnownPendingLevel; - root = lastPingedTime > root ? lastPingedTime : root; - return 2 >= root && lastExpiredTime !== root ? 0 : root; -} -function ensureRootIsScheduled(root) { - if (0 !== root.lastExpiredTime) - (root.callbackExpirationTime = 1073741823), - (root.callbackPriority = 99), - (root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - )); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + suspendedLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + currentTime = return_highestLanePriority; + if (0 === suspendedLanes) + null !== existingCallbackNode && + (existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode), + (root.callbackNode = null), + (root.callbackPriority = 0)); else { - var expirationTime = getNextRootExpirationTimeToWorkOn(root), - existingCallbackNode = root.callbackNode; - if (0 === expirationTime) - null !== existingCallbackNode && - ((root.callbackNode = null), - (root.callbackExpirationTime = 0), - (root.callbackPriority = 90)); - else { - var priorityLevel = requestCurrentTimeForUpdate(); - 1073741823 === expirationTime - ? (priorityLevel = 99) - : 1 === expirationTime || 2 === expirationTime - ? (priorityLevel = 95) - : ((priorityLevel = - 10 * (1073741821 - expirationTime) - - 10 * (1073741821 - priorityLevel)), - (priorityLevel = - 0 >= priorityLevel - ? 99 - : 250 >= priorityLevel - ? 98 - : 5250 >= priorityLevel - ? 97 - : 95)); - if (null !== existingCallbackNode) { - var existingCallbackPriority = root.callbackPriority; - if ( - root.callbackExpirationTime === expirationTime && - existingCallbackPriority >= priorityLevel - ) - return; - existingCallbackNode !== fakeCallbackNode && - Scheduler_cancelCallback(existingCallbackNode); - } - root.callbackExpirationTime = expirationTime; - root.callbackPriority = priorityLevel; - expirationTime = - 1073741823 === expirationTime - ? scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)) - : scheduleCallback( - priorityLevel, - performConcurrentWorkOnRoot.bind(null, root), - { timeout: 10 * (1073741821 - expirationTime) - now() } - ); - root.callbackNode = expirationTime; + if (null !== existingCallbackNode) { + if (root.callbackPriority === currentTime) return; + existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode); } + 15 === currentTime + ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), + null === syncQueue + ? ((syncQueue = [existingCallbackNode]), + (immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ))) + : syncQueue.push(existingCallbackNode), + (existingCallbackNode = fakeCallbackNode)) + : 14 === currentTime + ? (existingCallbackNode = scheduleCallback( + 99, + performSyncWorkOnRoot.bind(null, root) + )) + : ((existingCallbackNode = lanePriorityToSchedulerPriority(currentTime)), + (existingCallbackNode = scheduleCallback( + existingCallbackNode, + performConcurrentWorkOnRoot.bind(null, root) + ))); + root.callbackPriority = currentTime; + root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = 0; - if (didTimeout) { - didTimeout = requestCurrentTimeForUpdate(); - var lastExpiredTime = root.lastExpiredTime; - if (0 === lastExpiredTime || lastExpiredTime > didTimeout) - root.lastExpiredTime = didTimeout; - ensureRootIsScheduled(root); - return null; - } - lastExpiredTime = getNextRootExpirationTimeToWorkOn(root); - if (0 === lastExpiredTime) return null; - didTimeout = root.callbackNode; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) +function performConcurrentWorkOnRoot(root) { + currentEventTime = -1; + currentEventPendingLanes = currentEventWipLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - flushPassiveEffects(); - var expirationTime = lastExpiredTime; - var exitStatus = executionContext; - executionContext |= RenderContext; + var originalCallbackNode = root.callbackNode; + if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) + return null; + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + if (0 === lanes) return null; + var exitStatus = lanes; + var prevExecutionContext = executionContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - (root === workInProgressRoot && expirationTime === renderExpirationTime$1) || - prepareFreshStack(root, expirationTime); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== exitStatus + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, exitStatus); do try { workLoopConcurrent(); @@ -5553,199 +5807,163 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } while (1); resetContextDependencies(); - ReactCurrentDispatcher$1.current = prevDispatcher; - executionContext = exitStatus; + ReactCurrentDispatcher$2.current = prevDispatcher; + executionContext = prevExecutionContext; null !== workInProgress - ? (exitStatus = RootIncomplete) + ? (exitStatus = 0) : ((workInProgressRoot = null), + (workInProgressRootRenderLanes = 0), (exitStatus = workInProgressRootExitStatus)); - if (exitStatus !== RootIncomplete) { - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) - throw ((didTimeout = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), - didTimeout); - expirationTime = root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) + prepareFreshStack(root, 0); + else if (0 !== exitStatus) { + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) + throw ((originalCallbackNode = workInProgressRootFatalError), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); + root.finishedWork = root.current.alternate; + root.finishedLanes = lanes; switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: + case 0: + case 1: throw Error("Root did not complete. This is a bug in React."); - case RootErrored: + case 2: commitRoot(root); break; - case RootSuspended: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - expirationTime - )); + case 3: + markRootSuspended$1(root, lanes); if ( - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - ((expirationTime = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now()), - 10 < expirationTime) + (lanes & 62914560) === lanes && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { - if ( - workInProgressRootHasPendingPing && - ((prevDispatcher = root.lastPingedTime), - 0 === prevDispatcher || prevDispatcher >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - prevDispatcher = getNextRootExpirationTimeToWorkOn(root); - if (0 !== prevDispatcher && prevDispatcher !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; + if (0 !== getNextLanes(root, 0)) break; + prevExecutionContext = root.suspendedLanes; + if ((prevExecutionContext & lanes) !== lanes) { + requestEventTime(); + root.pingedLanes |= root.suspendedLanes & prevExecutionContext; break; } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - expirationTime + exitStatus ); break; } commitRoot(root); break; - case RootSuspendedWithDelay: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - expirationTime - )); - if ( - workInProgressRootHasPendingPing && - ((expirationTime = root.lastPingedTime), - 0 === expirationTime || expirationTime >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - expirationTime = getNextRootExpirationTimeToWorkOn(root); - if (0 !== expirationTime && expirationTime !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; - break; + case 4: + markRootSuspended$1(root, lanes); + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevExecutionContext = -1; 0 < lanes; ) { + var index$4 = 31 - clz32(lanes); + prevDispatcher = 1 << index$4; + index$4 = exitStatus[index$4]; + index$4 > prevExecutionContext && (prevExecutionContext = index$4); + lanes &= ~prevDispatcher; } - 1073741823 !== workInProgressRootLatestSuspenseTimeout - ? (expirationTime = - 10 * (1073741821 - workInProgressRootLatestSuspenseTimeout) - - now()) - : 1073741823 === workInProgressRootLatestProcessedExpirationTime - ? (expirationTime = 0) - : ((expirationTime = - 10 * - (1073741821 - workInProgressRootLatestProcessedExpirationTime) - - 5e3), - (exitStatus = now()), - (lastExpiredTime = - 10 * (1073741821 - lastExpiredTime) - exitStatus), - (expirationTime = exitStatus - expirationTime), - 0 > expirationTime && (expirationTime = 0), - (expirationTime = - (120 > expirationTime - ? 120 - : 480 > expirationTime - ? 480 - : 1080 > expirationTime - ? 1080 - : 1920 > expirationTime - ? 1920 - : 3e3 > expirationTime - ? 3e3 - : 4320 > expirationTime - ? 4320 - : 1960 * ceil(expirationTime / 1960)) - expirationTime), - lastExpiredTime < expirationTime && - (expirationTime = lastExpiredTime)); - if (10 < expirationTime) { + lanes = prevExecutionContext; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; + if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - expirationTime + lanes ); break; } commitRoot(root); break; - case RootCompleted: - if ( - 1073741823 !== workInProgressRootLatestProcessedExpirationTime && - null !== workInProgressRootCanSuspendUsingConfig - ) { - prevDispatcher = workInProgressRootLatestProcessedExpirationTime; - var suspenseConfig = workInProgressRootCanSuspendUsingConfig; - expirationTime = suspenseConfig.busyMinDurationMs | 0; - 0 >= expirationTime - ? (expirationTime = 0) - : ((exitStatus = suspenseConfig.busyDelayMs | 0), - (prevDispatcher = - now() - - (10 * (1073741821 - prevDispatcher) - - (suspenseConfig.timeoutMs | 0 || 5e3))), - (expirationTime = - prevDispatcher <= exitStatus - ? 0 - : exitStatus + expirationTime - prevDispatcher)); - if (10 < expirationTime) { - markRootSuspendedAtTime(root, lastExpiredTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - expirationTime - ); - break; - } - } + case 5: commitRoot(root); break; default: throw Error("Unknown root exit status."); } } - ensureRootIsScheduled(root); - return root.callbackNode === didTimeout + ensureRootIsScheduled(root, now()); + return root.callbackNode === originalCallbackNode ? performConcurrentWorkOnRoot.bind(null, root) : null; } +function markRootSuspended$1(root, suspendedLanes) { + suspendedLanes &= ~workInProgressRootPingedLanes; + suspendedLanes &= ~workInProgressRootUpdatedLanes; + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; + for (root = root.expirationTimes; 0 < suspendedLanes; ) { + var index$9 = 31 - clz32(suspendedLanes), + lane = 1 << index$9; + root[index$9] = -1; + suspendedLanes &= ~lane; + } +} function performSyncWorkOnRoot(root) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - lastExpiredTime = - 0 !== lastExpiredTime - ? root === workInProgressRoot && renderExpirationTime$1 >= lastExpiredTime - ? renderExpirationTime$1 - : lastExpiredTime - : 1073741823; - var exitStatus = renderRootSync(root, lastExpiredTime); + if ( + root === workInProgressRoot && + 0 !== (root.expiredLanes & workInProgressRootRenderLanes) + ) { + var lanes = workInProgressRootRenderLanes; + var exitStatus = renderRootSync(root, lanes); + 0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes) && + ((lanes = getNextLanes(root, lanes)), + (exitStatus = renderRootSync(root, lanes))); + } else + (lanes = getNextLanes(root, 0)), (exitStatus = renderRootSync(root, lanes)); 0 !== root.tag && - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), exitStatus); root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + root.finishedLanes = lanes; commitRoot(root); - ensureRootIsScheduled(root); + ensureRootIsScheduled(root, now()); return null; } -function prepareFreshStack(root, expirationTime) { +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes); + subtreeRenderLanes |= lanes; + workInProgressRootIncludedLanes |= lanes; +} +function popRenderLanes() { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor); +} +function prepareFreshStack(root, lanes) { root.finishedWork = null; - root.finishedExpirationTime = 0; + root.finishedLanes = 0; var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); @@ -5763,6 +5981,7 @@ function prepareFreshStack(root, expirationTime) { popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); + resetWorkInProgressVersions(); break; case 5: popHostContext(interruptedWork); @@ -5778,25 +5997,27 @@ function prepareFreshStack(root, expirationTime) { break; case 10: popProvider(interruptedWork); + break; + case 22: + case 23: + popRenderLanes(); } timeoutHandle = timeoutHandle.return; } workInProgressRoot = root; workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = workInProgressRootLatestProcessedExpirationTime = 1073741823; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = 0; - workInProgressRootHasPendingPing = !1; + workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; } function handleError(root$jscomp$0, thrownValue) { do { + var erroredWork = workInProgress; try { resetContextDependencies(); - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - if (didScheduleRenderPhaseUpdate) + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (didScheduleRenderPhaseUpdate) { for ( var hook = currentlyRenderingFiber$1.memoizedState; null !== hook; @@ -5806,49 +6027,52 @@ function handleError(root$jscomp$0, thrownValue) { null !== queue && (queue.pending = null); hook = hook.next; } - renderExpirationTime = 0; + didScheduleRenderPhaseUpdate = !1; + } + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; - didScheduleRenderPhaseUpdate = !1; - if (null === workInProgress || null === workInProgress.return) - return ( - (workInProgressRootExitStatus = RootFatalErrored), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null) - ); + didScheduleRenderPhaseUpdateDuringThisPass = !1; + ReactCurrentOwner$2.current = null; + if (null === erroredWork || null === erroredWork.return) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + break; + } a: { var root = root$jscomp$0, - returnFiber = workInProgress.return, - sourceFiber = workInProgress, + returnFiber = erroredWork.return, + sourceFiber = erroredWork, value = thrownValue; - thrownValue = renderExpirationTime$1; - sourceFiber.effectTag |= 2048; + thrownValue = workInProgressRootRenderLanes; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && "object" === typeof value && "function" === typeof value.then ) { - var thenable = value; + var wakeable = value; if (0 === (sourceFiber.mode & 2)) { var currentSource = sourceFiber.alternate; currentSource ? ((sourceFiber.updateQueue = currentSource.updateQueue), (sourceFiber.memoizedState = currentSource.memoizedState), - (sourceFiber.expirationTime = currentSource.expirationTime)) + (sourceFiber.lanes = currentSource.lanes)) : ((sourceFiber.updateQueue = null), (sourceFiber.memoizedState = null)); } var hasInvisibleParentBoundary = 0 !== (suspenseStackCursor.current & 1), - _workInProgress = returnFiber; + workInProgress$76 = returnFiber; do { var JSCompiler_temp; - if ((JSCompiler_temp = 13 === _workInProgress.tag)) { - var nextState = _workInProgress.memoizedState; + if ((JSCompiler_temp = 13 === workInProgress$76.tag)) { + var nextState = workInProgress$76.memoizedState; if (null !== nextState) JSCompiler_temp = null !== nextState.dehydrated ? !0 : !1; else { - var props = _workInProgress.memoizedProps; + var props = workInProgress$76.memoizedProps; JSCompiler_temp = void 0 === props.fallback ? !1 @@ -5860,23 +6084,24 @@ function handleError(root$jscomp$0, thrownValue) { } } if (JSCompiler_temp) { - var thenables = _workInProgress.updateQueue; - if (null === thenables) { + var wakeables = workInProgress$76.updateQueue; + if (null === wakeables) { var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else thenables.add(thenable); - if (0 === (_workInProgress.mode & 2)) { - _workInProgress.effectTag |= 64; - sourceFiber.effectTag &= -2981; + updateQueue.add(wakeable); + workInProgress$76.updateQueue = updateQueue; + } else wakeables.add(wakeable); + if (0 === (workInProgress$76.mode & 2)) { + workInProgress$76.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(1073741823, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } - sourceFiber.expirationTime = 1073741823; + sourceFiber.lanes |= 1; break a; } value = void 0; @@ -5885,108 +6110,98 @@ function handleError(root$jscomp$0, thrownValue) { null === pingCache ? ((pingCache = root.pingCache = new PossiblyWeakMap()), (value = new Set()), - pingCache.set(thenable, value)) - : ((value = pingCache.get(thenable)), + pingCache.set(wakeable, value)) + : ((value = pingCache.get(wakeable)), void 0 === value && - ((value = new Set()), pingCache.set(thenable, value))); + ((value = new Set()), pingCache.set(wakeable, value))); if (!value.has(sourceFiber)) { value.add(sourceFiber); var ping = pingSuspendedRoot.bind( null, root, - thenable, + wakeable, sourceFiber ); - thenable.then(ping, ping); + wakeable.then(ping, ping); } - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; + workInProgress$76.flags |= 8192; + workInProgress$76.lanes = thrownValue; break a; } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$76 = workInProgress$76.return; + } while (null !== workInProgress$76); value = Error( (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) + " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." ); } - workInProgressRootExitStatus !== RootCompleted && - (workInProgressRootExitStatus = RootErrored); + 5 !== workInProgressRootExitStatus && + (workInProgressRootExitStatus = 2); value = createCapturedValue(value, sourceFiber); - _workInProgress = returnFiber; + workInProgress$76 = returnFiber; do { - switch (_workInProgress.tag) { + switch (workInProgress$76.tag) { case 3: - thenable = value; - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update = createRootErrorUpdate( - _workInProgress, - thenable, + root = value; + workInProgress$76.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$76.lanes |= thrownValue; + var update$77 = createRootErrorUpdate( + workInProgress$76, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update); + enqueueCapturedUpdate(workInProgress$76, update$77); break a; case 1: - thenable = value; - var ctor = _workInProgress.type, - instance = _workInProgress.stateNode; + root = value; + var ctor = workInProgress$76.type, + instance = workInProgress$76.stateNode; if ( - 0 === (_workInProgress.effectTag & 64) && + 0 === (workInProgress$76.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update2 = createClassErrorUpdate( - _workInProgress, - thenable, + workInProgress$76.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$76.lanes |= thrownValue; + var update$80 = createClassErrorUpdate( + workInProgress$76, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update2); + enqueueCapturedUpdate(workInProgress$76, update$80); break a; } } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$76 = workInProgress$76.return; + } while (null !== workInProgress$76); } - workInProgress = completeUnitOfWork(workInProgress); + completeUnitOfWork(erroredWork); } catch (yetAnotherThrownValue) { thrownValue = yetAnotherThrownValue; + workInProgress === erroredWork && + null !== erroredWork && + (workInProgress = erroredWork = erroredWork.return); continue; } break; } while (1); } function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - expirationTime < workInProgressRootLatestProcessedExpirationTime && - 2 < expirationTime && - (workInProgressRootLatestProcessedExpirationTime = expirationTime); - null !== suspenseConfig && - expirationTime < workInProgressRootLatestSuspenseTimeout && - 2 < expirationTime && - ((workInProgressRootLatestSuspenseTimeout = expirationTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig)); -} -function markUnprocessedUpdateTime(expirationTime) { - expirationTime > workInProgressRootNextUnprocessedUpdateTime && - (workInProgressRootNextUnprocessedUpdateTime = expirationTime); -} -function renderRootSync(root, expirationTime) { +function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; - executionContext |= RenderContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - (root === workInProgressRoot && expirationTime === renderExpirationTime$1) || - prepareFreshStack(root, expirationTime); + (workInProgressRoot === root && workInProgressRootRenderLanes === lanes) || + prepareFreshStack(root, lanes); do try { workLoopSync(); @@ -5997,142 +6212,144 @@ function renderRootSync(root, expirationTime) { while (1); resetContextDependencies(); executionContext = prevExecutionContext; - ReactCurrentDispatcher$1.current = prevDispatcher; + ReactCurrentDispatcher$2.current = prevDispatcher; if (null !== workInProgress) throw Error( "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." ); workInProgressRoot = null; + workInProgressRootRenderLanes = 0; return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress; ) performUnitOfWork(workInProgress); } function workLoopConcurrent() { - for (; null !== workInProgress && !shouldYield(); ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress && !Scheduler_shouldYield(); ) + performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { - var next = beginWork$1( - unitOfWork.alternate, - unitOfWork, - renderExpirationTime$1 - ); + var next = beginWork$1(unitOfWork.alternate, unitOfWork, subtreeRenderLanes); unitOfWork.memoizedProps = unitOfWork.pendingProps; - null === next && (next = completeUnitOfWork(unitOfWork)); + null === next ? completeUnitOfWork(unitOfWork) : (workInProgress = next); ReactCurrentOwner$2.current = null; - return next; } function completeUnitOfWork(unitOfWork) { - workInProgress = unitOfWork; + var completedWork = unitOfWork; do { - var current = workInProgress.alternate; - unitOfWork = workInProgress.return; - if (0 === (workInProgress.effectTag & 2048)) { - current = completeWork(current, workInProgress, renderExpirationTime$1); + var current = completedWork.alternate; + unitOfWork = completedWork.return; + if (0 === (completedWork.flags & 4096)) { + current = completeWork(current, completedWork, subtreeRenderLanes); + if (null !== current) { + workInProgress = current; + return; + } + current = completedWork; if ( - 1 === renderExpirationTime$1 || - 1 !== workInProgress.childExpirationTime + (23 !== current.tag && 22 !== current.tag) || + null === current.memoizedState || + 0 !== (subtreeRenderLanes & 1073741824) || + 0 === (current.mode & 4) ) { - for ( - var newChildExpirationTime = 0, _child = workInProgress.child; - null !== _child; - - ) { - var _childUpdateExpirationTime = _child.expirationTime, - _childChildExpirationTime = _child.childExpirationTime; - _childUpdateExpirationTime > newChildExpirationTime && - (newChildExpirationTime = _childUpdateExpirationTime); - _childChildExpirationTime > newChildExpirationTime && - (newChildExpirationTime = _childChildExpirationTime); - _child = _child.sibling; - } - workInProgress.childExpirationTime = newChildExpirationTime; + for (var newChildLanes = 0, child = current.child; null !== child; ) + (newChildLanes |= child.lanes | child.childLanes), + (child = child.sibling); + current.childLanes = newChildLanes; } - if (null !== current) return current; null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && - (unitOfWork.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && + (unitOfWork.firstEffect = completedWork.firstEffect), + null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && - (unitOfWork.lastEffect.nextEffect = workInProgress.firstEffect), - (unitOfWork.lastEffect = workInProgress.lastEffect)), - 1 < workInProgress.effectTag && + (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), + (unitOfWork.lastEffect = completedWork.lastEffect)), + 1 < completedWork.flags && (null !== unitOfWork.lastEffect - ? (unitOfWork.lastEffect.nextEffect = workInProgress) - : (unitOfWork.firstEffect = workInProgress), - (unitOfWork.lastEffect = workInProgress))); + ? (unitOfWork.lastEffect.nextEffect = completedWork) + : (unitOfWork.firstEffect = completedWork), + (unitOfWork.lastEffect = completedWork))); } else { - current = unwindWork(workInProgress); - if (null !== current) return (current.effectTag &= 2047), current; + current = unwindWork(completedWork); + if (null !== current) { + current.flags &= 4095; + workInProgress = current; + return; + } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } - current = workInProgress.sibling; - if (null !== current) return current; - workInProgress = unitOfWork; - } while (null !== workInProgress); - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootCompleted); - return null; -} -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - fiber = fiber.childExpirationTime; - return updateExpirationTime > fiber ? updateExpirationTime : fiber; + completedWork = completedWork.sibling; + if (null !== completedWork) { + workInProgress = completedWork; + return; + } + workInProgress = completedWork = unitOfWork; + } while (null !== completedWork); + 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } function commitRoot(root) { var renderPriorityLevel = getCurrentPriorityLevel(); runWithPriority(99, commitRootImpl.bind(null, root, renderPriorityLevel)); return null; } -function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { +function commitRootImpl(root, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - var finishedWork = root$jscomp$1.finishedWork, - expirationTime = root$jscomp$1.finishedExpirationTime; + var finishedWork = root.finishedWork; if (null === finishedWork) return null; - root$jscomp$1.finishedWork = null; - root$jscomp$1.finishedExpirationTime = 0; - if (finishedWork === root$jscomp$1.current) + root.finishedWork = null; + root.finishedLanes = 0; + if (finishedWork === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - root$jscomp$1.callbackNode = null; - root$jscomp$1.callbackExpirationTime = 0; - root$jscomp$1.callbackPriority = 90; - root$jscomp$1.nextKnownPendingLevel = 0; - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - root$jscomp$1.firstPendingTime = remainingExpirationTimeBeforeCommit; - expirationTime <= root$jscomp$1.lastSuspendedTime - ? (root$jscomp$1.firstSuspendedTime = root$jscomp$1.lastSuspendedTime = root$jscomp$1.nextKnownPendingLevel = 0) - : expirationTime <= root$jscomp$1.firstSuspendedTime && - (root$jscomp$1.firstSuspendedTime = expirationTime - 1); - expirationTime <= root$jscomp$1.lastPingedTime && - (root$jscomp$1.lastPingedTime = 0); - expirationTime <= root$jscomp$1.lastExpiredTime && - (root$jscomp$1.lastExpiredTime = 0); - root$jscomp$1 === workInProgressRoot && + root.callbackNode = null; + var remainingLanes = finishedWork.lanes | finishedWork.childLanes, + remainingLanes$jscomp$0 = remainingLanes, + noLongerPendingLanes = root.pendingLanes & ~remainingLanes$jscomp$0; + root.pendingLanes = remainingLanes$jscomp$0; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes$jscomp$0; + root.mutableReadLanes &= remainingLanes$jscomp$0; + root.entangledLanes &= remainingLanes$jscomp$0; + remainingLanes$jscomp$0 = root.entanglements; + for ( + var eventTimes = root.eventTimes, expirationTimes = root.expirationTimes; + 0 < noLongerPendingLanes; + + ) { + var index$10 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$10; + remainingLanes$jscomp$0[index$10] = 0; + eventTimes[index$10] = -1; + expirationTimes[index$10] = -1; + noLongerPendingLanes &= ~lane; + } + null !== rootsWithPendingDiscreteUpdates && + 0 === (remainingLanes & 24) && + rootsWithPendingDiscreteUpdates.has(root) && + rootsWithPendingDiscreteUpdates.delete(root); + root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (renderExpirationTime$1 = 0)); - 1 < finishedWork.effectTag + (workInProgressRootRenderLanes = 0)); + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), - (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect)) - : (remainingExpirationTimeBeforeCommit = finishedWork) - : (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect); - if (null !== remainingExpirationTimeBeforeCommit) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - ReactCurrentOwner$2.current = null; - nextEffect = remainingExpirationTimeBeforeCommit; + (remainingLanes = finishedWork.firstEffect)) + : (remainingLanes = finishedWork) + : (remainingLanes = finishedWork.firstEffect); + if (null !== remainingLanes) { + remainingLanes$jscomp$0 = executionContext; + executionContext |= 32; + focusedInstanceHandle = ReactCurrentOwner$2.current = null; + shouldFireAfterActiveInstanceBlur = !1; + nextEffect = remainingLanes; do try { commitBeforeMutationEffects(); @@ -6142,17 +6359,13 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - nextEffect = remainingExpirationTimeBeforeCommit; + focusedInstanceHandle = null; + nextEffect = remainingLanes; do try { - for ( - var root = root$jscomp$1, - renderPriorityLevel = renderPriorityLevel$jscomp$1; - null !== nextEffect; - - ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + for (; null !== nextEffect; ) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6162,82 +6375,138 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: commitWork(nextEffect.alternate, nextEffect); break; case 8: - var current$jscomp$0 = nextEffect; - a: for ( - var finishedRoot = root, - root$jscomp$0 = current$jscomp$0, - renderPriorityLevel$jscomp$0 = renderPriorityLevel, - node = root$jscomp$0; - ; - - ) + eventTimes = nextEffect; + a: for (noLongerPendingLanes = expirationTimes = eventTimes; ; ) { + index$10 = noLongerPendingLanes; if ( - (commitUnmount( - finishedRoot, - node, - renderPriorityLevel$jscomp$0 - ), - null !== node.child) + injectedHook && + "function" === typeof injectedHook.onCommitFiberUnmount ) - (node.child.return = node), (node = node.child); + try { + injectedHook.onCommitFiberUnmount(rendererID, index$10); + } catch (err) {} + switch (index$10.tag) { + case 0: + case 11: + case 14: + case 15: + var updateQueue = index$10.updateQueue; + if (null !== updateQueue) { + var lastEffect = updateQueue.lastEffect; + if (null !== lastEffect) { + var firstEffect = lastEffect.next; + lane = firstEffect; + do { + var _effect2 = lane, + destroy = _effect2.destroy, + tag = _effect2.tag; + if (void 0 !== destroy) + if (0 !== (tag & 4)) + enqueuePendingPassiveHookEffectUnmount( + index$10, + lane + ); + else { + _effect2 = index$10; + try { + destroy(); + } catch (error) { + captureCommitPhaseError(_effect2, error); + } + } + lane = lane.next; + } while (lane !== firstEffect); + } + } + break; + case 1: + safelyDetachRef(index$10); + var instance = index$10.stateNode; + if ("function" === typeof instance.componentWillUnmount) + try { + (lane = index$10), + (_effect2 = instance), + (_effect2.props = lane.memoizedProps), + (_effect2.state = lane.memoizedState), + _effect2.componentWillUnmount(); + } catch (unmountError) { + captureCommitPhaseError(index$10, unmountError); + } + break; + case 5: + safelyDetachRef(index$10); + break; + case 4: + createChildNodeSet(index$10.stateNode.containerInfo); + } + if (null !== noLongerPendingLanes.child) + (noLongerPendingLanes.child.return = noLongerPendingLanes), + (noLongerPendingLanes = noLongerPendingLanes.child); else { - if (node === root$jscomp$0) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === root$jscomp$0) + if (noLongerPendingLanes === expirationTimes) break; + for (; null === noLongerPendingLanes.sibling; ) { + if ( + null === noLongerPendingLanes.return || + noLongerPendingLanes.return === expirationTimes + ) break a; - node = node.return; + noLongerPendingLanes = noLongerPendingLanes.return; } - node.sibling.return = node.return; - node = node.sibling; + noLongerPendingLanes.sibling.return = + noLongerPendingLanes.return; + noLongerPendingLanes = noLongerPendingLanes.sibling; } - detachFiber(current$jscomp$0); + } + var alternate = eventTimes.alternate; + detachFiberMutation(eventTimes); + null !== alternate && detachFiberMutation(alternate); } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$87) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$87); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - root$jscomp$1.current = finishedWork; - nextEffect = remainingExpirationTimeBeforeCommit; + root.current = finishedWork; + nextEffect = remainingLanes; do try { - for (effectTag = root$jscomp$1; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { - var instance = nextEffect.stateNode; + var instance$jscomp$0 = nextEffect.stateNode; switch (nextEffect.tag) { case 5: - current = instance.canonical; + current = instance$jscomp$0.canonical; break; default: - current = instance; + current = instance$jscomp$0; } "function" === typeof ref ? ref(current) @@ -6246,55 +6515,71 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$88) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$88); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); nextEffect = null; requestPaint(); - executionContext = prevExecutionContext; - } else root$jscomp$1.current = finishedWork; + executionContext = remainingLanes$jscomp$0; + } else root.current = finishedWork; if (rootDoesHavePassiveEffects) (rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root$jscomp$1), - (pendingPassiveEffectsRenderPriority = renderPriorityLevel$jscomp$1); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsRenderPriority = renderPriorityLevel); else - for ( - nextEffect = remainingExpirationTimeBeforeCommit; - null !== nextEffect; - - ) - (renderPriorityLevel$jscomp$1 = nextEffect.nextEffect), + for (nextEffect = remainingLanes; null !== nextEffect; ) + (renderPriorityLevel = nextEffect.nextEffect), (nextEffect.nextEffect = null), - (nextEffect = renderPriorityLevel$jscomp$1); - renderPriorityLevel$jscomp$1 = root$jscomp$1.firstPendingTime; - 0 === renderPriorityLevel$jscomp$1 && - (legacyErrorBoundariesThatAlreadyFailed = null); - 1073741823 === renderPriorityLevel$jscomp$1 - ? root$jscomp$1 === rootWithNestedUpdates + nextEffect.flags & 8 && + ((flags$jscomp$0 = nextEffect), + (flags$jscomp$0.sibling = null), + (flags$jscomp$0.stateNode = null)), + (nextEffect = renderPriorityLevel); + remainingLanes = root.pendingLanes; + 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); + 1 === remainingLanes + ? root === rootWithNestedUpdates ? nestedUpdateCount++ - : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root$jscomp$1)) + : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)) : (nestedUpdateCount = 0); - "function" === typeof onCommitFiberRoot && - onCommitFiberRoot(finishedWork.stateNode, expirationTime); - ensureRootIsScheduled(root$jscomp$1); + finishedWork = finishedWork.stateNode; + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + injectedHook.onCommitFiberRoot( + rendererID, + finishedWork, + void 0, + 64 === (finishedWork.current.flags & 64) + ); + } catch (err) {} + ensureRootIsScheduled(root, now()); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root$jscomp$1 = firstUncaughtError), + (root = firstUncaughtError), (firstUncaughtError = null), - root$jscomp$1); - if ((executionContext & LegacyUnbatchedContext) !== NoContext) return null; + root); + if (0 !== (executionContext & 8)) return null; flushSyncCallbackQueue(); return null; } function commitBeforeMutationEffects() { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect); - 0 === (effectTag & 512) || + var current = nextEffect.alternate; + shouldFireAfterActiveInstanceBlur || + null === focusedInstanceHandle || + (0 !== (nextEffect.flags & 8) + ? doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0) + : 13 === nextEffect.tag && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0)); + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6313,45 +6598,81 @@ function flushPassiveEffects() { pendingPassiveEffectsRenderPriority = 90; return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } + return !1; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); } function flushPassiveEffectsImpl() { if (null === rootWithPendingPassiveEffects) return !1; var root = rootWithPendingPassiveEffects; rootWithPendingPassiveEffects = null; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; - executionContext |= CommitContext; - for (root = root.current.firstEffect; null !== root; ) { + executionContext |= 32; + var unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + for (var i = 0; i < unmountEffects.length; i += 2) { + var effect$93 = unmountEffects[i], + fiber = unmountEffects[i + 1], + destroy = effect$93.destroy; + effect$93.destroy = void 0; + if ("function" === typeof destroy) + try { + destroy(); + } catch (error) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error); + } + } + unmountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; + for (i = 0; i < unmountEffects.length; i += 2) { + effect$93 = unmountEffects[i]; + fiber = unmountEffects[i + 1]; try { - var finishedWork = root; - if (0 !== (finishedWork.effectTag & 512)) - switch (finishedWork.tag) { - case 0: - case 11: - case 15: - case 22: - commitHookEffectListUnmount(5, finishedWork), - commitHookEffectListMount(5, finishedWork); - } - } catch (error) { - if (null === root) throw Error("Should be working on an effect."); - captureCommitPhaseError(root, error); + var create$97 = effect$93.create; + effect$93.destroy = create$97(); + } catch (error$98) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error$98); } - finishedWork = root.nextEffect; - root.nextEffect = null; - root = finishedWork; } + for (create$97 = root.current.firstEffect; null !== create$97; ) + (root = create$97.nextEffect), + (create$97.nextEffect = null), + create$97.flags & 8 && + ((create$97.sibling = null), (create$97.stateNode = null)), + (create$97 = root); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; } function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1073741823); + sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1); enqueueUpdate(rootFiber, sourceFiber); - rootFiber = markUpdateTimeFromFiberToRoot(rootFiber, 1073741823); - null !== rootFiber && ensureRootIsScheduled(rootFiber); + sourceFiber = requestEventTime(); + rootFiber = markUpdateLaneFromFiberToRoot(rootFiber, 1); + null !== rootFiber && + (markRootUpdated(rootFiber, 1, sourceFiber), + ensureRootIsScheduled(rootFiber, sourceFiber)); } function captureCommitPhaseError(sourceFiber, error) { if (3 === sourceFiber.tag) @@ -6370,145 +6691,166 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1073741823); - enqueueUpdate(fiber, sourceFiber); - fiber = markUpdateTimeFromFiberToRoot(fiber, 1073741823); - null !== fiber && ensureRootIsScheduled(fiber); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); + fiber = markUpdateLaneFromFiberToRoot(fiber, 1); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { +function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; - null !== pingCache && pingCache.delete(thenable); - workInProgressRoot === root && renderExpirationTime$1 === suspendedTime - ? workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ? prepareFreshStack(root, renderExpirationTime$1) - : (workInProgressRootHasPendingPing = !0) - : isRootSuspendedAtTime(root, suspendedTime) && - ((thenable = root.lastPingedTime), - (0 !== thenable && thenable < suspendedTime) || - ((root.lastPingedTime = suspendedTime), ensureRootIsScheduled(root))); -} -function resolveRetryThenable(boundaryFiber, thenable) { + null !== pingCache && pingCache.delete(wakeable); + wakeable = requestEventTime(); + root.pingedLanes |= root.suspendedLanes & pingedLanes; + workInProgressRoot === root && + (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && + (4 === workInProgressRootExitStatus || + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 62914560) === + workInProgressRootRenderLanes && + 500 > now() - globalMostRecentFallbackTime) + ? prepareFreshStack(root, 0) + : (workInProgressRootPingedLanes |= pingedLanes)); + ensureRootIsScheduled(root, wakeable); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(thenable); - thenable = 0; - 0 === thenable && - ((thenable = requestCurrentTimeForUpdate()), - (thenable = computeExpirationForFiber(thenable, boundaryFiber, null))); - boundaryFiber = markUpdateTimeFromFiberToRoot(boundaryFiber, thenable); - null !== boundaryFiber && ensureRootIsScheduled(boundaryFiber); + null !== retryCache && retryCache.delete(wakeable); + wakeable = 0; + 0 === wakeable && + ((wakeable = boundaryFiber.mode), + 0 === (wakeable & 2) + ? (wakeable = 1) + : 0 === (wakeable & 4) + ? (wakeable = 99 === getCurrentPriorityLevel() ? 1 : 2) + : (0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes), + (wakeable = getHighestPriorityLane(62914560 & ~currentEventWipLanes)), + 0 === wakeable && (wakeable = 4194304))); + retryCache = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + null !== boundaryFiber && + (markRootUpdated(boundaryFiber, wakeable, retryCache), + ensureRootIsScheduled(boundaryFiber, retryCache)); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +beginWork$1 = function(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || didPerformWorkStackCursor.current ) didReceiveUpdate = !0; + else if (0 !== (renderLanes & updateLanes)) + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { - if (updateExpirationTime < renderExpirationTime) { - didReceiveUpdate = !1; - switch (workInProgress.tag) { - case 3: - pushHostRootContext(workInProgress); - break; - case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer( + didReceiveUpdate = !1; + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; + case 10: + updateLanes = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + push(valueCursor, context._currentValue2); + context._currentValue2 = updateLanes; + break; + case 13: + if (null !== workInProgress.memoizedState) { + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + workInProgress = bailoutOnAlreadyFinishedWork( + current, workInProgress, - workInProgress.stateNode.containerInfo + renderLanes ); - break; - case 10: - updateExpirationTime = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - push(valueCursor, context._currentValue2); - context._currentValue2 = updateExpirationTime; - break; - case 13: - if (null !== workInProgress.memoizedState) { - updateExpirationTime = workInProgress.child.childExpirationTime; - if ( - 0 !== updateExpirationTime && - updateExpirationTime >= renderExpirationTime - ) - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - workInProgress = bailoutOnAlreadyFinishedWork( + return null !== workInProgress ? workInProgress.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + updateLanes = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 64)) { + if (updateLanes) + return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); - return null !== workInProgress ? workInProgress.sibling : null; - } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - updateExpirationTime = - workInProgress.childExpirationTime >= renderExpirationTime; - if (0 !== (current.effectTag & 64)) { - if (updateExpirationTime) - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 64; - } - context = workInProgress.memoizedState; - null !== context && - ((context.rendering = null), (context.tail = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (!updateExpirationTime) return null; - } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + workInProgress.flags |= 64; + } + context = workInProgress.memoizedState; + null !== context && + ((context.rendering = null), + (context.tail = null), + (context.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (updateLanes) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); } - didReceiveUpdate = !1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else didReceiveUpdate = !1; - workInProgress.expirationTime = 0; + workInProgress.lanes = 0; switch (workInProgress.tag) { case 2: - updateExpirationTime = workInProgress.type; + updateLanes = workInProgress.type; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); context = renderWithHooks( null, workInProgress, - updateExpirationTime, + updateLanes, current, context, - renderExpirationTime + renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -6518,7 +6860,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress.tag = 1; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - if (isContextProvider(updateExpirationTime)) { + if (isContextProvider(updateLanes)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; @@ -6527,53 +6869,41 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ? context.state : null; initializeUpdateQueue(workInProgress); - var getDerivedStateFromProps = - updateExpirationTime.getDerivedStateFromProps; + var getDerivedStateFromProps = updateLanes.getDerivedStateFromProps; "function" === typeof getDerivedStateFromProps && applyDerivedStateFromProps( workInProgress, - updateExpirationTime, + updateLanes, getDerivedStateFromProps, current ); context.updater = classComponentUpdater; workInProgress.stateNode = context; - context._reactInternalFiber = workInProgress; - mountClassInstance( - workInProgress, - updateExpirationTime, - current, - renderExpirationTime - ); + context._reactInternals = workInProgress; + mountClassInstance(workInProgress, updateLanes, current, renderLanes); workInProgress = finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, hasContext, - renderExpirationTime + renderLanes ); } else (workInProgress.tag = 0), - reconcileChildren( - null, - workInProgress, - context, - renderExpirationTime - ), + reconcileChildren(null, workInProgress, context, renderLanes), (workInProgress = workInProgress.child); return workInProgress; case 16: + context = workInProgress.elementType; a: { - context = workInProgress.elementType; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; - initializeLazyComponentType(context); - if (1 !== context._status) throw context._result; - context = context._result; + hasContext = context._init; + context = hasContext(context._payload); workInProgress.type = context; hasContext = workInProgress.tag = resolveLazyComponentTag(context); current = resolveDefaultProps(context, current); @@ -6584,7 +6914,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 1: @@ -6593,7 +6923,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 11: @@ -6602,7 +6932,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 14: @@ -6611,8 +6941,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, resolveDefaultProps(context.type, current), - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); break a; } @@ -6625,126 +6955,106 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return workInProgress; case 0: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateFunctionComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 1: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateClassComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 3: pushHostRootContext(workInProgress); - updateExpirationTime = workInProgress.updateQueue; - if (null === current || null === updateExpirationTime) + updateLanes = workInProgress.updateQueue; + if (null === current || null === updateLanes) throw Error( "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue." ); - updateExpirationTime = workInProgress.pendingProps; + updateLanes = workInProgress.pendingProps; context = workInProgress.memoizedState; context = null !== context ? context.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue( - workInProgress, - updateExpirationTime, - null, - renderExpirationTime - ); - updateExpirationTime = workInProgress.memoizedState.element; - updateExpirationTime === context + processUpdateQueue(workInProgress, updateLanes, null, renderLanes); + updateLanes = workInProgress.memoizedState.element; + updateLanes === context ? (workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes )) - : (reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + : (reconcileChildren(current, workInProgress, updateLanes, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; case 5: return ( pushHostContext(workInProgress), - (updateExpirationTime = workInProgress.pendingProps.children), + (updateLanes = workInProgress.pendingProps.children), markRef(current, workInProgress), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), - (workInProgress = workInProgress.child), - workInProgress + reconcileChildren(current, workInProgress, updateLanes, renderLanes), + workInProgress.child ); case 6: return null; case 13: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case 4: return ( pushHostContainer( workInProgress, workInProgress.stateNode.containerInfo ), - (updateExpirationTime = workInProgress.pendingProps), + (updateLanes = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, null, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes )) : reconcileChildren( current, workInProgress, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ), workInProgress.child ); case 11: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateForwardRef( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 7: @@ -6753,7 +7063,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -6763,7 +7073,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -6773,13 +7083,13 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 10: a: { - updateExpirationTime = workInProgress.type._context; + updateLanes = workInProgress.type._context; context = workInProgress.pendingProps; getDerivedStateFromProps = workInProgress.memoizedProps; hasContext = context.value; @@ -6791,9 +7101,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ((context$jscomp$0 = getDerivedStateFromProps.value), (hasContext = objectIs(context$jscomp$0, hasContext) ? 0 - : ("function" === - typeof updateExpirationTime._calculateChangedBits - ? updateExpirationTime._calculateChangedBits( + : ("function" === typeof updateLanes._calculateChangedBits + ? updateLanes._calculateChangedBits( context$jscomp$0, hasContext ) @@ -6807,7 +7116,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); break a; } @@ -6828,25 +7137,24 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ) { if ( - dependency.context === updateExpirationTime && + dependency.context === updateLanes && 0 !== (dependency.observedBits & hasContext) ) { 1 === context$jscomp$0.tag && - ((dependency = createUpdate(renderExpirationTime, null)), + ((dependency = createUpdate( + -1, + renderLanes & -renderLanes + )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); - context$jscomp$0.expirationTime < renderExpirationTime && - (context$jscomp$0.expirationTime = renderExpirationTime); + context$jscomp$0.lanes |= renderLanes; dependency = context$jscomp$0.alternate; - null !== dependency && - dependency.expirationTime < renderExpirationTime && - (dependency.expirationTime = renderExpirationTime); + null !== dependency && (dependency.lanes |= renderLanes); scheduleWorkOnParentPath( context$jscomp$0.return, - renderExpirationTime + renderLanes ); - list.expirationTime < renderExpirationTime && - (list.expirationTime = renderExpirationTime); + list.lanes |= renderLanes; break; } dependency = dependency.next; @@ -6884,7 +7192,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, context.children, - renderExpirationTime + renderLanes ); workInProgress = workInProgress.child; } @@ -6893,17 +7201,12 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return ( (context = workInProgress.type), (hasContext = workInProgress.pendingProps), - (updateExpirationTime = hasContext.children), - prepareToReadContext(workInProgress, renderExpirationTime), + (updateLanes = hasContext.children), + prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), - (updateExpirationTime = updateExpirationTime(context)), - (workInProgress.effectTag |= 1), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + (updateLanes = updateLanes(context)), + (workInProgress.flags |= 1), + reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); case 14: @@ -6919,8 +7222,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, hasContext, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); case 15: @@ -6929,48 +7232,43 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); case 17: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), - isContextProvider(updateExpirationTime) + isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) : (current = !1), - prepareToReadContext(workInProgress, renderExpirationTime), - constructClassInstance(workInProgress, updateExpirationTime, context), - mountClassInstance( - workInProgress, - updateExpirationTime, - context, - renderExpirationTime - ), + prepareToReadContext(workInProgress, renderLanes), + constructClassInstance(workInProgress, updateLanes, context), + mountClassInstance(workInProgress, updateLanes, context, renderLanes), finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, current, - renderExpirationTime + renderLanes ) ); case 19: - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + case 22: + return updateOffscreenComponent(current, workInProgress, renderLanes); + case 23: + return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( "Unknown unit of work tag (" + @@ -6978,32 +7276,6 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { "). This error is likely caused by a bug in React. Please file an issue." ); }; -var onCommitFiberRoot = null, - onCommitFiberUnmount = null; -function injectInternals(internals) { - if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled || !hook.supportsFiber) return !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = function(root) { - try { - hook.onCommitFiberRoot( - rendererID, - root, - void 0, - 64 === (root.current.effectTag & 64) - ); - } catch (err) {} - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) {} - }; - } catch (err) {} - return !0; -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -7013,11 +7285,14 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; - this.childExpirationTime = this.expirationTime = 0; + this.childLanes = this.lanes = 0; this.alternate = null; } +function createFiber(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); +} function shouldConstruct(Component) { Component = Component.prototype; return !(!Component || !Component.isReactComponent); @@ -7035,7 +7310,7 @@ function resolveLazyComponentTag(Component) { function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress - ? ((workInProgress = new FiberNode( + ? ((workInProgress = createFiber( current.tag, pendingProps, current.key, @@ -7047,12 +7322,13 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.alternate = current), (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), - (workInProgress.effectTag = 0), + (workInProgress.type = current.type), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null)); - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -7061,11 +7337,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.dependencies = null === pendingProps ? null - : { - expirationTime: pendingProps.expirationTime, - firstContext: pendingProps.firstContext, - responders: pendingProps.responders - }; + : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext }; workInProgress.sibling = current.sibling; workInProgress.index = current.index; workInProgress.ref = current.ref; @@ -7077,7 +7349,7 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { var fiberTag = 2; owner = type; @@ -7086,15 +7358,10 @@ function createFiberFromTypeAndProps( else a: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_CONCURRENT_MODE_TYPE: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = 8; - mode |= 7; + mode |= 16; break; case REACT_STRICT_MODE_TYPE: fiberTag = 8; @@ -7102,25 +7369,34 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: return ( - (type = new FiberNode(12, pendingProps, key, mode | 8)), + (type = createFiber(12, pendingProps, key, mode | 8)), (type.elementType = REACT_PROFILER_TYPE), (type.type = REACT_PROFILER_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_TYPE: return ( - (type = new FiberNode(13, pendingProps, key, mode)), + (type = createFiber(13, pendingProps, key, mode)), (type.type = REACT_SUSPENSE_TYPE), (type.elementType = REACT_SUSPENSE_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_LIST_TYPE: return ( - (type = new FiberNode(19, pendingProps, key, mode)), + (type = createFiber(19, pendingProps, key, mode)), (type.elementType = REACT_SUSPENSE_LIST_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), + type + ); + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + case REACT_LEGACY_HIDDEN_TYPE: + return ( + (type = createFiber(23, pendingProps, key, mode)), + (type.elementType = REACT_LEGACY_HIDDEN_TYPE), + (type.lanes = lanes), type ); default: @@ -7142,9 +7418,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7152,30 +7425,36 @@ function createFiberFromTypeAndProps( "." ); } - key = new FiberNode(fiberTag, pendingProps, key, mode); + key = createFiber(fiberTag, pendingProps, key, mode); key.elementType = type; key.type = owner; - key.expirationTime = expirationTime; + key.lanes = lanes; return key; } -function createFiberFromFragment(elements, mode, expirationTime, key) { - elements = new FiberNode(7, elements, key, mode); - elements.expirationTime = expirationTime; +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; return elements; } -function createFiberFromText(content, mode, expirationTime) { - content = new FiberNode(6, content, null, mode); - content.expirationTime = expirationTime; +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; return content; } -function createFiberFromPortal(portal, mode, expirationTime) { - mode = new FiberNode( +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( 4, null !== portal.children ? portal.children : [], portal.key, mode ); - mode.expirationTime = expirationTime; + mode.lanes = lanes; mode.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -7185,51 +7464,31 @@ function createFiberFromPortal(portal, mode, expirationTime) { } function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; - this.pingCache = this.pendingChildren = null; - this.finishedExpirationTime = 0; - this.finishedWork = null; + this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; this.timeoutHandle = -1; this.pendingContext = this.context = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = 90; - this.lastExpiredTime = this.lastPingedTime = this.nextKnownPendingLevel = this.lastSuspendedTime = this.firstSuspendedTime = this.firstPendingTime = 0; -} -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - root = root.lastSuspendedTime; - return ( - 0 !== firstSuspendedTime && - firstSuspendedTime >= expirationTime && - root <= expirationTime - ); + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; + this.entanglements = createLaneMap(0); } -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime, - lastSuspendedTime = root.lastSuspendedTime; - firstSuspendedTime < expirationTime && - (root.firstSuspendedTime = expirationTime); - if (lastSuspendedTime > expirationTime || 0 === firstSuspendedTime) - root.lastSuspendedTime = expirationTime; - expirationTime <= root.lastPingedTime && (root.lastPingedTime = 0); - expirationTime <= root.lastExpiredTime && (root.lastExpiredTime = 0); -} -function markRootUpdatedAtTime(root, expirationTime) { - expirationTime > root.firstPendingTime && - (root.firstPendingTime = expirationTime); - var firstSuspendedTime = root.firstSuspendedTime; - 0 !== firstSuspendedTime && - (expirationTime >= firstSuspendedTime - ? (root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = 0) - : expirationTime >= root.lastSuspendedTime && - (root.lastSuspendedTime = expirationTime + 1), - expirationTime > root.nextKnownPendingLevel && - (root.nextKnownPendingLevel = expirationTime)); +function createPortal(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } function findHostInstance(component) { - var fiber = component._reactInternalFiber; + var fiber = component._reactInternals; if (void 0 === fiber) { if ("function" === typeof component.render) throw Error("Unable to find node on an unmounted component."); @@ -7243,11 +7502,10 @@ function findHostInstance(component) { } function updateContainer(element, container, parentComponent, callback) { var current = container.current, - currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, current, suspenseConfig); + eventTime = requestEventTime(), + lane = requestUpdateLane(current); a: if (parentComponent) { - parentComponent = parentComponent._reactInternalFiber; + parentComponent = parentComponent._reactInternals; b: { if ( getNearestMountedFiber(parentComponent) !== parentComponent || @@ -7256,22 +7514,23 @@ function updateContainer(element, container, parentComponent, callback) { throw Error( "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." ); - var parentContext = parentComponent; + var JSCompiler_inline_result = parentComponent; do { - switch (parentContext.tag) { + switch (JSCompiler_inline_result.tag) { case 3: - parentContext = parentContext.stateNode.context; + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; break b; case 1: - if (isContextProvider(parentContext.type)) { - parentContext = - parentContext.stateNode + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode .__reactInternalMemoizedMergedChildContext; break b; } } - parentContext = parentContext.return; - } while (null !== parentContext); + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); throw Error( "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." ); @@ -7282,34 +7541,26 @@ function updateContainer(element, container, parentComponent, callback) { parentComponent = processChildContext( parentComponent, Component, - parentContext + JSCompiler_inline_result ); break a; } } - parentComponent = parentContext; + parentComponent = JSCompiler_inline_result; } else parentComponent = emptyContextObject; null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(currentTime, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); enqueueUpdate(current, container); - scheduleWork(current, currentTime); - return currentTime; + scheduleUpdateOnFiber(current, lane, eventTime); + return lane; } -function createPortal(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; +function emptyFindFiberByHostInstance() { + return null; } function findNodeHandle(componentOrHandle) { if (null == componentOrHandle) return null; @@ -7331,53 +7582,70 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - executionContext === NoContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; -var roots = new Map(); -(function(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: null, - overrideProps: null, - setSuspenseHandler: null, - scheduleUpdate: null, - currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - fiber = findCurrentHostFiber(fiber); - return null === fiber ? null : fiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - return findFiberByHostInstance ? findFiberByHostInstance(instance) : null; - }, - findHostInstancesForRefresh: null, - scheduleRefresh: null, - scheduleRoot: null, - setRefreshHandler: null, - getCurrentFiber: null - }); -})({ - findFiberByHostInstance: getInstanceFromInstance, - bundleType: 0, - version: "16.13.0", - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: function() { - throw Error( - "getInspectorDataForViewTag() is not available in production" - ); - }, - getInspectorDataForViewAtPoint: function() { - throw Error( - "getInspectorDataForViewAtPoint() is not available in production." - ); - }.bind(null, findNodeHandle) - } -}); +var roots = new Map(), + devToolsConfig$jscomp$inline_865 = { + findFiberByHostInstance: getInstanceFromInstance, + bundleType: 0, + version: "17.0.1-454c2211c", + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: function() { + throw Error( + "getInspectorDataForViewTag() is not available in production" + ); + }, + getInspectorDataForViewAtPoint: function() { + throw Error( + "getInspectorDataForViewAtPoint() is not available in production." + ); + }.bind(null, findNodeHandle) + } + }; +var internals$jscomp$inline_1054 = { + bundleType: devToolsConfig$jscomp$inline_865.bundleType, + version: devToolsConfig$jscomp$inline_865.version, + rendererPackageName: devToolsConfig$jscomp$inline_865.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_865.rendererConfig, + overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, + overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, + setSuspenseHandler: null, + scheduleUpdate: null, + currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, + findHostInstanceByFiber: function(fiber) { + fiber = findCurrentHostFiber(fiber); + return null === fiber ? null : fiber.stateNode; + }, + findFiberByHostInstance: + devToolsConfig$jscomp$inline_865.findFiberByHostInstance || + emptyFindFiberByHostInstance, + findHostInstancesForRefresh: null, + scheduleRefresh: null, + scheduleRoot: null, + setRefreshHandler: null, + getCurrentFiber: null +}; +if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { + var hook$jscomp$inline_1055 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if ( + !hook$jscomp$inline_1055.isDisabled && + hook$jscomp$inline_1055.supportsFiber + ) + try { + (rendererID = hook$jscomp$inline_1055.inject( + internals$jscomp$inline_1054 + )), + (injectedHook = hook$jscomp$inline_1055); + } catch (err) {} +} exports.createPortal = function(children, containerTag) { return createPortal( children, @@ -7417,7 +7685,7 @@ exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { root = new FiberRootNode(containerTag, 0, !1); - var uninitializedFiber = new FiberNode(3, null, null, 0); + var uninitializedFiber = createFiber(3, null, null, 0); root.current = uninitializedFiber; uninitializedFiber.stateNode = root; initializeUpdateQueue(uninitializedFiber); diff --git a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js index 2529b47e0b91d4..51f399468cdf57 100644 --- a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js @@ -920,7 +920,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_229 = { +var injectedNamesToPlugins$jscomp$inline_223 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -955,34 +955,34 @@ var injectedNamesToPlugins$jscomp$inline_229 = { } } }, - isOrderingDirty$jscomp$inline_230 = !1, - pluginName$jscomp$inline_231; -for (pluginName$jscomp$inline_231 in injectedNamesToPlugins$jscomp$inline_229) + isOrderingDirty$jscomp$inline_224 = !1, + pluginName$jscomp$inline_225; +for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) if ( - injectedNamesToPlugins$jscomp$inline_229.hasOwnProperty( - pluginName$jscomp$inline_231 + injectedNamesToPlugins$jscomp$inline_223.hasOwnProperty( + pluginName$jscomp$inline_225 ) ) { - var pluginModule$jscomp$inline_232 = - injectedNamesToPlugins$jscomp$inline_229[pluginName$jscomp$inline_231]; + var pluginModule$jscomp$inline_226 = + injectedNamesToPlugins$jscomp$inline_223[pluginName$jscomp$inline_225]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_231) || - namesToPlugins[pluginName$jscomp$inline_231] !== - pluginModule$jscomp$inline_232 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_225) || + namesToPlugins[pluginName$jscomp$inline_225] !== + pluginModule$jscomp$inline_226 ) { - if (namesToPlugins[pluginName$jscomp$inline_231]) + if (namesToPlugins[pluginName$jscomp$inline_225]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_231 + + pluginName$jscomp$inline_225 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_231 - ] = pluginModule$jscomp$inline_232; - isOrderingDirty$jscomp$inline_230 = !0; + pluginName$jscomp$inline_225 + ] = pluginModule$jscomp$inline_226; + isOrderingDirty$jscomp$inline_224 = !0; } } -isOrderingDirty$jscomp$inline_230 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_224 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -1019,7 +1019,6 @@ var ReactSharedInternals = REACT_SUSPENSE_LIST_TYPE = 60120, REACT_MEMO_TYPE = 60115, REACT_LAZY_TYPE = 60116, - REACT_BLOCK_TYPE = 60121, REACT_DEBUG_TRACING_MODE_TYPE = 60129, REACT_OFFSCREEN_TYPE = 60130, REACT_LEGACY_HIDDEN_TYPE = 60131; @@ -1037,7 +1036,6 @@ if ("function" === typeof Symbol && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); symbolFor("react.scope"); REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); @@ -1084,8 +1082,6 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); case REACT_LAZY_TYPE: innerType = type._payload; type = type._init; @@ -1103,7 +1099,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1713,7 +1709,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1753,31 +1749,27 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); Scheduler_now(); -var return_highestLanePriority = 10; +var return_highestLanePriority = 8; function getHighestPriorityLanes(lanes) { - if (0 !== (1 & lanes)) return (return_highestLanePriority = 17), 1; - if (0 !== (2 & lanes)) return (return_highestLanePriority = 16), 2; - if (0 !== (4 & lanes)) return (return_highestLanePriority = 15), 4; + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; var inputDiscreteLanes = 24 & lanes; - if (0 !== inputDiscreteLanes) - return (return_highestLanePriority = 14), inputDiscreteLanes; - if (0 !== (lanes & 32)) return (return_highestLanePriority = 13), 32; - inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 12), inputDiscreteLanes; - if (0 !== (lanes & 256)) return (return_highestLanePriority = 11), 256; - inputDiscreteLanes = 3584 & lanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 10), inputDiscreteLanes; - if (0 !== (lanes & 4096)) return (return_highestLanePriority = 9), 4096; - inputDiscreteLanes = 122880 & lanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 8), inputDiscreteLanes; - if (0 !== (lanes & 131072)) return (return_highestLanePriority = 7), 131072; - inputDiscreteLanes = 3932160 & lanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 6), inputDiscreteLanes; inputDiscreteLanes = 62914560 & lanes; @@ -1791,18 +1783,18 @@ function getHighestPriorityLanes(lanes) { return (return_highestLanePriority = 2), inputDiscreteLanes; if (0 !== (1073741824 & lanes)) return (return_highestLanePriority = 1), 1073741824; - return_highestLanePriority = 10; + return_highestLanePriority = 8; return lanes; } function schedulerPriorityToLanePriority(schedulerPriorityLevel) { switch (schedulerPriorityLevel) { case 99: - return 17; + return 15; case 98: - return 12; + return 10; case 97: case 96: - return 10; + return 8; case 95: return 2; default: @@ -1811,16 +1803,14 @@ function schedulerPriorityToLanePriority(schedulerPriorityLevel) { } function lanePriorityToSchedulerPriority(lanePriority) { switch (lanePriority) { - case 17: - case 16: - return 99; case 15: case 14: + return 99; case 13: case 12: - return 98; case 11: case 10: + return 98; case 9: case 8: case 7: @@ -1850,7 +1840,7 @@ function getNextLanes(root, wipLanes) { pingedLanes = root.pingedLanes; if (0 !== expiredLanes) (nextLanes = expiredLanes), - (nextLanePriority = return_highestLanePriority = 17); + (nextLanePriority = return_highestLanePriority = 15); else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; 0 !== nonIdleUnblockedLanes @@ -1889,42 +1879,31 @@ function getNextLanes(root, wipLanes) { (wipLanes &= ~nextLanePriority); return nextLanes; } -function getMostRecentEventTime(root, lanes) { - root = root.eventTimes; - for (var mostRecentEventTime = -1; 0 < lanes; ) { - var index$4 = 31 - clz32(lanes), - lane = 1 << index$4; - index$4 = root[index$4]; - index$4 > mostRecentEventTime && (mostRecentEventTime = index$4); - lanes &= ~lane; - } - return mostRecentEventTime; -} function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } function findUpdateLane(lanePriority, wipLanes) { switch (lanePriority) { - case 17: + case 15: return 1; - case 16: - return 2; case 14: + return 2; + case 12: return ( (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(12, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority ); - case 12: + case 10: return ( (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority ); - case 10: + case 8: return ( (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), 0 === lanePriority && - ((lanePriority = getHighestPriorityLane(4055040 & ~wipLanes)), + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), 0 === lanePriority && (lanePriority = 512)), lanePriority ); @@ -1942,8 +1921,9 @@ function findUpdateLane(lanePriority, wipLanes) { function getHighestPriorityLane(lanes) { return lanes & -lanes; } -function pickArbitraryLane(lanes) { - return lanes & -lanes; +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; @@ -1978,7 +1958,7 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); var fakeCallbackNode = {}, requestPaint = @@ -2067,30 +2047,7 @@ function flushSyncCallbackQueueImpl() { } } } -function describeFiber(fiber) { - switch (fiber.tag) { - case 5: - return describeComponentFrame(fiber.type, null, null); - case 16: - return describeComponentFrame("Lazy", null, null); - case 13: - return describeComponentFrame("Suspense", null, null); - case 19: - return describeComponentFrame("SuspenseList", null, null); - case 0: - case 2: - case 15: - return describeFunctionComponentFrame(fiber.type, null); - case 11: - return describeFunctionComponentFrame(fiber.type.render, null); - case 22: - return describeFunctionComponentFrame(fiber.type._render, null); - case 1: - return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; - default: - return ""; - } -} +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -2116,6 +2073,28 @@ function shallowEqual(objA, objB) { return !1; return !0; } +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } +} function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { baseProps = Object.assign({}, baseProps); @@ -2209,11 +2188,10 @@ function cloneUpdateQueue(current, workInProgress) { effects: current.effects }); } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { return { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: 0, payload: null, callback: null, @@ -2246,7 +2224,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: queue.eventTime, lane: queue.lane, - suspenseConfig: queue.suspenseConfig, tag: queue.tag, payload: queue.payload, callback: queue.callback, @@ -2320,16 +2297,11 @@ function processUpdateQueue( (current = current.next = { eventTime: updateEventTime, lane: 0, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, next: null }); - markRenderEventTimeAndConfig( - updateEventTime, - firstBaseUpdate.suspenseConfig - ); a: { var workInProgress = workInProgress$jscomp$0, update = firstBaseUpdate; @@ -2349,8 +2321,7 @@ function processUpdateQueue( currentLastBaseUpdate = workInProgress; break a; case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; + workInProgress.flags = (workInProgress.flags & -8193) | 64; case 0: workInProgress = update.payload; pendingQueue = @@ -2373,7 +2344,7 @@ function processUpdateQueue( } } null !== firstBaseUpdate.callback && - ((workInProgress$jscomp$0.effectTag |= 32), + ((workInProgress$jscomp$0.flags |= 32), (pendingQueue = queue.effects), null === pendingQueue ? (queue.effects = [firstBaseUpdate]) @@ -2382,7 +2353,6 @@ function processUpdateQueue( (updateEventTime = { eventTime: updateEventTime, lane: pendingQueue, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, @@ -2434,8 +2404,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2461,41 +2430,32 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); } }; @@ -2588,7 +2548,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2603,7 +2563,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2637,7 +2597,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2661,7 +2621,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2693,16 +2653,16 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -3237,11 +3197,12 @@ function ChildReconciler(shouldTrackSideEffects) { switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3301,7 +3262,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3333,7 +3294,7 @@ var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3458,40 +3419,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var suspenseConfig = update.suspenseConfig, - updateLane = update.lane, - updateEventTime = update.eventTime; - (renderLanes & updateLane) === updateLane - ? (null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - eventTime: updateEventTime, - lane: 0, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }), - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig), - (current = - update.eagerReducer === reducer - ? update.eagerState - : reducer(current, update.action))) - : ((suspenseConfig = { - eventTime: updateEventTime, - lane: updateLane, - suspenseConfig: suspenseConfig, + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) + null !== newBaseQueueLast && + (newBaseQueueLast = newBaseQueueLast.next = { + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = suspenseConfig), - (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = suspenseConfig), - (currentlyRenderingFiber$1.lanes |= updateLane), - (workInProgressRootSkippedLanes |= updateLane)); + (current = + update.eagerReducer === reducer + ? update.eagerState + : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3576,10 +3531,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { maybeNewVersion = getSnapshot(source._source); objectIs(snapshot, maybeNewVersion) || (setSnapshot(maybeNewVersion), - (maybeNewVersion = requestUpdateLane( - fiber, - ReactCurrentBatchConfig.suspense - )), + (maybeNewVersion = requestUpdateLane(fiber)), (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); maybeNewVersion = root.mutableReadLanes; root.entangledLanes |= maybeNewVersion; @@ -3588,9 +3540,9 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { 0 < lanes; ) { - var index$12 = 31 - clz32(lanes), - lane = 1 << index$12; - entanglements[index$12] |= maybeNewVersion; + var index$11 = 31 - clz32(lanes), + lane = 1 << index$11; + entanglements[index$11] |= maybeNewVersion; lanes &= ~lane; } } @@ -3604,7 +3556,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { latestSetSnapshot = refs.setSnapshot; try { latestSetSnapshot(latestGetSnapshot(source._source)); - var lane = requestUpdateLane(fiber, ReactCurrentBatchConfig.suspense); + var lane = requestUpdateLane(fiber); root.mutableReadLanes |= lane & root.pendingLanes; } catch (error) { latestSetSnapshot(function() { @@ -3675,17 +3627,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3693,12 +3645,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3737,13 +3689,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3771,39 +3716,36 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(fiber, suspenseConfig); - suspenseConfig = { - eventTime: eventTime, - lane: lane, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || @@ -3819,8 +3761,8 @@ function dispatchAction(fiber, queue, action) { try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { @@ -3848,7 +3790,13 @@ var ContextOnlyDispatcher = { }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3894,36 +3842,30 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; }, useMutableSource: function(source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -3953,36 +3895,27 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4004,36 +3937,27 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4090,11 +4014,11 @@ function updateForwardRef( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } @@ -4131,7 +4055,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -4148,7 +4072,7 @@ function updateMemoComponent( Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -4168,7 +4092,7 @@ function updateSimpleMemoComponent( current.ref === workInProgress.ref ) if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) - 0 !== (current.effectTag & 16384) && (didReceiveUpdate = !0); + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); else return ( (workInProgress.lanes = current.lanes), @@ -4203,9 +4127,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { return ( (current = null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [1073741824]) - : spawnedWorkDuringRender.push(1073741824), + markSpawnedWork(1073741824), (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current }), pushRenderLanes(workInProgress, current), @@ -4226,7 +4148,7 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, @@ -4251,11 +4173,11 @@ function updateFunctionComponent( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } @@ -4275,7 +4197,7 @@ function updateClassComponent( null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -4341,9 +4263,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4351,7 +4273,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4424,17 +4346,17 @@ function updateClassComponent( oldContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) + (workInProgress.flags |= 256)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4444,11 +4366,11 @@ function updateClassComponent( : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (nextProps = !1)); } return finishClassComponent( @@ -4469,7 +4391,7 @@ function finishClassComponent( renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), @@ -4484,7 +4406,7 @@ function finishClassComponent( var nextChildren = null; profilerStartTime = -1; } else nextChildren = shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((didCaptureError = nextChildren), (workInProgress.child = reconcileChildFibers( @@ -4522,55 +4444,49 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = suspenseStackCursor.current, showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((showFallback = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { + current = nextProps.children; + suspenseContext = nextProps.fallback; if (showFallback) return ( - (current = nextProps.fallback), - (suspenseContext = workInProgress.mode), - (showFallback = workInProgress.child), - (nextProps = { mode: "hidden", children: nextProps.children }), - 0 === (suspenseContext & 2) && null !== showFallback - ? ((showFallback.childLanes = 0), - (showFallback.pendingProps = nextProps), - workInProgress.mode & 8 && - ((showFallback.actualDuration = 0), - (showFallback.actualStartTime = -1), - (showFallback.selfBaseDuration = 0), - (showFallback.treeBaseDuration = 0))) - : (showFallback = createFiberFromOffscreen( - nextProps, - suspenseContext, - 0, - null - )), - (current = createFiberFromFragment( + (current = mountSuspenseFallbackChildren( + workInProgress, current, suspenseContext, - renderLanes, - null + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current + ); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes )), - (showFallback.return = workInProgress), - (current.return = workInProgress), - (showFallback.sibling = current), - (workInProgress.child = showFallback), (workInProgress.child.memoizedState = { baseLanes: renderLanes }), (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432), current ); renderLanes = createFiberFromOffscreen( - { mode: "visible", children: nextProps.children }, + { mode: "visible", children: current }, workInProgress.mode, renderLanes, null @@ -4588,13 +4504,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4616,13 +4532,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4635,6 +4551,41 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { workInProgress.memoizedState = null; return renderLanes; } +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren), + workInProgress.mode & 8 && + ((progressedPrimaryFragment.actualDuration = 0), + (progressedPrimaryFragment.actualStartTime = -1), + (progressedPrimaryFragment.selfBaseDuration = 0), + (progressedPrimaryFragment.treeBaseDuration = 0))) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} function updateSuspensePrimaryChildren( current, workInProgress, @@ -4652,7 +4603,7 @@ function updateSuspensePrimaryChildren( primaryChildren.sibling = null; null !== current && ((current.nextEffect = null), - (current.effectTag = 8), + (current.flags = 8), (workInProgress.firstEffect = workInProgress.lastEffect = current)); return (workInProgress.child = primaryChildren); } @@ -4696,7 +4647,7 @@ function updateSuspenseFallbackChildren( renderLanes, null )), - (fallbackChildren.effectTag |= 2)); + (fallbackChildren.flags |= 2)); fallbackChildren.return = workInProgress; primaryChildren.return = workInProgress; primaryChildren.sibling = fallbackChildren; @@ -4725,7 +4676,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4734,7 +4684,6 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } @@ -4745,9 +4694,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && @@ -4882,7 +4831,7 @@ appendAllChildren = function( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4935,7 +4884,7 @@ function appendAllChildrenToContainer( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4979,7 +4928,7 @@ updateHostContainer = function(workInProgress) { newChildSet = createChildNodeSet(container); appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); portalOrRoot.pendingChildren = newChildSet; - workInProgress.effectTag |= 4; + workInProgress.flags |= 4; completeRoot(container, newChildSet); } }; @@ -5017,7 +4966,7 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { }), (workInProgress.stateNode = type), current - ? (workInProgress.effectTag |= 4) + ? (workInProgress.flags |= 4) : appendAllChildren(type, workInProgress, !1, !1)); } }; @@ -5031,7 +4980,7 @@ updateHostText$1 = function(current, workInProgress, oldText, newText) { oldText, workInProgress )), - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : (workInProgress.stateNode = current.stateNode); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { @@ -5086,7 +5035,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.pendingContext = null)), (null !== current && null !== current.child) || newProps.hydrate || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -5104,8 +5053,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -5140,7 +5088,7 @@ function completeWork(current, workInProgress, renderLanes) { current = { node: rootContainerInstance, canonical: current }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -5169,7 +5117,7 @@ function completeWork(current, workInProgress, renderLanes) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return ( (workInProgress.lanes = renderLanes), 0 !== (workInProgress.mode & 8) && @@ -5202,7 +5150,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderLanes ); } - newProps && (workInProgress.effectTag |= 4); + newProps && (workInProgress.flags |= 4); return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -5214,24 +5162,24 @@ function completeWork(current, workInProgress, renderLanes) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.effectTag & 64)) + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; @@ -5239,7 +5187,7 @@ function completeWork(current, workInProgress, renderLanes) { for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (updatePayload = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), @@ -5287,6 +5235,13 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); } else { if (!rootContainerInstance) @@ -5294,12 +5249,12 @@ function completeWork(current, workInProgress, renderLanes) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -5312,15 +5267,14 @@ function completeWork(current, workInProgress, renderLanes) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.lanes = renderLanes), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [renderLanes]) - : spawnedWorkDuringRender.push(renderLanes)); + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5331,9 +5285,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -5348,15 +5300,15 @@ function completeWork(current, workInProgress, renderLanes) { ), current) : null; + case 22: case 23: - case 24: return ( popRenderLanes(), null !== current && (null !== current.memoizedState) !== (null !== workInProgress.memoizedState) && "unstable-defer-without-hiding" !== newProps.mode && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), null ); } @@ -5370,9 +5322,9 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), 0 !== (workInProgress.mode & 8) && transferActualDuration(workInProgress), workInProgress) @@ -5382,21 +5334,21 @@ function unwindWork(workInProgress) { pop(didPerformWorkStackCursor); pop(contextStackCursor); resetWorkInProgressVersions(); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), 0 !== (workInProgress.mode & 8) && transferActualDuration(workInProgress), workInProgress) @@ -5408,8 +5360,8 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: case 23: - case 24: return popRenderLanes(), null; default: return null; @@ -5452,7 +5404,7 @@ function logCapturedError(boundary, errorInfo) { } var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; @@ -5463,7 +5415,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { return lane; } function createClassErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { @@ -5506,10 +5458,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5539,7 +5490,6 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 0: case 11: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5570,7 +5520,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { return; case 1: finishedRoot = finishedWork.stateNode; - finishedWork.effectTag & 4 && + finishedWork.flags & 4 && (null === current ? finishedRoot.componentDidMount() : ((create$82 = @@ -5605,7 +5555,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { } return; case 5: - null === current && finishedWork.effectTag & 4 && shim(); + null === current && finishedWork.flags & 4 && shim(); return; case 6: return; @@ -5631,8 +5581,8 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: case 23: - case 24: return; } throw Error( @@ -5657,7 +5607,6 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5682,8 +5631,8 @@ function commitWork(current, finishedWork) { case 19: attachSuspenseRetryListeners(finishedWork); return; + case 22: case 23: - case 24: return; } a: { @@ -5738,14 +5687,13 @@ var ceil = Math.ceil, subtreeRenderLanesCursor = createCursor(0), workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestSuspenseTimeout = -1, - workInProgressRootCanSuspendUsingConfig = null, workInProgressRootIncludedLanes = 0, workInProgressRootSkippedLanes = 0, workInProgressRootUpdatedLanes = 0, workInProgressRootPingedLanes = 0, mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5772,46 +5720,33 @@ function requestEventTime() { ? currentEventTime : (currentEventTime = now()); } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; if (0 === (fiber & 2)) return 1; if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; 0 === currentEventWipLanes && (currentEventWipLanes = workInProgressRootIncludedLanes); - if (null !== suspenseConfig) { - suspenseConfig = suspenseConfig.timeoutMs; - fiber = void 0 === suspenseConfig || 1e4 > (suspenseConfig | 0) ? 8 : 6; + if (0 !== ReactCurrentBatchConfig.transition) { 0 !== currentEventPendingLanes && (currentEventPendingLanes = null !== mostRecentlyUpdatedRoot ? mostRecentlyUpdatedRoot.pendingLanes : 0); - suspenseConfig = currentEventWipLanes; - var pendingLanes = currentEventPendingLanes; - if (8 === fiber) - (fiber = pickArbitraryLane(122880 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(122880 & ~suspenseConfig)), - 0 === fiber && (fiber = 8192)), - (suspenseConfig = fiber); - else if (6 === fiber) - (fiber = pickArbitraryLane(3932160 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(3932160 & ~suspenseConfig)), - 0 === fiber && (fiber = 262144)), - (suspenseConfig = fiber); - else - throw Error( - "Invalid transition priority: " + fiber + ". This is a bug in React." - ); - return suspenseConfig; + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; } - suspenseConfig = getCurrentPriorityLevel(); - 0 !== (executionContext & 4) && 98 === suspenseConfig - ? (suspenseConfig = findUpdateLane(14, currentEventWipLanes)) - : ((suspenseConfig = schedulerPriorityToLanePriority(suspenseConfig)), - (suspenseConfig = findUpdateLane(suspenseConfig, currentEventWipLanes))); - return suspenseConfig; + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; } function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) @@ -5833,7 +5768,9 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { ? (schedulePendingInteractions(fiber, lane), performSyncWorkOnRoot(fiber)) : (ensureRootIsScheduled(fiber, eventTime), schedulePendingInteractions(fiber, lane), - 0 === executionContext && flushSyncCallbackQueue()) + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) : (0 === (executionContext & 4) || (98 !== priorityLevel && 99 !== priorityLevel) || (null === rootsWithPendingDiscreteUpdates @@ -5875,8 +5812,8 @@ function ensureRootIsScheduled(root, currentTime) { getHighestPriorityLanes(lane); var priority = return_highestLanePriority; expirationTimes[index$5] = - 12 <= priority - ? expirationTime + 1e3 + 10 <= priority + ? expirationTime + 250 : 6 <= priority ? expirationTime + 5e3 : -1; @@ -5901,7 +5838,7 @@ function ensureRootIsScheduled(root, currentTime) { existingCallbackNode !== fakeCallbackNode && Scheduler_cancelCallback(existingCallbackNode); } - 17 === currentTime + 15 === currentTime ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), null === syncQueue ? ((syncQueue = [existingCallbackNode]), @@ -5911,7 +5848,7 @@ function ensureRootIsScheduled(root, currentTime) { ))) : syncQueue.push(existingCallbackNode), (existingCallbackNode = fakeCallbackNode)) - : 16 === currentTime + : 14 === currentTime ? (existingCallbackNode = scheduleCallback( 99, performSyncWorkOnRoot.bind(null, root) @@ -5925,7 +5862,7 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { currentEventTime = -1; currentEventPendingLanes = currentEventWipLanes = 0; if (0 !== (executionContext & 48)) @@ -5938,21 +5875,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - if (didTimeout) - return ( - (root.expiredLanes |= lanes & root.pendingLanes), - ensureRootIsScheduled(root, now()), - null - ); var lanes$jscomp$0 = lanes; - didTimeout = executionContext; + var exitStatus = executionContext; executionContext |= 16; var prevDispatcher = pushDispatcher(); if ( workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes$jscomp$0 ) - prepareFreshStack(root, lanes$jscomp$0), + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, lanes$jscomp$0), startWorkOnPendingInteractions(root, lanes$jscomp$0); lanes$jscomp$0 = pushInteractions(root); do @@ -5966,21 +5898,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { resetContextDependencies(); tracing.__interactionsRef.current = lanes$jscomp$0; ReactCurrentDispatcher$2.current = prevDispatcher; - executionContext = didTimeout; + executionContext = exitStatus; null !== workInProgress - ? (didTimeout = 0) + ? (exitStatus = 0) : ((workInProgressRoot = null), (workInProgressRootRenderLanes = 0), - (didTimeout = workInProgressRootExitStatus)); + (exitStatus = workInProgressRootExitStatus)); if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) prepareFreshStack(root, 0); - else if (0 !== didTimeout) { - 2 === didTimeout && + else if (0 !== exitStatus) { + 2 === exitStatus && ((executionContext |= 64), root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), (lanes = getLanesToRetrySynchronouslyOnError(root)), - 0 !== lanes && (didTimeout = renderRootSync(root, lanes))); - if (1 === didTimeout) + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), markRootSuspended$1(root, lanes), @@ -5988,7 +5920,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); @@ -5999,8 +5931,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ( (lanes & 62914560) === lanes && - ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; prevDispatcher = root.suspendedLanes; @@ -6011,7 +5943,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - didTimeout + exitStatus ); break; } @@ -6019,33 +5951,31 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; case 4: markRootSuspended$1(root, lanes); - if (0 !== getNextLanes(root, 0)) break; - didTimeout = root.suspendedLanes; - if ((didTimeout & lanes) !== lanes) { - requestEventTime(); - root.pingedLanes |= root.suspendedLanes & didTimeout; - break; + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevDispatcher = -1; 0 < lanes; ) { + var index$4 = 31 - clz32(lanes); + lanes$jscomp$0 = 1 << index$4; + index$4 = exitStatus[index$4]; + index$4 > prevDispatcher && (prevDispatcher = index$4); + lanes &= ~lanes$jscomp$0; } - lanes = getMostRecentEventTime(root, lanes); - -1 !== workInProgressRootLatestSuspenseTimeout - ? (lanes = workInProgressRootLatestSuspenseTimeout - now()) - : -1 === lanes - ? (lanes = 0) - : ((lanes = now() - lanes), - (lanes = - (120 > lanes - ? 120 - : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes)); + lanes = prevDispatcher; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), @@ -6056,30 +5986,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { commitRoot(root); break; case 5: - lanes$jscomp$0 = getMostRecentEventTime(root, lanes); - if ( - -1 !== lanes$jscomp$0 && - null !== workInProgressRootCanSuspendUsingConfig && - ((didTimeout = - workInProgressRootCanSuspendUsingConfig.busyMinDurationMs | 0), - 0 >= didTimeout - ? (didTimeout = 0) - : ((prevDispatcher = - workInProgressRootCanSuspendUsingConfig.busyDelayMs | 0), - (lanes$jscomp$0 = now() - lanes$jscomp$0), - (didTimeout = - lanes$jscomp$0 <= prevDispatcher - ? 0 - : prevDispatcher + didTimeout - lanes$jscomp$0)), - 10 < didTimeout) - ) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - didTimeout - ); - break; - } commitRoot(root); break; default: @@ -6097,9 +6003,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$10 = 31 - clz32(suspendedLanes), - lane = 1 << index$10; - root[index$10] = -1; + var index$9 = 31 - clz32(suspendedLanes), + lane = 1 << index$9; + root[index$9] = -1; suspendedLanes &= ~lane; } } @@ -6182,8 +6088,8 @@ function prepareFreshStack(root, lanes) { case 10: popProvider(interruptedWork); break; + case 22: case 23: - case 24: popRenderLanes(); } timeoutHandle = timeoutHandle.return; @@ -6193,8 +6099,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = -1; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; spawnedWorkDuringRender = null; } @@ -6234,7 +6138,7 @@ function handleError(root$jscomp$0, thrownValue) { sourceFiber = erroredWork, value = thrownValue; thrownValue = workInProgressRootRenderLanes; - sourceFiber.effectTag |= 2048; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && @@ -6280,13 +6184,13 @@ function handleError(root$jscomp$0, thrownValue) { workInProgress$77.updateQueue = updateQueue; } else wakeables.add(wakeable); if (0 === (workInProgress$77.mode & 2)) { - workInProgress$77.effectTag |= 64; - sourceFiber.effectTag |= 16384; - sourceFiber.effectTag &= -2981; + workInProgress$77.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(-1, 1, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } @@ -6313,7 +6217,7 @@ function handleError(root$jscomp$0, thrownValue) { ); wakeable.then(ping, ping); } - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; workInProgress$77.lanes = thrownValue; break a; } @@ -6332,7 +6236,7 @@ function handleError(root$jscomp$0, thrownValue) { switch (workInProgress$77.tag) { case 3: root = value; - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; thrownValue &= -thrownValue; workInProgress$77.lanes |= thrownValue; var update$78 = createRootErrorUpdate( @@ -6347,14 +6251,14 @@ function handleError(root$jscomp$0, thrownValue) { var ctor = workInProgress$77.type, instance = workInProgress$77.stateNode; if ( - 0 === (workInProgress$77.effectTag & 64) && + 0 === (workInProgress$77.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; thrownValue &= -thrownValue; workInProgress$77.lanes |= thrownValue; var update$81 = createClassErrorUpdate( @@ -6390,13 +6294,6 @@ function pushInteractions(root) { tracing.__interactionsRef.current = root.memoizedInteractions; return prevInteractions; } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - null !== suspenseConfig && - ((eventTime += suspenseConfig.timeoutMs | 0 || 5e3), - eventTime > workInProgressRootLatestSuspenseTimeout && - ((workInProgressRootLatestSuspenseTimeout = eventTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig))); -} function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 16; @@ -6450,7 +6347,7 @@ function completeUnitOfWork(unitOfWork) { do { var current = completedWork.alternate; unitOfWork = completedWork.return; - if (0 === (completedWork.effectTag & 2048)) { + if (0 === (completedWork.flags & 4096)) { if (0 === (completedWork.mode & 8)) current = completeWork(current, completedWork, subtreeRenderLanes); else { @@ -6466,7 +6363,7 @@ function completeUnitOfWork(unitOfWork) { } current = completedWork; if ( - (24 !== current.tag && 23 !== current.tag) || + (23 !== current.tag && 22 !== current.tag) || null === current.memoizedState || 0 !== (subtreeRenderLanes & 1073741824) || 0 === (current.mode & 4) @@ -6503,14 +6400,14 @@ function completeUnitOfWork(unitOfWork) { current.childLanes = fiber; } null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && (unitOfWork.firstEffect = completedWork.firstEffect), null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), (unitOfWork.lastEffect = completedWork.lastEffect)), - 1 < completedWork.effectTag && + 1 < completedWork.flags && (null !== unitOfWork.lastEffect ? (unitOfWork.lastEffect.nextEffect = completedWork) : (unitOfWork.firstEffect = completedWork), @@ -6518,7 +6415,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(completedWork); if (null !== current) { - current.effectTag &= 2047; + current.flags &= 4095; workInProgress = current; return; } @@ -6531,7 +6428,7 @@ function completeUnitOfWork(unitOfWork) { } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } completedWork = completedWork.sibling; if (null !== completedWork) { @@ -6577,11 +6474,11 @@ function commitRootImpl(root, renderPriorityLevel) { 0 < noLongerPendingLanes; ) { - var index$11 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$11; - remainingLanes$jscomp$0[index$11] = 0; - eventTimes[index$11] = -1; - expirationTimes[index$11] = -1; + var index$10 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$10; + remainingLanes$jscomp$0[index$10] = 0; + eventTimes[index$10] = -1; + expirationTimes[index$10] = -1; noLongerPendingLanes &= ~lane; } null !== rootsWithPendingDiscreteUpdates && @@ -6591,7 +6488,7 @@ function commitRootImpl(root, renderPriorityLevel) { root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - 1 < finishedWork.effectTag + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), (remainingLanes = finishedWork.firstEffect)) @@ -6619,8 +6516,8 @@ function commitRootImpl(root, renderPriorityLevel) { do try { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6630,19 +6527,19 @@ function commitRootImpl(root, renderPriorityLevel) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: @@ -6650,8 +6547,8 @@ function commitRootImpl(root, renderPriorityLevel) { break; case 8: expirationTimes = nextEffect; - a: for (index$11 = noLongerPendingLanes = expirationTimes; ; ) { - lane = index$11; + a: for (index$10 = noLongerPendingLanes = expirationTimes; ; ) { + lane = index$10; if ( injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount @@ -6664,7 +6561,6 @@ function commitRootImpl(root, renderPriorityLevel) { case 11: case 14: case 15: - case 22: var updateQueue = lane.updateQueue; if (null !== updateQueue) { var lastEffect = updateQueue.lastEffect; @@ -6714,21 +6610,21 @@ function commitRootImpl(root, renderPriorityLevel) { case 4: createChildNodeSet(lane.stateNode.containerInfo); } - if (null !== index$11.child) - (index$11.child.return = index$11), - (index$11 = index$11.child); + if (null !== index$10.child) + (index$10.child.return = index$10), + (index$10 = index$10.child); else { - if (index$11 === noLongerPendingLanes) break; - for (; null === index$11.sibling; ) { + if (index$10 === noLongerPendingLanes) break; + for (; null === index$10.sibling; ) { if ( - null === index$11.return || - index$11.return === noLongerPendingLanes + null === index$10.return || + index$10.return === noLongerPendingLanes ) break a; - index$11 = index$11.return; + index$10 = index$10.return; } - index$11.sibling.return = index$11.return; - index$11 = index$11.sibling; + index$10.sibling.return = index$10.return; + index$10 = index$10.sibling; } } var alternate = expirationTimes.alternate; @@ -6737,9 +6633,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$95) { + } catch (error$90) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$95); + captureCommitPhaseError(nextEffect, error$90); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6747,11 +6643,11 @@ function commitRootImpl(root, renderPriorityLevel) { nextEffect = remainingLanes; do try { - for (effectTag = root; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6770,9 +6666,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$96) { + } catch (error$91) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$96); + captureCommitPhaseError(nextEffect, error$91); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6781,7 +6677,7 @@ function commitRootImpl(root, renderPriorityLevel) { tracing.__interactionsRef.current = eventTimes; executionContext = remainingLanes$jscomp$0; } else (root.current = finishedWork), (commitTime = now$1()); - if ((effectTag$jscomp$0 = rootDoesHavePassiveEffects)) + if ((flags$jscomp$0 = rootDoesHavePassiveEffects)) (rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes), @@ -6790,7 +6686,7 @@ function commitRootImpl(root, renderPriorityLevel) { for (nextEffect = remainingLanes; null !== nextEffect; ) (ref = nextEffect.nextEffect), (nextEffect.nextEffect = null), - nextEffect.effectTag & 8 && + nextEffect.flags & 8 && ((instance$jscomp$0 = nextEffect), (instance$jscomp$0.sibling = null), (instance$jscomp$0.stateNode = null)), @@ -6812,7 +6708,7 @@ function commitRootImpl(root, renderPriorityLevel) { ); schedulePendingInteractions(root, remainingLanes); } else legacyErrorBoundariesThatAlreadyFailed = null; - effectTag$jscomp$0 || finishPendingInteractions(root, lanes); + flags$jscomp$0 || finishPendingInteractions(root, lanes); 1 === remainingLanes ? root === rootWithNestedUpdates ? nestedUpdateCount++ @@ -6825,7 +6721,7 @@ function commitRootImpl(root, renderPriorityLevel) { rendererID, finishedWork, renderPriorityLevel, - 64 === (finishedWork.current.effectTag & 64) + 64 === (finishedWork.current.flags & 64) ); } catch (err) {} ensureRootIsScheduled(root, now()); @@ -6843,17 +6739,16 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; shouldFireAfterActiveInstanceBlur || null === focusedInstanceHandle || - (0 !== (nextEffect.effectTag & 8) + (0 !== (nextEffect.flags & 8) ? doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0) : 13 === nextEffect.tag && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0)); - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(current, nextEffect); - 0 === (effectTag & 512) || + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6870,7 +6765,6 @@ function flushPassiveEffects() { ? 97 : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = 90; - schedulerPriorityToLanePriority(priorityLevel); return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } return !1; @@ -6907,10 +6801,10 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsUnmount; pendingPassiveHookEffectsUnmount = []; for (var i = 0; i < unmountEffects.length; i += 2) { - var effect$101 = unmountEffects[i], + var effect$96 = unmountEffects[i], fiber = unmountEffects[i + 1], - destroy = effect$101.destroy; - effect$101.destroy = void 0; + destroy = effect$96.destroy; + effect$96.destroy = void 0; if ("function" === typeof destroy) try { destroy(); @@ -6922,22 +6816,22 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsMount; pendingPassiveHookEffectsMount = []; for (i = 0; i < unmountEffects.length; i += 2) { - effect$101 = unmountEffects[i]; + effect$96 = unmountEffects[i]; fiber = unmountEffects[i + 1]; try { - var create$105 = effect$101.create; - effect$101.destroy = create$105(); - } catch (error$106) { + var create$100 = effect$96.create; + effect$96.destroy = create$100(); + } catch (error$101) { if (null === fiber) throw Error("Should be working on an effect."); - captureCommitPhaseError(fiber, error$106); + captureCommitPhaseError(fiber, error$101); } } for (unmountEffects = root.current.firstEffect; null !== unmountEffects; ) - (create$105 = unmountEffects.nextEffect), + (create$100 = unmountEffects.nextEffect), (unmountEffects.nextEffect = null), - unmountEffects.effectTag & 8 && + unmountEffects.flags & 8 && ((unmountEffects.sibling = null), (unmountEffects.stateNode = null)), - (unmountEffects = create$105); + (unmountEffects = create$100); tracing.__interactionsRef.current = prevInteractions; finishPendingInteractions(root, lanes); executionContext = prevExecutionContext; @@ -6972,14 +6866,22 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1); - enqueueUpdate(fiber, sourceFiber); - sourceFiber = requestEventTime(); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); fiber = markUpdateLaneFromFiberToRoot(fiber, 1); - null !== fiber && - (markRootUpdated(fiber, 1, sourceFiber), - ensureRootIsScheduled(fiber, sourceFiber), - schedulePendingInteractions(fiber, 1)); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update), + schedulePendingInteractions(fiber, 1); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } @@ -7034,7 +6936,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ) didReceiveUpdate = !0; else if (0 !== (renderLanes & updateLanes)) - didReceiveUpdate = 0 !== (current.effectTag & 16384) ? !0 : !1; + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { didReceiveUpdate = !1; switch (workInProgress.tag) { @@ -7062,7 +6964,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 12: 0 !== (renderLanes & workInProgress.childLanes) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); updateLanes = workInProgress.stateNode; updateLanes.effectDuration = 0; updateLanes.passiveEffectDuration = 0; @@ -7087,14 +6989,14 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 19: updateLanes = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.effectTag & 64)) { + if (0 !== (current.flags & 64)) { if (updateLanes) return updateSuspenseListComponent( current, workInProgress, renderLanes ); - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; } context = workInProgress.memoizedState; null !== context && @@ -7104,8 +7006,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { push(suspenseStackCursor, suspenseStackCursor.current); if (updateLanes) break; else return null; + case 22: case 23: - case 24: return ( (workInProgress.lanes = 0), updateOffscreenComponent(current, workInProgress, renderLanes) @@ -7121,7 +7023,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); prepareToReadContext(workInProgress, renderLanes); @@ -7133,7 +7035,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context, renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -7183,7 +7085,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; hasContext = context._init; context = hasContext(context._payload); @@ -7362,7 +7264,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 12: return ( - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (updateLanes = workInProgress.stateNode), (updateLanes.effectDuration = 0), (updateLanes.passiveEffectDuration = 0), @@ -7430,8 +7332,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { 1 === context$jscomp$0.tag && ((dependency = createUpdate( -1, - renderLanes & -renderLanes, - null + renderLanes & -renderLanes )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); @@ -7493,7 +7394,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), (updateLanes = updateLanes(context)), - (workInProgress.effectTag |= 1), + (workInProgress.flags |= 1), reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); @@ -7534,7 +7435,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) @@ -7553,9 +7454,9 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 19: return updateSuspenseListComponent(current, workInProgress, renderLanes); - case 23: + case 22: return updateOffscreenComponent(current, workInProgress, renderLanes); - case 24: + case 23: return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( @@ -7564,6 +7465,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { "). This error is likely caused by a bug in React. Please file an issue." ); }; +function markSpawnedWork(lane) { + null === spawnedWorkDuringRender + ? (spawnedWorkDuringRender = [lane]) + : spawnedWorkDuringRender.push(lane); +} function scheduleInteractions(root, lane, interactions) { if (0 < interactions.size) { var pendingInteractionMap = root.pendingInteractionMap, @@ -7637,9 +7543,9 @@ function finishPendingInteractions(root, committedLanes) { if (null !== subscriber && 0 === interaction.__count) try { subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error$107) { + } catch (error$102) { scheduleCallback(99, function() { - throw error$107; + throw error$102; }); } })); @@ -7655,7 +7561,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; this.childLanes = this.lanes = 0; this.alternate = null; @@ -7696,7 +7602,7 @@ function createWorkInProgress(current, pendingProps) { (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), (workInProgress.type = current.type), - (workInProgress.effectTag = 0), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null), @@ -7772,7 +7678,7 @@ function createFiberFromTypeAndProps( return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: return ( - (type = createFiber(24, pendingProps, key, mode)), + (type = createFiber(23, pendingProps, key, mode)), (type.elementType = REACT_LEGACY_HIDDEN_TYPE), (type.lanes = lanes), type @@ -7796,9 +7702,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7818,7 +7721,7 @@ function createFiberFromFragment(elements, mode, lanes, key) { return elements; } function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps = createFiber(22, pendingProps, key, mode); pendingProps.elementType = REACT_OFFSCREEN_TYPE; pendingProps.lanes = lanes; return pendingProps; @@ -7852,10 +7755,10 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.hydrate = hydrate; this.callbackNode = null; this.callbackPriority = 0; - this.eventTimes = Array(31).fill(0); - this.expirationTimes = Array(31).fill(-1); + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; - this.entanglements = Array(31).fill(0); + this.entanglements = createLaneMap(0); this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); @@ -7887,8 +7790,7 @@ function findHostInstance(component) { function updateContainer(element, container, parentComponent, callback) { var current = container.current, eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(current, suspenseConfig); + lane = requestUpdateLane(current); a: if (parentComponent) { parentComponent = parentComponent._reactInternals; b: { @@ -7936,7 +7838,7 @@ function updateContainer(element, container, parentComponent, callback) { null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(eventTime, lane, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); @@ -7967,14 +7869,16 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - 0 === executionContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; var roots = new Map(), - devToolsConfig$jscomp$inline_913 = { + devToolsConfig$jscomp$inline_887 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "17.0.0-alpha.0", + version: "17.0.1-454c2211c", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -7989,13 +7893,17 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1111 = { - bundleType: devToolsConfig$jscomp$inline_913.bundleType, - version: devToolsConfig$jscomp$inline_913.version, - rendererPackageName: devToolsConfig$jscomp$inline_913.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_913.rendererConfig, +var internals$jscomp$inline_1087 = { + bundleType: devToolsConfig$jscomp$inline_887.bundleType, + version: devToolsConfig$jscomp$inline_887.version, + rendererPackageName: devToolsConfig$jscomp$inline_887.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_887.rendererConfig, overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, @@ -8004,7 +7912,7 @@ var internals$jscomp$inline_1111 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_913.findFiberByHostInstance || + devToolsConfig$jscomp$inline_887.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, @@ -8013,16 +7921,16 @@ var internals$jscomp$inline_1111 = { getCurrentFiber: null }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1112 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1088 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1112.isDisabled && - hook$jscomp$inline_1112.supportsFiber + !hook$jscomp$inline_1088.isDisabled && + hook$jscomp$inline_1088.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1112.inject( - internals$jscomp$inline_1111 + (rendererID = hook$jscomp$inline_1088.inject( + internals$jscomp$inline_1087 )), - (injectedHook = hook$jscomp$inline_1112); + (injectedHook = hook$jscomp$inline_1088); } catch (err) {} } exports.createPortal = function(children, containerTag) { @@ -8089,6 +7997,18 @@ exports.render = function(element, containerTag, callback) { else element = null; return element; }; +exports.sendAccessibilityEvent = function(handle, eventType) { + null != handle._nativeTag && + (handle._internalInstanceHandle + ? nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ) + : ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + )); +}; exports.stopSurface = function(containerTag) { var root = roots.get(containerTag); root && diff --git a/Libraries/Renderer/implementations/ReactFabric-profiling.js b/Libraries/Renderer/implementations/ReactFabric-profiling.js index cc076b1040285b..65acff0cff3217 100644 --- a/Libraries/Renderer/implementations/ReactFabric-profiling.js +++ b/Libraries/Renderer/implementations/ReactFabric-profiling.js @@ -17,16 +17,6 @@ var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/R React = require("react"), Scheduler = require("scheduler"), tracing = require("scheduler/tracing"); -function getParent(inst) { - do inst = inst.return; - while (inst && 5 !== inst.tag); - return inst ? inst : null; -} -function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); - for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); -} function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -97,109 +87,6 @@ function executeDirectDispatch(event) { event._dispatchInstances = null; return dispatchListener; } -function getListener(inst, registrationName) { - var listener = inst.stateNode; - if (!listener) return null; - var props = getFiberCurrentPropsFromNode(listener); - if (!props) return null; - listener = props[registrationName]; - a: switch (registrationName) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - (props = !props.disabled) || - ((inst = inst.type), - (props = !( - "button" === inst || - "input" === inst || - "select" === inst || - "textarea" === inst - ))); - inst = !props; - break a; - default: - inst = !1; - } - if (inst) return null; - if (listener && "function" !== typeof listener) - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - return listener; -} -function accumulateInto(current, next) { - if (null == next) - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - if (null == current) return next; - if (Array.isArray(current)) { - if (Array.isArray(next)) return current.push.apply(current, next), current; - current.push(next); - return current; - } - return Array.isArray(next) ? [current].concat(next) : [current, next]; -} -function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); -} -function accumulateDirectionalDispatches(inst, phase, event) { - if ( - (phase = getListener( - inst, - event.dispatchConfig.phasedRegistrationNames[phase] - )) - ) - (event._dispatchListeners = accumulateInto( - event._dispatchListeners, - phase - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - )); -} -function accumulateTwoPhaseDispatchesSingle(event) { - event && - event.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); -} -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - targetInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); - } -} -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - var inst = event._targetInst; - if (inst && event && event.dispatchConfig.registrationName) { - var listener = getListener(inst, event.dispatchConfig.registrationName); - listener && - ((event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); - } - } -} function functionThatReturnsTrue() { return !0; } @@ -215,6 +102,7 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchInstances = this._dispatchListeners = null; dispatchConfig = this.constructor.Interface; for (var propName in dispatchConfig) dispatchConfig.hasOwnProperty(propName) && @@ -294,7 +182,12 @@ SyntheticEvent.extend = function(Interface) { return Class; }; addEventPoolingTo(SyntheticEvent); -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { if (this.eventPool.length) { var instance = this.eventPool.pop(); this.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); @@ -311,8 +204,8 @@ function releasePooledEvent(event) { 10 > this.eventPool.length && this.eventPool.push(event); } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ @@ -440,6 +333,22 @@ function accumulate(current, next) { ? [current].concat(next) : [current, next]; } +function accumulateInto(current, next) { + if (null == next) + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + if (null == current) return next; + if (Array.isArray(current)) { + if (Array.isArray(next)) return current.push.apply(current, next), current; + current.push(next); + return current; + } + return Array.isArray(next) ? [current].concat(next) : [current, next]; +} +function forEachAccumulated(arr, cb, scope) { + Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); +} var responderInst = null, trackedTouchCount = 0; function changeResponder(nextResponderInst, blockHostResponder) { @@ -453,65 +362,132 @@ function changeResponder(nextResponderInst, blockHostResponder) { ); } var eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: ["topScroll"] - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: ["topSelectionChange"] - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies - }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies + dependencies: startDependencies + }, + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] + dependencies: ["topScroll"] + }, + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" }, - responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] + dependencies: ["topSelectionChange"] + }, + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } + dependencies: moveDependencies + }, + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies + }, + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies }, - ResponderEventPlugin = { + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, + responderReject: { registrationName: "onResponderReject", dependencies: [] }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } +}; +function getParent(inst) { + do inst = inst.return; + while (inst && 5 !== inst.tag); + return inst ? inst : null; +} +function traverseTwoPhase(inst, fn, arg) { + for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); +} +function getListener(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +function accumulateDirectionalDispatches(inst, phase, event) { + if ( + (phase = getListener( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + targetInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); + } +} +function accumulateTwoPhaseDispatchesSingle(event) { + event && + event.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); +} +var ResponderEventPlugin = { _getResponder: function() { return responderInst; }, @@ -572,68 +548,70 @@ var eventTypes = { JSCompiler_temp = null; } else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp === responderInst; - JSCompiler_temp = ResponderSyntheticEvent.getPooled( + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( shouldSetEventType, - JSCompiler_temp, + targetInst, nativeEvent, nativeEventTarget ); - JSCompiler_temp.touchHistory = ResponderTouchHistoryStore.touchHistory; - targetInst + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp ? forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingleSkipTarget ) : forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingle ); b: { - shouldSetEventType = JSCompiler_temp._dispatchListeners; - targetInst = JSCompiler_temp._dispatchInstances; - if (Array.isArray(shouldSetEventType)) + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (Array.isArray(JSCompiler_temp)) for ( depthA = 0; - depthA < shouldSetEventType.length && - !JSCompiler_temp.isPropagationStopped(); + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); depthA++ ) { if ( - shouldSetEventType[depthA](JSCompiler_temp, targetInst[depthA]) + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - shouldSetEventType = targetInst[depthA]; + JSCompiler_temp = targetInst[depthA]; break b; } } else if ( - shouldSetEventType && - shouldSetEventType(JSCompiler_temp, targetInst) + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) ) { - shouldSetEventType = targetInst; + JSCompiler_temp = targetInst; break b; } - shouldSetEventType = null; + JSCompiler_temp = null; } - JSCompiler_temp._dispatchInstances = null; - JSCompiler_temp._dispatchListeners = null; - JSCompiler_temp.isPersistent() || - JSCompiler_temp.constructor.release(JSCompiler_temp); - if (shouldSetEventType && shouldSetEventType !== responderInst) + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) if ( - ((JSCompiler_temp = ResponderSyntheticEvent.getPooled( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderGrant, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), - (JSCompiler_temp.touchHistory = + (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateDirectDispatchesSingle ), - (targetInst = !0 === executeDirectDispatch(JSCompiler_temp)), + (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) ) if ( @@ -660,13 +638,13 @@ var eventTypes = { forEachAccumulated(depthA, accumulateDirectDispatchesSingle); var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - [JSCompiler_temp, depthA] + [shouldSetEventType, depthA] ); - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); } else (shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderReject, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), @@ -683,9 +661,9 @@ var eventTypes = { else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - JSCompiler_temp + shouldSetEventType )), - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); else JSCompiler_temp$jscomp$0 = null; } else JSCompiler_temp$jscomp$0 = null; shouldSetEventType = responderInst && isStartish(topLevelType); @@ -813,7 +791,6 @@ function recomputePluginOrdering() { for (var eventName in pluginIndex) { var JSCompiler_inline_result = void 0; var dispatchConfig = pluginIndex[eventName], - pluginModule$jscomp$0 = pluginModule, eventName$jscomp$0 = eventName; if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( @@ -830,7 +807,7 @@ function recomputePluginOrdering() { ) && publishRegistrationName( phasedRegistrationNames[JSCompiler_inline_result], - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ); JSCompiler_inline_result = !0; @@ -838,7 +815,7 @@ function recomputePluginOrdering() { dispatchConfig.registrationName ? (publishRegistrationName( dispatchConfig.registrationName, - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ), (JSCompiler_inline_result = !0)) @@ -866,13 +843,75 @@ function publishRegistrationName(registrationName, pluginModule) { } var plugins = [], eventNameDispatchConfigs = {}, - registrationNameModules = {}, - customBubblingEventTypes = + registrationNameModules = {}; +function getListener$1(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; +function accumulateDirectionalDispatches$1(inst, phase, event) { + if ( + (phase = getListener$1( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + for (var inst = event._targetInst, path = []; inst; ) { + path.push(inst); + do inst = inst.return; + while (inst && 5 !== inst.tag); + inst = inst ? inst : null; + } + for (inst = path.length; 0 < inst--; ) + accumulateDirectionalDispatches$1(path[inst], "captured", event); + for (inst = 0; inst < path.length; inst++) + accumulateDirectionalDispatches$1(path[inst], "bubbled", event); + } +} +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener$1(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} if (eventPluginOrder) throw Error( "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React." @@ -882,7 +921,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_92 = { +var injectedNamesToPlugins$jscomp$inline_223 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -906,42 +945,45 @@ var injectedNamesToPlugins$jscomp$inline_92 = { nativeEventTarget ); if (bubbleDispatchConfig) - forEachAccumulated(topLevelType, accumulateTwoPhaseDispatchesSingle); + forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle); + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); else return null; return topLevelType; } } }, - isOrderingDirty$jscomp$inline_93 = !1, - pluginName$jscomp$inline_94; -for (pluginName$jscomp$inline_94 in injectedNamesToPlugins$jscomp$inline_92) + isOrderingDirty$jscomp$inline_224 = !1, + pluginName$jscomp$inline_225; +for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) if ( - injectedNamesToPlugins$jscomp$inline_92.hasOwnProperty( - pluginName$jscomp$inline_94 + injectedNamesToPlugins$jscomp$inline_223.hasOwnProperty( + pluginName$jscomp$inline_225 ) ) { - var pluginModule$jscomp$inline_95 = - injectedNamesToPlugins$jscomp$inline_92[pluginName$jscomp$inline_94]; + var pluginModule$jscomp$inline_226 = + injectedNamesToPlugins$jscomp$inline_223[pluginName$jscomp$inline_225]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_94) || - namesToPlugins[pluginName$jscomp$inline_94] !== - pluginModule$jscomp$inline_95 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_225) || + namesToPlugins[pluginName$jscomp$inline_225] !== + pluginModule$jscomp$inline_226 ) { - if (namesToPlugins[pluginName$jscomp$inline_94]) + if (namesToPlugins[pluginName$jscomp$inline_225]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_94 + + pluginName$jscomp$inline_225 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_94 - ] = pluginModule$jscomp$inline_95; - isOrderingDirty$jscomp$inline_93 = !0; + pluginName$jscomp$inline_225 + ] = pluginModule$jscomp$inline_226; + isOrderingDirty$jscomp$inline_224 = !0; } } -isOrderingDirty$jscomp$inline_93 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_224 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -965,31 +1007,42 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler({ } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher") || - (ReactSharedInternals.ReactCurrentDispatcher = { current: null }); -ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig") || - (ReactSharedInternals.ReactCurrentBatchConfig = { suspense: null }); -var hasSymbol = "function" === typeof Symbol && Symbol.for, - REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, - REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, - REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, - REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, - REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, - REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, - REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 60111, - REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, - REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 60120, - REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115, - REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116, - REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121, - MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + REACT_ELEMENT_TYPE = 60103, + REACT_PORTAL_TYPE = 60106, + REACT_FRAGMENT_TYPE = 60107, + REACT_STRICT_MODE_TYPE = 60108, + REACT_PROFILER_TYPE = 60114, + REACT_PROVIDER_TYPE = 60109, + REACT_CONTEXT_TYPE = 60110, + REACT_FORWARD_REF_TYPE = 60112, + REACT_SUSPENSE_TYPE = 60113, + REACT_SUSPENSE_LIST_TYPE = 60120, + REACT_MEMO_TYPE = 60115, + REACT_LAZY_TYPE = 60116, + REACT_DEBUG_TRACING_MODE_TYPE = 60129, + REACT_OFFSCREEN_TYPE = 60130, + REACT_LEGACY_HIDDEN_TYPE = 60131; +if ("function" === typeof Symbol && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + symbolFor("react.scope"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} +var MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "object" !== typeof maybeIterable) return null; maybeIterable = @@ -997,27 +1050,6 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } -function initializeLazyComponentType(lazyComponent) { - if (-1 === lazyComponent._status) { - var ctor = lazyComponent._result; - ctor || (ctor = lazyComponent._ctor); - ctor = ctor(); - lazyComponent._status = 0; - lazyComponent._result = ctor; - ctor.then( - function(moduleObject) { - 0 === lazyComponent._status && - ((moduleObject = moduleObject.default), - (lazyComponent._status = 1), - (lazyComponent._result = moduleObject)); - }, - function(error) { - 0 === lazyComponent._status && - ((lazyComponent._status = 2), (lazyComponent._result = error)); - } - ); - } -} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1051,11 +1083,12 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); case REACT_LAZY_TYPE: - if ((type = 1 === type._status ? type._result : null)) - return getComponentName(type); + innerType = type._payload; + type = type._init; + try { + return getComponentName(type(innerType)); + } catch (x) {} } return null; } @@ -1067,7 +1100,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1107,36 +1140,36 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { + for (var didFindChild = !1, child$0 = parentA.child; child$0; ) { + if (child$0 === a) { didFindChild = !0; a = parentA; b = parentB; break; } - if (_child === b) { + if (child$0 === b) { didFindChild = !0; b = parentA; a = parentB; break; } - _child = _child.sibling; + child$0 = child$0.sibling; } if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { + for (child$0 = parentB.child; child$0; ) { + if (child$0 === a) { didFindChild = !0; a = parentB; b = parentA; break; } - if (_child === b) { + if (child$0 === b) { didFindChild = !0; b = parentB; a = parentA; break; } - _child = _child.sibling; + child$0 = child$0.sibling; } if (!didFindChild) throw Error( @@ -1171,6 +1204,18 @@ function findCurrentHostFiber(parent) { } return null; } +function doesFiberContain(parentFiber, childFiber) { + for ( + var parentFiberAlternate = parentFiber.alternate; + null !== childFiber; + + ) { + if (childFiber === parentFiber || childFiber === parentFiberAlternate) + return !0; + childFiber = childFiber.return; + } + return !1; +} function mountSafeCallback_NOT_REALLY_SAFE(context, callback) { return function() { if ( @@ -1384,19 +1429,19 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ), (removedKeys = null)); } - for (var _propKey in prevProps) - void 0 === nextProps[_propKey] && - (!(attributeConfig = validAttributes[_propKey]) || - (updatePayload && void 0 !== updatePayload[_propKey]) || - ((prevProp = prevProps[_propKey]), + for (var propKey$2 in prevProps) + void 0 === nextProps[propKey$2] && + (!(attributeConfig = validAttributes[propKey$2]) || + (updatePayload && void 0 !== updatePayload[propKey$2]) || + ((prevProp = prevProps[propKey$2]), void 0 !== prevProp && ("object" !== typeof attributeConfig || "function" === typeof attributeConfig.diff || "function" === typeof attributeConfig.process - ? (((updatePayload || (updatePayload = {}))[_propKey] = null), + ? (((updatePayload || (updatePayload = {}))[propKey$2] = null), removedKeys || (removedKeys = {}), - removedKeys[_propKey] || - ((removedKeys[_propKey] = !0), removedKeyCount++)) + removedKeys[propKey$2] || + ((removedKeys[propKey$2] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( updatePayload, prevProp, @@ -1444,37 +1489,49 @@ function dispatchEvent(target, topLevelType, nativeEvent) { null != stateNode && (eventTarget = stateNode.canonical); } batchedUpdates(function() { - var events = eventTarget; - for (var events$jscomp$0 = null, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; + var JSCompiler_inline_result = eventTarget; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; possiblePlugin && (possiblePlugin = possiblePlugin.extractEvents( topLevelType, target, nativeEvent, - events, - 1 + JSCompiler_inline_result )) && - (events$jscomp$0 = accumulateInto(events$jscomp$0, possiblePlugin)); + (events = accumulateInto(events, possiblePlugin)); } - events = events$jscomp$0; - null !== events && (eventQueue = accumulateInto(eventQueue, events)); - events = eventQueue; + JSCompiler_inline_result = events; + null !== JSCompiler_inline_result && + (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); + JSCompiler_inline_result = eventQueue; eventQueue = null; - if (events) { - forEachAccumulated(events, executeDispatchesAndReleaseTopLevel); + if (JSCompiler_inline_result) { + forEachAccumulated( + JSCompiler_inline_result, + executeDispatchesAndReleaseTopLevel + ); if (eventQueue) throw Error( "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." ); if (hasRethrowError) - throw ((events = rethrowError), + throw ((JSCompiler_inline_result = rethrowError), (hasRethrowError = !1), (rethrowError = null), - events); + JSCompiler_inline_result); } }); } +function shim() { + throw Error( + "The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue." + ); +} function shim$1() { throw Error( "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." @@ -1567,19 +1624,32 @@ var scheduleTimeout = setTimeout, cancelTimeout = clearTimeout; function cloneHiddenInstance(instance) { var node = instance.node; - var updatePayload = diffProperties( + var JSCompiler_inline_result = diffProperties( null, emptyObject, { style: { display: "none" } }, instance.canonical.viewConfig.validAttributes ); return { - node: cloneNodeWithNewProps(node, updatePayload), + node: cloneNodeWithNewProps(node, JSCompiler_inline_result), canonical: instance.canonical }; } +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; +} +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; +} var valueStack = [], index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} function pop(cursor) { 0 > index || ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); @@ -1590,8 +1660,8 @@ function push(cursor, value) { cursor.current = value; } var emptyContextObject = {}, - contextStackCursor = { current: emptyContextObject }, - didPerformWorkStackCursor = { current: !1 }, + contextStackCursor = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyContextObject; function getMaskedContext(workInProgress, unmaskedContext) { var contextTypes = workInProgress.type.contextTypes; @@ -1640,7 +1710,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1671,12 +1741,212 @@ function invalidateContextProvider(workInProgress, type, didChange) { : pop(didPerformWorkStackCursor); push(didPerformWorkStackCursor, didChange); } +var rendererID = null, + injectedHook = null, + isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__, + Scheduler_now = Scheduler.unstable_now; +if ( + null == tracing.__interactionsRef || + null == tracing.__interactionsRef.current +) + throw Error( + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" + ); +Scheduler_now(); +var return_highestLanePriority = 8; +function getHighestPriorityLanes(lanes) { + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; + var inputDiscreteLanes = 24 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 12), inputDiscreteLanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 10), inputDiscreteLanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 8), inputDiscreteLanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 6), inputDiscreteLanes; + inputDiscreteLanes = 62914560 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 5), inputDiscreteLanes; + if (lanes & 67108864) return (return_highestLanePriority = 4), 67108864; + if (0 !== (lanes & 134217728)) + return (return_highestLanePriority = 3), 134217728; + inputDiscreteLanes = 805306368 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 2), inputDiscreteLanes; + if (0 !== (1073741824 & lanes)) + return (return_highestLanePriority = 1), 1073741824; + return_highestLanePriority = 8; + return lanes; +} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case 99: + return 15; + case 98: + return 10; + case 97: + case 96: + return 8; + case 95: + return 2; + default: + return 0; + } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case 15: + case 14: + return 99; + case 13: + case 12: + case 11: + case 10: + return 98; + case 9: + case 8: + case 7: + case 6: + case 4: + case 5: + return 97; + case 3: + case 2: + case 1: + return 95; + case 0: + return 90; + default: + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} +function getNextLanes(root, wipLanes) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return (return_highestLanePriority = 0); + var nextLanes = 0, + nextLanePriority = 0, + expiredLanes = root.expiredLanes, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes; + if (0 !== expiredLanes) + (nextLanes = expiredLanes), + (nextLanePriority = return_highestLanePriority = 15); + else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { + var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; + 0 !== nonIdleUnblockedLanes + ? ((nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)), + (nextLanePriority = return_highestLanePriority)) + : ((pingedLanes &= expiredLanes), + 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority))); + } else + (expiredLanes = pendingLanes & ~suspendedLanes), + 0 !== expiredLanes + ? ((nextLanes = getHighestPriorityLanes(expiredLanes)), + (nextLanePriority = return_highestLanePriority)) + : 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority)); + if (0 === nextLanes) return 0; + nextLanes = 31 - clz32(nextLanes); + nextLanes = pendingLanes & (((0 > nextLanes ? 0 : 1 << nextLanes) << 1) - 1); + if ( + 0 !== wipLanes && + wipLanes !== nextLanes && + 0 === (wipLanes & suspendedLanes) + ) { + getHighestPriorityLanes(wipLanes); + if (nextLanePriority <= return_highestLanePriority) return wipLanes; + return_highestLanePriority = nextLanePriority; + } + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (nextLanePriority = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~nextLanePriority); + return nextLanes; +} +function getLanesToRetrySynchronouslyOnError(root) { + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; +} +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case 15: + return 1; + case 14: + return 2; + case 12: + return ( + (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + ); + case 10: + return ( + (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority + ); + case 8: + return ( + (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), + 0 === lanePriority && + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), + 0 === lanePriority && (lanePriority = 512)), + lanePriority + ); + case 2: + return ( + (wipLanes = getHighestPriorityLane(805306368 & ~wipLanes)), + 0 === wipLanes && (wipLanes = 268435456), + wipLanes + ); + } + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); +} +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + var higherPriorityLanes = updateLane - 1; + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, + log = Math.log, + LN2 = Math.LN2; +function clz32Fallback(lanes) { + return 0 === lanes ? 32 : (31 - ((log(lanes) / LN2) | 0)) | 0; +} var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, Scheduler_shouldYield = Scheduler.unstable_shouldYield, Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, + Scheduler_now$1 = Scheduler.unstable_now, Scheduler_getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel, Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, @@ -1689,7 +1959,7 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); var fakeCallbackNode = {}, requestPaint = @@ -1697,12 +1967,12 @@ var fakeCallbackNode = {}, syncQueue = null, immediateQueueCallbackNode = null, isFlushingSyncQueue = !1, - initialTimeMs = Scheduler_now(), + initialTimeMs$1 = Scheduler_now$1(), now = - 1e4 > initialTimeMs - ? Scheduler_now + 1e4 > initialTimeMs$1 + ? Scheduler_now$1 : function() { - return Scheduler_now() - initialTimeMs; + return Scheduler_now$1() - initialTimeMs$1; }; function getCurrentPriorityLevel() { switch (Scheduler_getCurrentPriorityLevel()) { @@ -1744,16 +2014,6 @@ function scheduleCallback(reactPriorityLevel, callback, options) { reactPriorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); return Scheduler_scheduleCallback(reactPriorityLevel, callback, options); } -function scheduleSyncCallback(callback) { - null === syncQueue - ? ((syncQueue = [callback]), - (immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ))) - : syncQueue.push(callback); - return fakeCallbackNode; -} function flushSyncCallbackQueue() { if (null !== immediateQueueCallbackNode) { var node = immediateQueueCallbackNode; @@ -1788,19 +2048,7 @@ function flushSyncCallbackQueueImpl() { } } } -function inferPriorityFromExpirationTime(currentTime, expirationTime) { - if (1073741823 === expirationTime) return 99; - if (1 === expirationTime || 2 === expirationTime) return 95; - currentTime = - 10 * (1073741821 - expirationTime) - 10 * (1073741821 - currentTime); - return 0 >= currentTime - ? 99 - : 250 >= currentTime - ? 98 - : 5250 >= currentTime - ? 97 - : 95; -} +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -1826,42 +2074,27 @@ function shallowEqual(objA, objB) { return !1; return !0; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; -function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 3: - case 4: - case 6: - case 7: - case 10: - case 9: - var JSCompiler_inline_result = ""; - break a; - default: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource, - name = getComponentName(workInProgress.type); - JSCompiler_inline_result = null; - owner && (JSCompiler_inline_result = getComponentName(owner.type)); - owner = name; - name = ""; - source - ? (name = - " (at " + - source.fileName.replace(BEFORE_SLASH_RE, "") + - ":" + - source.lineNumber + - ")") - : JSCompiler_inline_result && - (name = " (created by " + JSCompiler_inline_result + ")"); - JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress.return; - } while (workInProgress); - return info; +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } } function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { @@ -1870,10 +2103,11 @@ function resolveDefaultProps(Component, baseProps) { for (var propName in Component) void 0 === baseProps[propName] && (baseProps[propName] = Component[propName]); + return baseProps; } return baseProps; } -var valueCursor = { current: null }, +var valueCursor = createCursor(null), currentlyRenderingFiber = null, lastContextDependency = null, lastContextWithAllBitsObserved = null; @@ -1885,31 +2119,29 @@ function popProvider(providerFiber) { pop(valueCursor); providerFiber.type._context._currentValue2 = currentValue; } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { +function scheduleWorkOnParentPath(parent, renderLanes) { for (; null !== parent; ) { var alternate = parent.alternate; - if (parent.childExpirationTime < renderExpirationTime) - (parent.childExpirationTime = renderExpirationTime), - null !== alternate && - alternate.childExpirationTime < renderExpirationTime && - (alternate.childExpirationTime = renderExpirationTime); - else if ( - null !== alternate && - alternate.childExpirationTime < renderExpirationTime - ) - alternate.childExpirationTime = renderExpirationTime; - else break; + if ((parent.childLanes & renderLanes) === renderLanes) + if ( + null === alternate || + (alternate.childLanes & renderLanes) === renderLanes + ) + break; + else alternate.childLanes |= renderLanes; + else + (parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes); parent = parent.return; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextWithAllBitsObserved = lastContextDependency = null; workInProgress = workInProgress.dependencies; null !== workInProgress && null !== workInProgress.firstContext && - (workInProgress.expirationTime >= renderExpirationTime && - (didReceiveUpdate = !0), + (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), (workInProgress.firstContext = null)); } function readContext(context, observedBits) { @@ -1928,7 +2160,7 @@ function readContext(context, observedBits) { ); lastContextDependency = observedBits; currentlyRenderingFiber.dependencies = { - expirationTime: 0, + lanes: 0, firstContext: observedBits, responders: null }; @@ -1940,7 +2172,8 @@ var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, effects: null }; @@ -1950,21 +2183,21 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue === current && (workInProgress.updateQueue = { baseState: current.baseState, - baseQueue: current.baseQueue, + firstBaseUpdate: current.firstBaseUpdate, + lastBaseUpdate: current.lastBaseUpdate, shared: current.shared, effects: current.effects }); } -function createUpdate(expirationTime, suspenseConfig) { - expirationTime = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, +function createUpdate(eventTime, lane) { + return { + eventTime: eventTime, + lane: lane, tag: 0, payload: null, callback: null, next: null }; - return (expirationTime.next = expirationTime); } function enqueueUpdate(fiber, update) { fiber = fiber.updateQueue; @@ -1977,132 +2210,177 @@ function enqueueUpdate(fiber, update) { fiber.pending = update; } } -function enqueueCapturedUpdate(workInProgress, update) { - var current = workInProgress.alternate; - null !== current && cloneUpdateQueue(current, workInProgress); - workInProgress = workInProgress.updateQueue; - current = workInProgress.baseQueue; - null === current - ? ((workInProgress.baseQueue = update.next = update), - (update.next = update)) - : ((update.next = current.next), (current.next = update)); +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + var queue = workInProgress.updateQueue, + current = workInProgress.alternate; + if ( + null !== current && + ((current = current.updateQueue), queue === current) + ) { + var newFirst = null, + newLast = null; + queue = queue.firstBaseUpdate; + if (null !== queue) { + do { + var clone = { + eventTime: queue.eventTime, + lane: queue.lane, + tag: queue.tag, + payload: queue.payload, + callback: queue.callback, + next: null + }; + null === newLast + ? (newFirst = newLast = clone) + : (newLast = newLast.next = clone); + queue = queue.next; + } while (null !== queue); + null === newLast + ? (newFirst = newLast = capturedUpdate) + : (newLast = newLast.next = capturedUpdate); + } else newFirst = newLast = capturedUpdate; + queue = { + baseState: current.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: current.shared, + effects: current.effects + }; + workInProgress.updateQueue = queue; + return; + } + workInProgress = queue.lastBaseUpdate; + null === workInProgress + ? (queue.firstBaseUpdate = capturedUpdate) + : (workInProgress.next = capturedUpdate); + queue.lastBaseUpdate = capturedUpdate; } function processUpdateQueue( workInProgress$jscomp$0, props, instance, - renderExpirationTime + renderLanes ) { var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; - var baseQueue = queue.baseQueue, + var firstBaseUpdate = queue.firstBaseUpdate, + lastBaseUpdate = queue.lastBaseUpdate, pendingQueue = queue.shared.pending; if (null !== pendingQueue) { - if (null !== baseQueue) { - var baseFirst = baseQueue.next; - baseQueue.next = pendingQueue.next; - pendingQueue.next = baseFirst; - } - baseQueue = pendingQueue; queue.shared.pending = null; - baseFirst = workInProgress$jscomp$0.alternate; - null !== baseFirst && - ((baseFirst = baseFirst.updateQueue), - null !== baseFirst && (baseFirst.baseQueue = pendingQueue)); + var lastPendingUpdate = pendingQueue, + firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; + null === lastBaseUpdate + ? (firstBaseUpdate = firstPendingUpdate) + : (lastBaseUpdate.next = firstPendingUpdate); + lastBaseUpdate = lastPendingUpdate; + var current = workInProgress$jscomp$0.alternate; + if (null !== current) { + current = current.updateQueue; + var currentLastBaseUpdate = current.lastBaseUpdate; + currentLastBaseUpdate !== lastBaseUpdate && + (null === currentLastBaseUpdate + ? (current.firstBaseUpdate = firstPendingUpdate) + : (currentLastBaseUpdate.next = firstPendingUpdate), + (current.lastBaseUpdate = lastPendingUpdate)); + } } - if (null !== baseQueue) { - baseFirst = baseQueue.next; - var newState = queue.baseState, - newExpirationTime = 0, - newBaseState = null, - newBaseQueueFirst = null, - newBaseQueueLast = null; - if (null !== baseFirst) { - var update = baseFirst; - do { - pendingQueue = update.expirationTime; - if (pendingQueue < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, + if (null !== firstBaseUpdate) { + currentLastBaseUpdate = queue.baseState; + lastBaseUpdate = 0; + current = firstPendingUpdate = lastPendingUpdate = null; + do { + pendingQueue = firstBaseUpdate.lane; + var updateEventTime = firstBaseUpdate.eventTime; + if ((renderLanes & pendingQueue) === pendingQueue) { + null !== current && + (current = current.next = { + eventTime: updateEventTime, + lane: 0, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, next: null - }; - null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone), - (newBaseState = newState)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - pendingQueue > newExpirationTime && - (newExpirationTime = pendingQueue); - } else { - null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }); - markRenderEventTimeAndConfig(pendingQueue, update.suspenseConfig); - a: { - var workInProgress = workInProgress$jscomp$0, - update$jscomp$0 = update; - pendingQueue = props; - clone = instance; - switch (update$jscomp$0.tag) { - case 1: - workInProgress = update$jscomp$0.payload; - if ("function" === typeof workInProgress) { - newState = workInProgress.call(clone, newState, pendingQueue); - break a; - } - newState = workInProgress; - break a; - case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; - case 0: - workInProgress = update$jscomp$0.payload; - pendingQueue = - "function" === typeof workInProgress - ? workInProgress.call(clone, newState, pendingQueue) - : workInProgress; - if (null === pendingQueue || void 0 === pendingQueue) break a; - newState = Object.assign({}, newState, pendingQueue); + }); + a: { + var workInProgress = workInProgress$jscomp$0, + update = firstBaseUpdate; + pendingQueue = props; + updateEventTime = instance; + switch (update.tag) { + case 1: + workInProgress = update.payload; + if ("function" === typeof workInProgress) { + currentLastBaseUpdate = workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ); break a; - case 2: - hasForceUpdate = !0; - } + } + currentLastBaseUpdate = workInProgress; + break a; + case 3: + workInProgress.flags = (workInProgress.flags & -8193) | 64; + case 0: + workInProgress = update.payload; + pendingQueue = + "function" === typeof workInProgress + ? workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ) + : workInProgress; + if (null === pendingQueue || void 0 === pendingQueue) break a; + currentLastBaseUpdate = Object.assign( + {}, + currentLastBaseUpdate, + pendingQueue + ); + break a; + case 2: + hasForceUpdate = !0; } - null !== update.callback && - ((workInProgress$jscomp$0.effectTag |= 32), - (pendingQueue = queue.effects), - null === pendingQueue - ? (queue.effects = [update]) - : pendingQueue.push(update)); } - update = update.next; - if (null === update || update === baseFirst) - if (((pendingQueue = queue.shared.pending), null === pendingQueue)) - break; - else - (update = baseQueue.next = pendingQueue.next), - (pendingQueue.next = baseFirst), - (queue.baseQueue = baseQueue = pendingQueue), - (queue.shared.pending = null); - } while (1); - } - null === newBaseQueueLast - ? (newBaseState = newState) - : (newBaseQueueLast.next = newBaseQueueFirst); - queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; - markUnprocessedUpdateTime(newExpirationTime); - workInProgress$jscomp$0.expirationTime = newExpirationTime; - workInProgress$jscomp$0.memoizedState = newState; + null !== firstBaseUpdate.callback && + ((workInProgress$jscomp$0.flags |= 32), + (pendingQueue = queue.effects), + null === pendingQueue + ? (queue.effects = [firstBaseUpdate]) + : pendingQueue.push(firstBaseUpdate)); + } else + (updateEventTime = { + eventTime: updateEventTime, + lane: pendingQueue, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, + next: null + }), + null === current + ? ((firstPendingUpdate = current = updateEventTime), + (lastPendingUpdate = currentLastBaseUpdate)) + : (current = current.next = updateEventTime), + (lastBaseUpdate |= pendingQueue); + firstBaseUpdate = firstBaseUpdate.next; + if (null === firstBaseUpdate) + if (((pendingQueue = queue.shared.pending), null === pendingQueue)) + break; + else + (firstBaseUpdate = pendingQueue.next), + (pendingQueue.next = null), + (queue.lastBaseUpdate = pendingQueue), + (queue.shared.pending = null); + } while (1); + null === current && (lastPendingUpdate = currentLastBaseUpdate); + queue.baseState = lastPendingUpdate; + queue.firstBaseUpdate = firstPendingUpdate; + queue.lastBaseUpdate = current; + workInProgressRootSkippedLanes |= lastBaseUpdate; + workInProgress$jscomp$0.lanes = lastBaseUpdate; + workInProgress$jscomp$0.memoizedState = currentLastBaseUpdate; } } function commitUpdateQueue(finishedWork, finishedQueue, instance) { @@ -2127,8 +2405,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2142,54 +2419,45 @@ function applyDerivedStateFromProps( ? ctor : Object.assign({}, ctor, getDerivedStateFromProps); workInProgress.memoizedState = getDerivedStateFromProps; - 0 === workInProgress.expirationTime && + 0 === workInProgress.lanes && (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { isMounted: function(component) { - return (component = component._reactInternalFiber) + return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, enqueueSetState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); } }; function checkShouldComponentUpdate( @@ -2227,7 +2495,7 @@ function constructClassInstance(workInProgress, ctor, props) { null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; ctor.updater = classComponentUpdater; workInProgress.stateNode = ctor; - ctor._reactInternalFiber = workInProgress; + ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), @@ -2248,12 +2516,7 @@ function callComponentWillReceiveProps( instance.state !== workInProgress && classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; instance.props = newProps; instance.state = workInProgress.memoizedState; @@ -2266,7 +2529,7 @@ function mountClassInstance( ? previousContext : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && @@ -2283,15 +2546,10 @@ function mountClassInstance( instance.UNSAFE_componentWillMount(), ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ), + processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2306,7 +2564,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2340,7 +2598,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2352,7 +2610,7 @@ function throwOnInvalidObjectType(returnFiber, newChild) { ("[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + "). If you meant to render a collection of children, use an array instead." ); } function ChildReconciler(shouldTrackSideEffects) { @@ -2364,7 +2622,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2396,26 +2654,22 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (null === current || 6 !== current.tag) return ( - (current = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromText(textContent, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2423,27 +2677,27 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (null !== current && current.elementType === element.type) return ( - (expirationTime = useFiber(current, element.props)), - (expirationTime.ref = coerceRef(returnFiber, current, element)), - (expirationTime.return = returnFiber), - expirationTime + (lanes = useFiber(current, element.props)), + (lanes.ref = coerceRef(returnFiber, current, element)), + (lanes.return = returnFiber), + lanes ); - expirationTime = createFiberFromTypeAndProps( + lanes = createFiberFromTypeAndProps( element.type, element.key, element.props, null, returnFiber.mode, - expirationTime + lanes ); - expirationTime.ref = coerceRef(returnFiber, current, element); - expirationTime.return = returnFiber; - return expirationTime; + lanes.ref = coerceRef(returnFiber, current, element); + lanes.return = returnFiber; + return lanes; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( null === current || 4 !== current.tag || @@ -2451,11 +2705,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) return ( - (current = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromPortal(portal, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2463,13 +2713,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (null === current || 7 !== current.tag) return ( (current = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key )), (current.return = returnFiber), @@ -2479,13 +2729,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (newChild = createFiberFromText( "" + newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2494,24 +2744,24 @@ function ChildReconciler(shouldTrackSideEffects) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: return ( - (expirationTime = createFiberFromTypeAndProps( + (lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef(returnFiber, null, newChild)), - (expirationTime.return = returnFiber), - expirationTime + (lanes.ref = coerceRef(returnFiber, null, newChild)), + (lanes.return = returnFiber), + lanes ); case REACT_PORTAL_TYPE: return ( (newChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2522,7 +2772,7 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null )), (newChild.return = returnFiber), @@ -2532,12 +2782,12 @@ function ChildReconciler(shouldTrackSideEffects) { } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { var key = null !== oldFiber ? oldFiber.key : null; if ("string" === typeof newChild || "number" === typeof newChild) return null !== key ? null - : updateTextNode(returnFiber, oldFiber, "" + newChild, expirationTime); + : updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: @@ -2547,26 +2797,20 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ) - : updateElement(returnFiber, oldFiber, newChild, expirationTime) + : updateElement(returnFiber, oldFiber, newChild, lanes) : null; case REACT_PORTAL_TYPE: return newChild.key === key - ? updatePortal(returnFiber, oldFiber, newChild, expirationTime) + ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; } if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null - : updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + : updateFragment(returnFiber, oldFiber, newChild, lanes, null); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2576,17 +2820,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateTextNode( - returnFiber, - existingChildren, - "" + newChild, - expirationTime - ) + updateTextNode(returnFiber, existingChildren, "" + newChild, lanes) ); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { @@ -2601,15 +2840,10 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, existingChildren, newChild.props.children, - expirationTime, + lanes, newChild.key ) - : updateElement( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + : updateElement(returnFiber, existingChildren, newChild, lanes) ); case REACT_PORTAL_TYPE: return ( @@ -2617,24 +2851,13 @@ function ChildReconciler(shouldTrackSideEffects) { existingChildren.get( null === newChild.key ? newIdx : newChild.key ) || null), - updatePortal( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + updatePortal(returnFiber, existingChildren, newChild, lanes) ); } if (isArray(newChild) || getIteratorFn(newChild)) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateFragment( - returnFiber, - existingChildren, - newChild, - expirationTime, - null - ) + updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); throwOnInvalidObjectType(returnFiber, newChild); } @@ -2644,7 +2867,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { for ( var resultingFirstChild = null, @@ -2662,7 +2885,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); @@ -2685,11 +2908,7 @@ function ChildReconciler(shouldTrackSideEffects) { ); if (null === oldFiber) { for (; newIdx < newChildren.length; newIdx++) - (oldFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - )), + (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && ((currentFirstChild = placeChild( oldFiber, @@ -2712,7 +2931,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes )), null !== nextOldFiber && (shouldTrackSideEffects && @@ -2739,7 +2958,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { var iteratorFn = getIteratorFn(newChildrenIterable); if ("function" !== typeof iteratorFn) @@ -2761,12 +2980,7 @@ function ChildReconciler(shouldTrackSideEffects) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) : (nextOldFiber = oldFiber.sibling); - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); break; @@ -2786,7 +3000,7 @@ function ChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) - (step = createChild(returnFiber, step.value, expirationTime)), + (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber @@ -2800,13 +3014,7 @@ function ChildReconciler(shouldTrackSideEffects) { !step.done; newIdx++, step = newChildrenIterable.next() ) - (step = updateFromMap( - oldFiber, - returnFiber, - newIdx, - step.value, - expirationTime - )), + (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && (shouldTrackSideEffects && null !== step.alternate && @@ -2822,7 +3030,7 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, expirationTime) { + return function(returnFiber, currentFirstChild, newChild, lanes) { var isUnkeyedTopLevelFragment = "object" === typeof newChild && null !== newChild && @@ -2888,26 +3096,26 @@ function ChildReconciler(shouldTrackSideEffects) { ? ((currentFirstChild = createFiberFromFragment( newChild.props.children, returnFiber.mode, - expirationTime, + lanes, newChild.key )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) - : ((expirationTime = createFiberFromTypeAndProps( + : ((lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef( + (lanes.ref = coerceRef( returnFiber, currentFirstChild, newChild )), - (expirationTime.return = returnFiber), - (returnFiber = expirationTime)); + (lanes.return = returnFiber), + (returnFiber = lanes)); } return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: @@ -2946,7 +3154,7 @@ function ChildReconciler(shouldTrackSideEffects) { currentFirstChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); currentFirstChild.return = returnFiber; returnFiber = currentFirstChild; @@ -2965,7 +3173,7 @@ function ChildReconciler(shouldTrackSideEffects) { (currentFirstChild = createFiberFromText( newChild, returnFiber.mode, - expirationTime + lanes )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)), @@ -2976,25 +3184,26 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); if (getIteratorFn(newChild)) return reconcileChildrenIterator( returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); isObject && throwOnInvalidObjectType(returnFiber, newChild); if ("undefined" === typeof newChild && !isUnkeyedTopLevelFragment) switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3002,9 +3211,9 @@ function ChildReconciler(shouldTrackSideEffects) { var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), NO_CONTEXT = {}, - contextStackCursor$1 = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + contextStackCursor$1 = createCursor(NO_CONTEXT), + contextFiberStackCursor = createCursor(NO_CONTEXT), + rootInstanceStackCursor = createCursor(NO_CONTEXT); function requiredContext(c) { if (c === NO_CONTEXT) throw Error( @@ -3027,26 +3236,26 @@ function popHostContainer() { function pushHostContext(fiber) { requiredContext(rootInstanceStackCursor.current); var context = requiredContext(contextStackCursor$1.current); - var nextContext = fiber.type; - nextContext = - "AndroidTextInput" === nextContext || - "RCTMultilineTextInputView" === nextContext || - "RCTSinglelineTextInputView" === nextContext || - "RCTText" === nextContext || - "RCTVirtualText" === nextContext; - nextContext = - context.isInAParentText !== nextContext - ? { isInAParentText: nextContext } + var JSCompiler_inline_result = fiber.type; + JSCompiler_inline_result = + "AndroidTextInput" === JSCompiler_inline_result || + "RCTMultilineTextInputView" === JSCompiler_inline_result || + "RCTSinglelineTextInputView" === JSCompiler_inline_result || + "RCTText" === JSCompiler_inline_result || + "RCTVirtualText" === JSCompiler_inline_result; + JSCompiler_inline_result = + context.isInAParentText !== JSCompiler_inline_result + ? { isInAParentText: JSCompiler_inline_result } : context; - context !== nextContext && + context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, nextContext)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && (pop(contextStackCursor$1), pop(contextFiberStackCursor)); } -var suspenseStackCursor = { current: 0 }; +var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { for (var node = row; null !== node; ) { if (13 === node.tag) { @@ -3054,7 +3263,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim$1() || shim$1())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3070,19 +3279,23 @@ function findFirstSuspended(row) { } return null; } -function createDeprecatedResponderListener(responder, props) { - return { responder: responder, props: props }; +var workInProgressSources = []; +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) + workInProgressSources[i]._workInProgressVersionSecondary = null; + workInProgressSources.length = 0; } -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig, - renderExpirationTime = 0, + renderLanes = 0, currentlyRenderingFiber$1 = null, currentHook = null, workInProgressHook = null, - didScheduleRenderPhaseUpdate = !1; + didScheduleRenderPhaseUpdate = !1, + didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3097,36 +3310,36 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = 0; - ReactCurrentDispatcher.current = + workInProgress.lanes = 0; + ReactCurrentDispatcher$1.current = null === current || null === current.memoizedState ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; current = Component(props, secondArg); - if (workInProgress.expirationTime === renderExpirationTime) { - nextRenderExpirationTime = 0; + if (didScheduleRenderPhaseUpdateDuringThisPass) { + nextRenderLanes = 0; do { - workInProgress.expirationTime = 0; - if (!(25 > nextRenderExpirationTime)) + didScheduleRenderPhaseUpdateDuringThisPass = !1; + if (!(25 > nextRenderLanes)) throw Error( "Too many re-renders. React limits the number of renders to prevent an infinite loop." ); - nextRenderExpirationTime += 1; + nextRenderLanes += 1; workInProgressHook = currentHook = null; workInProgress.updateQueue = null; - ReactCurrentDispatcher.current = HooksDispatcherOnRerender; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerender; current = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; workInProgress = null !== currentHook && null !== currentHook.next; - renderExpirationTime = 0; + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; didScheduleRenderPhaseUpdate = !1; if (workInProgress) @@ -3207,40 +3420,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var updateExpirationTime = update.expirationTime; - if (updateExpirationTime < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }; - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - updateExpirationTime > currentlyRenderingFiber$1.expirationTime && - ((currentlyRenderingFiber$1.expirationTime = updateExpirationTime), - markUnprocessedUpdateTime(updateExpirationTime)); - } else + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) null !== newBaseQueueLast && (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ), (current = update.eagerReducer === reducer ? update.eagerState : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3277,6 +3484,114 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + var getVersion = source._getVersion; + getVersion = getVersion(source._source); + var JSCompiler_inline_result = source._workInProgressVersionSecondary; + if (null !== JSCompiler_inline_result) + root = JSCompiler_inline_result === getVersion; + else if ( + ((root = root.mutableReadLanes), (root = (renderLanes & root) === root)) + ) + (source._workInProgressVersionSecondary = getVersion), + workInProgressSources.push(source); + if (root) return getSnapshot(source._source); + workInProgressSources.push(source); + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); +} +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + var getVersion = source._getVersion, + version = getVersion(source._source), + dispatcher = ReactCurrentDispatcher$1.current, + _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + setSnapshot = _dispatcher$useState[1], + snapshot = _dispatcher$useState[0]; + _dispatcher$useState = workInProgressHook; + var memoizedState = hook.memoizedState, + refs = memoizedState.refs, + prevGetSnapshot = refs.getSnapshot, + prevSource = memoizedState.source; + memoizedState = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { refs: refs, source: source, subscribe: subscribe }; + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; + refs.setSnapshot = setSnapshot; + var maybeNewVersion = getVersion(source._source); + if (!objectIs(version, maybeNewVersion)) { + maybeNewVersion = getSnapshot(source._source); + objectIs(snapshot, maybeNewVersion) || + (setSnapshot(maybeNewVersion), + (maybeNewVersion = requestUpdateLane(fiber)), + (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); + maybeNewVersion = root.mutableReadLanes; + root.entangledLanes |= maybeNewVersion; + for ( + var entanglements = root.entanglements, lanes = maybeNewVersion; + 0 < lanes; + + ) { + var index$11 = 31 - clz32(lanes), + lane = 1 << index$11; + entanglements[index$11] |= maybeNewVersion; + lanes &= ~lane; + } + } + }, + [getSnapshot, source, subscribe] + ); + dispatcher.useEffect( + function() { + return subscribe(source._source, function() { + var latestGetSnapshot = refs.getSnapshot, + latestSetSnapshot = refs.setSnapshot; + try { + latestSetSnapshot(latestGetSnapshot(source._source)); + var lane = requestUpdateLane(fiber); + root.mutableReadLanes |= lane & root.pendingLanes; + } catch (error) { + latestSetSnapshot(function() { + throw error; + }); + } + }); + }, + [source, subscribe] + ); + (objectIs(prevGetSnapshot, getSnapshot) && + objectIs(prevSource, source) && + objectIs(memoizedState, subscribe)) || + ((hook = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }), + (hook.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + hook + )), + (_dispatcher$useState.queue = hook), + (_dispatcher$useState.baseQueue = null), + (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); + return snapshot; +} +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} function mountState(initialState) { var hook = mountWorkInProgressHook(); "function" === typeof initialState && (initialState = initialState()); @@ -3313,17 +3628,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3331,12 +3646,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3375,13 +3690,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3409,65 +3717,60 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, fiber, suspenseConfig); - suspenseConfig = { - expirationTime: currentTime, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + var eventTime = requestEventTime(), + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || (null !== pending && pending === currentlyRenderingFiber$1) ) - (didScheduleRenderPhaseUpdate = !0), - (suspenseConfig.expirationTime = renderExpirationTime), - (currentlyRenderingFiber$1.expirationTime = renderExpirationTime); + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = !0; else { if ( - 0 === fiber.expirationTime && - (null === pending || 0 === pending.expirationTime) && + 0 === fiber.lanes && + (null === pending || 0 === pending.lanes) && ((pending = queue.lastRenderedReducer), null !== pending) ) try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { } - scheduleWork(fiber, currentTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function updateEventListener() {} var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -3480,14 +3783,21 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: !1 }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3533,39 +3843,44 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; + }, + useMutableSource: function(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { getSnapshot: getSnapshot, setSnapshot: null }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); }, - useEvent: function() {} + useOpaqueIdentifier: function() { + throw Error("Not yet implemented"); + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnUpdate = { readContext: readContext, @@ -3581,39 +3896,33 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return updateReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnRerender = { readContext: readContext, @@ -3629,39 +3938,33 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return rerenderReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, now$1 = Scheduler.unstable_now, commitTime = 0, @@ -3674,27 +3977,21 @@ function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { profilerStartTime = -1; } } +function transferActualDuration(fiber) { + for (var child = fiber.child; child; ) + (fiber.actualDuration += child.actualDuration), (child = child.sibling); +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { workInProgress.child = null === current - ? mountChildFibers( - workInProgress, - null, - nextChildren, - renderExpirationTime - ) + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } function updateForwardRef( @@ -3702,33 +3999,28 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { Component = Component.render; var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, nextProps, ref, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, nextProps, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } function updateMemoComponent( @@ -3736,8 +4028,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (null === current) { var type = Component.type; @@ -3756,17 +4048,17 @@ function updateMemoComponent( workInProgress, type, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); current = createFiberFromTypeAndProps( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3774,19 +4066,14 @@ function updateMemoComponent( } type = current.child; if ( - updateExpirationTime < renderExpirationTime && - ((updateExpirationTime = type.memoizedProps), + 0 === (updateLanes & renderLanes) && + ((updateLanes = type.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps) && - current.ref === workInProgress.ref) + Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3797,26 +4084,64 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { - return null !== current && + if ( + null !== current && shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref && - ((didReceiveUpdate = !1), updateExpirationTime < renderExpirationTime) - ? ((workInProgress.expirationTime = current.expirationTime), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - )) - : updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderExpirationTime + current.ref === workInProgress.ref + ) + if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, + nextChildren = nextProps.children, + prevState = null !== current ? current.memoizedState : null; + if ( + "hidden" === nextProps.mode || + "unstable-defer-without-hiding" === nextProps.mode + ) + if (0 === (workInProgress.mode & 4)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes(workInProgress, renderLanes); + else if (0 !== (renderLanes & 1073741824)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes( + workInProgress, + null !== prevState ? prevState.baseLanes : renderLanes + ); + else + return ( + (current = + null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), + markSpawnedWork(1073741824), + (workInProgress.lanes = workInProgress.childLanes = 1073741824), + (workInProgress.memoizedState = { baseLanes: current }), + pushRenderLanes(workInProgress, current), + null + ); + else + null !== prevState + ? ((nextProps = prevState.baseLanes | renderLanes), + (workInProgress.memoizedState = null)) + : (nextProps = renderLanes), + pushRenderLanes(workInProgress, nextProps); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } function markRef(current, workInProgress) { var ref = workInProgress.ref; @@ -3824,42 +4149,37 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { var context = isContextProvider(Component) ? previousContext : contextStackCursor.current; context = getMaskedContext(workInProgress, context); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); Component = renderWithHooks( current, workInProgress, Component, nextProps, context, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, Component, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } function updateClassComponent( @@ -3867,25 +4187,20 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (isContextProvider(Component)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ), + mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); else if (null === current) { var instance = workInProgress.stateNode, @@ -3916,12 +4231,7 @@ function updateClassComponent( hasForceUpdate = !1; var oldState = workInProgress.memoizedState; instance.state = oldState; - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -3954,9 +4264,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -3964,119 +4274,113 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); - } else - (instance = workInProgress.stateNode), - cloneUpdateQueue(current, workInProgress), - (oldProps = workInProgress.memoizedProps), - (instance.props = - workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps)), - (oldContext = instance.context), - (contextType = Component.contextType), - "object" === typeof contextType && null !== contextType - ? (contextType = readContext(contextType)) - : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), - (contextType = getMaskedContext(workInProgress, contextType))), - (getDerivedStateFromProps = Component.getDerivedStateFromProps), - (hasNewLifecycles = - "function" === typeof getDerivedStateFromProps || - "function" === typeof instance.getSnapshotBeforeUpdate) || - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || - ((oldProps !== nextProps || oldContext !== contextType) && - callComponentWillReceiveProps( + } else { + instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + oldProps = workInProgress.memoizedProps; + contextType = + workInProgress.type === workInProgress.elementType + ? oldProps + : resolveDefaultProps(workInProgress.type, oldProps); + instance.props = contextType; + hasNewLifecycles = workInProgress.pendingProps; + oldState = instance.context; + oldContext = Component.contextType; + "object" === typeof oldContext && null !== oldContext + ? (oldContext = readContext(oldContext)) + : ((oldContext = isContextProvider(Component) + ? previousContext + : contextStackCursor.current), + (oldContext = getMaskedContext(workInProgress, oldContext))); + var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; + (getDerivedStateFromProps = + "function" === typeof getDerivedStateFromProps$jscomp$0 || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || + ((oldProps !== hasNewLifecycles || oldState !== oldContext) && + callComponentWillReceiveProps( + workInProgress, + instance, + nextProps, + oldContext + )); + hasForceUpdate = !1; + oldState = workInProgress.memoizedState; + instance.state = oldState; + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + var newState = workInProgress.memoizedState; + oldProps !== hasNewLifecycles || + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate + ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && + (applyDerivedStateFromProps( workInProgress, - instance, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), + (newState = workInProgress.memoizedState)), + (contextType = + hasForceUpdate || + checkShouldComponentUpdate( + workInProgress, + Component, + contextType, nextProps, - contextType - )), - (hasForceUpdate = !1), - (oldContext = workInProgress.memoizedState), - (instance.state = oldContext), - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ), - (oldState = workInProgress.memoizedState), - oldProps !== nextProps || - oldContext !== oldState || - didPerformWorkStackCursor.current || - hasForceUpdate - ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), - (oldState = workInProgress.memoizedState)), - (getDerivedStateFromProps = - hasForceUpdate || - checkShouldComponentUpdate( - workInProgress, - Component, - oldProps, - nextProps, - oldContext, - oldState, - contextType - )) - ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - nextProps, - oldState, - contextType - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - oldState, - contextType - )), - "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), - "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (workInProgress.memoizedProps = nextProps), - (workInProgress.memoizedState = oldState)), - (instance.props = nextProps), - (instance.state = oldState), - (instance.context = contextType), - (nextProps = getDerivedStateFromProps)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (nextProps = !1)); + oldState, + newState, + oldContext + )) + ? (getDerivedStateFromProps || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), + "function" === typeof instance.UNSAFE_componentWillUpdate && + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), + "function" === typeof instance.componentDidUpdate && + (workInProgress.flags |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.flags |= 256)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (workInProgress.memoizedProps = nextProps), + (workInProgress.memoizedState = newState)), + (instance.props = nextProps), + (instance.state = newState), + (instance.context = oldContext), + (nextProps = contextType)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (nextProps = !1)); + } return finishClassComponent( current, workInProgress, Component, nextProps, hasContext, - renderExpirationTime + renderLanes ); } function finishClassComponent( @@ -4085,18 +4389,14 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); shouldUpdate = workInProgress.stateNode; ReactCurrentOwner$1.current = workInProgress; @@ -4107,27 +4407,22 @@ function finishClassComponent( var nextChildren = null; profilerStartTime = -1; } else nextChildren = shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((didCaptureError = nextChildren), (workInProgress.child = reconcileChildFibers( workInProgress, current.child, null, - renderExpirationTime + renderLanes )), (workInProgress.child = reconcileChildFibers( workInProgress, null, didCaptureError, - renderExpirationTime + renderLanes ))) - : reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + : reconcileChildren(current, workInProgress, nextChildren, renderLanes); workInProgress.memoizedState = shouldUpdate.state; hasContext && invalidateContextProvider(workInProgress, Component, !0); return workInProgress.child; @@ -4144,169 +4439,227 @@ function pushHostRootContext(workInProgress) { pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } -var SUSPENDED_MARKER = { dehydrated: null, retryTime: 0 }; -function updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime -) { - var mode = workInProgress.mode, - nextProps = workInProgress.pendingProps, +var SUSPENDED_MARKER = { dehydrated: null, retryLane: 0 }; +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, - nextDidTimeout = !1, + showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = - 0 !== (suspenseContext & 2) && - (null === current || null !== current.memoizedState)); + null !== current && null === current.memoizedState + ? !1 + : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((nextDidTimeout = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + current = nextProps.children; + suspenseContext = nextProps.fallback; + if (showFallback) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - mode = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( - workInProgress, - null, - mode, - renderExpirationTime - )); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432), + current + ); + renderLanes = createFiberFromOffscreen( + { mode: "visible", children: current }, + workInProgress.mode, + renderLanes, + null + ); + renderLanes.return = workInProgress; + return (workInProgress.child = renderLanes); } if (null !== current.memoizedState) { - current = current.child; - mode = current.sibling; - if (nextDidTimeout) { - nextProps = nextProps.fallback; - renderExpirationTime = createWorkInProgress( - current, - current.pendingProps + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - if ( - 0 === (workInProgress.mode & 2) && - ((nextDidTimeout = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child), - nextDidTimeout !== current.child) - ) - for ( - renderExpirationTime.child = nextDidTimeout; - null !== nextDidTimeout; - - ) - (nextDidTimeout.return = renderExpirationTime), - (nextDidTimeout = nextDidTimeout.sibling); - if (workInProgress.mode & 8) { - nextDidTimeout = 0; - for (current = renderExpirationTime.child; null !== current; ) - (nextDidTimeout += current.treeBaseDuration), - (current = current.sibling); - renderExpirationTime.treeBaseDuration = nextDidTimeout; - } - mode = createWorkInProgress(mode, nextProps); - mode.return = workInProgress; - renderExpirationTime.sibling = mode; - renderExpirationTime.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = renderExpirationTime; - return mode; - } - renderExpirationTime = reconcileChildFibers( + renderLanes = updateSuspensePrimaryChildren( + current, workInProgress, - current.child, nextProps.children, - renderExpirationTime + renderLanes ); workInProgress.memoizedState = null; - return (workInProgress.child = renderExpirationTime); + return renderLanes; } - current = current.child; - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - nextProps.child = current; - null !== current && (current.return = nextProps); - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - if (workInProgress.mode & 8) { - current = 0; - for (suspenseContext = nextProps.child; null !== suspenseContext; ) - (current += suspenseContext.treeBaseDuration), - (suspenseContext = suspenseContext.sibling); - nextProps.treeBaseDuration = current; - } - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - renderExpirationTime.effectTag |= 2; - nextProps.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - workInProgress.memoizedState = null; - return (workInProgress.child = reconcileChildFibers( - workInProgress, + renderLanes = updateSuspensePrimaryChildren( current, + workInProgress, nextProps.children, - renderExpirationTime - )); + renderLanes + ); + workInProgress.memoizedState = null; + return renderLanes; } -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - fiber.expirationTime < renderExpirationTime && - (fiber.expirationTime = renderExpirationTime); +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren), + workInProgress.mode & 8 && + ((progressedPrimaryFragment.actualDuration = 0), + (progressedPrimaryFragment.actualStartTime = -1), + (progressedPrimaryFragment.selfBaseDuration = 0), + (progressedPrimaryFragment.treeBaseDuration = 0))) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + mode: "visible", + children: primaryChildren + }); + 0 === (workInProgress.mode & 2) && (primaryChildren.lanes = renderLanes); + primaryChildren.return = workInProgress; + primaryChildren.sibling = null; + null !== current && + ((current.nextEffect = null), + (current.flags = 8), + (workInProgress.firstEffect = workInProgress.lastEffect = current)); + return (workInProgress.child = primaryChildren); +} +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + var primaryChildProps = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && workInProgress.child !== currentPrimaryChildFragment + ? ((primaryChildren = workInProgress.child), + (primaryChildren.childLanes = 0), + (primaryChildren.pendingProps = primaryChildProps), + workInProgress.mode & 8 && + ((primaryChildren.actualDuration = 0), + (primaryChildren.actualStartTime = -1), + (primaryChildren.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration), + (primaryChildren.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration)), + (currentPrimaryChildFragment = primaryChildren.lastEffect), + null !== currentPrimaryChildFragment + ? ((workInProgress.firstEffect = primaryChildren.firstEffect), + (workInProgress.lastEffect = currentPrimaryChildFragment), + (currentPrimaryChildFragment.nextEffect = null)) + : (workInProgress.firstEffect = workInProgress.lastEffect = null)) + : (primaryChildren = createWorkInProgress( + currentPrimaryChildFragment, + primaryChildProps + )); + null !== current + ? (fallbackChildren = createWorkInProgress(current, fallbackChildren)) + : ((fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + )), + (fallbackChildren.flags |= 2)); + fallbackChildren.return = workInProgress; + primaryChildren.return = workInProgress; + primaryChildren.sibling = fallbackChildren; + workInProgress.child = primaryChildren; + return fallbackChildren; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes |= renderLanes; var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < renderExpirationTime && - (alternate.expirationTime = renderExpirationTime); - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + null !== alternate && (alternate.lanes |= renderLanes); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function initSuspenseListRenderState( workInProgress, @@ -4324,7 +4677,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4333,35 +4685,24 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, revealOrder = nextProps.revealOrder, tailMode = nextProps.tail; - reconcileChildren( - current, - workInProgress, - nextProps.children, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderExpirationTime); - else if (19 === current.tag) - scheduleWorkOnFiber(current, renderExpirationTime); + scheduleWorkOnFiber(current, renderLanes); + else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -4383,30 +4724,29 @@ function updateSuspenseListComponent( else switch (revealOrder) { case "forwards": - renderExpirationTime = workInProgress.child; - for (revealOrder = null; null !== renderExpirationTime; ) - (current = renderExpirationTime.alternate), + renderLanes = workInProgress.child; + for (revealOrder = null; null !== renderLanes; ) + (current = renderLanes.alternate), null !== current && null === findFirstSuspended(current) && - (revealOrder = renderExpirationTime), - (renderExpirationTime = renderExpirationTime.sibling); - renderExpirationTime = revealOrder; - null === renderExpirationTime + (revealOrder = renderLanes), + (renderLanes = renderLanes.sibling); + renderLanes = revealOrder; + null === renderLanes ? ((revealOrder = workInProgress.child), (workInProgress.child = null)) - : ((revealOrder = renderExpirationTime.sibling), - (renderExpirationTime.sibling = null)); + : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); initSuspenseListRenderState( workInProgress, !1, revealOrder, - renderExpirationTime, + renderLanes, tailMode, workInProgress.lastEffect ); break; case "backwards": - renderExpirationTime = null; + renderLanes = null; revealOrder = workInProgress.child; for (workInProgress.child = null; null !== revealOrder; ) { current = revealOrder.alternate; @@ -4415,14 +4755,14 @@ function updateSuspenseListComponent( break; } current = revealOrder.sibling; - revealOrder.sibling = renderExpirationTime; - renderExpirationTime = revealOrder; + revealOrder.sibling = renderLanes; + renderLanes = revealOrder; revealOrder = current; } initSuspenseListRenderState( workInProgress, !0, - renderExpirationTime, + renderLanes, null, tailMode, workInProgress.lastEffect @@ -4443,36 +4783,29 @@ function updateSuspenseListComponent( } return workInProgress.child; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); profilerStartTime = -1; - var updateExpirationTime = workInProgress.expirationTime; - 0 !== updateExpirationTime && markUnprocessedUpdateTime(updateExpirationTime); - if (workInProgress.childExpirationTime < renderExpirationTime) return null; - if (null !== current && workInProgress.child !== current.child) - throw Error("Resuming work not yet implemented."); - if (null !== workInProgress.child) { - current = workInProgress.child; - renderExpirationTime = createWorkInProgress(current, current.pendingProps); - workInProgress.child = renderExpirationTime; - for ( - renderExpirationTime.return = workInProgress; - null !== current.sibling; - - ) - (current = current.sibling), - (renderExpirationTime = renderExpirationTime.sibling = createWorkInProgress( - current, - current.pendingProps - )), - (renderExpirationTime.return = workInProgress); - renderExpirationTime.sibling = null; + workInProgressRootSkippedLanes |= workInProgress.lanes; + if (0 !== (renderLanes & workInProgress.childLanes)) { + if (null !== current && workInProgress.child !== current.child) + throw Error("Resuming work not yet implemented."); + if (null !== workInProgress.child) { + current = workInProgress.child; + renderLanes = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes; + for (renderLanes.return = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (renderLanes = renderLanes.sibling = createWorkInProgress( + current, + current.pendingProps + )), + (renderLanes.return = workInProgress); + renderLanes.sibling = null; + } + return workInProgress.child; } - return workInProgress.child; + return null; } var appendAllChildren, updateHostContainer, @@ -4499,7 +4832,7 @@ appendAllChildren = function( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4552,7 +4885,7 @@ function appendAllChildrenToContainer( } else if (4 !== node.tag) { if ( 13 === node.tag && - 0 !== (node.effectTag & 4) && + 0 !== (node.flags & 4) && (instance = null !== node.memoizedState) ) { var primaryChildParent = node.child; @@ -4596,7 +4929,7 @@ updateHostContainer = function(workInProgress) { newChildSet = createChildNodeSet(container); appendAllChildrenToContainer(newChildSet, workInProgress, !1, !1); portalOrRoot.pendingChildren = newChildSet; - workInProgress.effectTag |= 4; + workInProgress.flags |= 4; completeRoot(container, newChildSet); } }; @@ -4634,7 +4967,7 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { }), (workInProgress.stateNode = type), current - ? (workInProgress.effectTag |= 4) + ? (workInProgress.flags |= 4) : appendAllChildren(type, workInProgress, !1, !1)); } }; @@ -4648,7 +4981,7 @@ updateHostText$1 = function(current, workInProgress, oldText, newText) { oldText, workInProgress )), - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : (workInProgress.stateNode = current.stateNode); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { @@ -4665,17 +4998,17 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var _lastTailNode = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (_lastTailNode = lastTailNode), + for (var lastTailNode$65 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$65 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === _lastTailNode + null === lastTailNode$65 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (_lastTailNode.sibling = null); + : (lastTailNode$65.sibling = null); } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { case 2: @@ -4696,10 +5029,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { popHostContainer(), pop(didPerformWorkStackCursor), pop(contextStackCursor), - (current = workInProgress.stateNode), - current.pendingContext && - ((current.context = current.pendingContext), - (current.pendingContext = null)), + resetWorkInProgressVersions(), + (newProps = workInProgress.stateNode), + newProps.pendingContext && + ((newProps.context = newProps.pendingContext), + (newProps.pendingContext = null)), + (null !== current && null !== current.child) || + newProps.hydrate || + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4708,17 +5045,16 @@ function completeWork(current, workInProgress, renderExpirationTime) { var rootContainerInstance = requiredContext( rootInstanceStackCursor.current ); - renderExpirationTime = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) updateHostComponent$1( current, workInProgress, - renderExpirationTime, + renderLanes, newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -4730,30 +5066,30 @@ function completeWork(current, workInProgress, renderExpirationTime) { requiredContext(contextStackCursor$1.current); current = nextReactTag; nextReactTag += 2; - renderExpirationTime = getViewConfigForType(renderExpirationTime); + renderLanes = getViewConfigForType(renderLanes); var updatePayload = diffProperties( null, emptyObject, newProps, - renderExpirationTime.validAttributes + renderLanes.validAttributes ); rootContainerInstance = createNode( current, - renderExpirationTime.uiViewClassName, + renderLanes.uiViewClassName, rootContainerInstance, updatePayload, workInProgress ); current = new ReactFabricHostComponent( current, - renderExpirationTime, + renderLanes, newProps, workInProgress ); current = { node: rootContainerInstance, canonical: current }; appendAllChildren(current, workInProgress, !1, !1); workInProgress.stateNode = current; - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -4782,52 +5118,40 @@ function completeWork(current, workInProgress, renderExpirationTime) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return ( - (workInProgress.expirationTime = renderExpirationTime), workInProgress + (workInProgress.lanes = renderLanes), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), + workInProgress ); newProps = null !== newProps; rootContainerInstance = !1; null !== current && - ((renderExpirationTime = current.memoizedState), - (rootContainerInstance = null !== renderExpirationTime), - newProps || - null === renderExpirationTime || - ((renderExpirationTime = current.child.sibling), - null !== renderExpirationTime && - ((updatePayload = workInProgress.firstEffect), - null !== updatePayload - ? ((workInProgress.firstEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = updatePayload)) - : ((workInProgress.firstEffect = workInProgress.lastEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = null)), - (renderExpirationTime.effectTag = 8)))); + (rootContainerInstance = null !== current.memoizedState); if (newProps && !rootContainerInstance && 0 !== (workInProgress.mode & 2)) if ( (null === current && !0 !== workInProgress.memoizedProps.unstable_avoidThisFallback) || 0 !== (suspenseStackCursor.current & 1) ) - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootSuspended); + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3); else { if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended + 0 === workInProgressRootExitStatus || + 3 === workInProgressRootExitStatus ) - workInProgressRootExitStatus = RootSuspendedWithDelay; - 0 !== workInProgressRootNextUnprocessedUpdateTime && - null !== workInProgressRoot && - (markRootSuspendedAtTime( - workInProgressRoot, - renderExpirationTime$1 - ), - markRootUpdatedAtTime( + workInProgressRootExitStatus = 4; + null === workInProgressRoot || + (0 === (workInProgressRootSkippedLanes & 134217727) && + 0 === (workInProgressRootUpdatedLanes & 134217727)) || + markRootSuspended$1( workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime - )); + workInProgressRootRenderLanes + ); } - newProps && (workInProgress.effectTag |= 4); + newProps && (workInProgress.flags |= 4); return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -4839,71 +5163,70 @@ function completeWork(current, workInProgress, renderExpirationTime) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( - workInProgressRootExitStatus !== RootIncomplete || - (null !== current && 0 !== (current.effectTag & 64)) + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; - current = renderExpirationTime; + current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (updatePayload = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), - (renderExpirationTime = rootContainerInstance.alternate), - null === renderExpirationTime - ? ((rootContainerInstance.childExpirationTime = 0), - (rootContainerInstance.expirationTime = updatePayload), + (renderLanes = rootContainerInstance.alternate), + null === renderLanes + ? ((rootContainerInstance.childLanes = 0), + (rootContainerInstance.lanes = updatePayload), (rootContainerInstance.child = null), (rootContainerInstance.memoizedProps = null), (rootContainerInstance.memoizedState = null), (rootContainerInstance.updateQueue = null), (rootContainerInstance.dependencies = null), + (rootContainerInstance.stateNode = null), (rootContainerInstance.selfBaseDuration = 0), (rootContainerInstance.treeBaseDuration = 0)) - : ((rootContainerInstance.childExpirationTime = - renderExpirationTime.childExpirationTime), - (rootContainerInstance.expirationTime = - renderExpirationTime.expirationTime), - (rootContainerInstance.child = - renderExpirationTime.child), + : ((rootContainerInstance.childLanes = + renderLanes.childLanes), + (rootContainerInstance.lanes = renderLanes.lanes), + (rootContainerInstance.child = renderLanes.child), (rootContainerInstance.memoizedProps = - renderExpirationTime.memoizedProps), + renderLanes.memoizedProps), (rootContainerInstance.memoizedState = - renderExpirationTime.memoizedState), + renderLanes.memoizedState), (rootContainerInstance.updateQueue = - renderExpirationTime.updateQueue), - (updatePayload = renderExpirationTime.dependencies), + renderLanes.updateQueue), + (rootContainerInstance.type = renderLanes.type), + (updatePayload = renderLanes.dependencies), (rootContainerInstance.dependencies = null === updatePayload ? null : { - expirationTime: updatePayload.expirationTime, - firstContext: updatePayload.firstContext, - responders: updatePayload.responders + lanes: updatePayload.lanes, + firstContext: updatePayload.firstContext }), (rootContainerInstance.selfBaseDuration = - renderExpirationTime.selfBaseDuration), + renderLanes.selfBaseDuration), (rootContainerInstance.treeBaseDuration = - renderExpirationTime.treeBaseDuration)), + renderLanes.treeBaseDuration)), (newProps = newProps.sibling); push( suspenseStackCursor, @@ -4913,6 +5236,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); } else { if (!rootContainerInstance) @@ -4920,12 +5250,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -4938,16 +5268,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && - 1 < renderExpirationTime && - ((workInProgress.effectTag |= 64), + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (current = renderExpirationTime - 1), - (workInProgress.expirationTime = workInProgress.childExpirationTime = current), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [current]) - : spawnedWorkDuringRender.push(current)); + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -4958,9 +5286,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -4975,6 +5301,17 @@ function completeWork(current, workInProgress, renderExpirationTime) { ), current) : null; + case 22: + case 23: + return ( + popRenderLanes(), + null !== current && + (null !== current.memoizedState) !== + (null !== workInProgress.memoizedState) && + "unstable-defer-without-hiding" !== newProps.mode && + (workInProgress.flags |= 4), + null + ); } throw Error( "Unknown unit of work tag (" + @@ -4986,30 +5323,35 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + resetWorkInProgressVersions(); + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), workInProgress) : null ); @@ -5019,16 +5361,25 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: + case 23: + return popRenderLanes(), null; default: return null; } } function createCapturedValue(value, source) { - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source) - }; + try { + var info = "", + node = source; + do (info += describeFiber(node)), (node = node.return); + while (node); + var JSCompiler_inline_result = info; + } catch (x) { + JSCompiler_inline_result = + "\nError generating stack: " + x.message + "\n" + x.stack; + } + return { value: value, source: source, stack: JSCompiler_inline_result }; } if ( "function" !== @@ -5037,51 +5388,61 @@ if ( throw Error( "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); -function logCapturedError(capturedError) { - !1 !== - ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ) && console.error(capturedError.error); -} -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source, - stack = errorInfo.stack; - null === stack && - null !== source && - (stack = getStackByFiberInDevAndProd(source)); - errorInfo = { - componentName: null !== source ? getComponentName(source.type) : null, - componentStack: null !== stack ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: !1, - willRetry: !1 - }; - null !== boundary && - 1 === boundary.tag && - ((errorInfo.errorBoundary = boundary.stateNode), - (errorInfo.errorBoundaryName = getComponentName(boundary.type)), - (errorInfo.errorBoundaryFound = !0), - (errorInfo.willRetry = !0)); +function logCapturedError(boundary, errorInfo) { try { - logCapturedError(errorInfo); + !1 !== + ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog({ + componentStack: null !== errorInfo.stack ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + null !== boundary && 1 === boundary.tag ? boundary.stateNode : null + }) && console.error(errorInfo.value); } catch (e) { setTimeout(function() { throw e; }); } } -function safelyCallComponentWillUnmount(current, instance) { - try { - (instance.props = current.memoizedProps), - (instance.state = current.memoizedState), - instance.componentWillUnmount(); - } catch (unmountError) { - captureCommitPhaseError(current, unmountError); +var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; +function createRootErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + lane.payload = { element: null }; + var error = errorInfo.value; + lane.callback = function() { + hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); + logCapturedError(fiber, errorInfo); + }; + return lane; +} +function createClassErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if ("function" === typeof getDerivedStateFromError) { + var error = errorInfo.value; + lane.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error); + }; } + var inst = fiber.stateNode; + null !== inst && + "function" === typeof inst.componentDidCatch && + (lane.callback = function() { + "function" !== typeof getDerivedStateFromError && + (null === legacyErrorBoundariesThatAlreadyFailed + ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) + : legacyErrorBoundariesThatAlreadyFailed.add(this), + logCapturedError(fiber, errorInfo)); + var stack = errorInfo.stack; + this.componentDidCatch(errorInfo.value, { + componentStack: null !== stack ? stack : "" + }); + }); + return lane; } +var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; function safelyDetachRef(current) { var ref = current.ref; if (null !== ref) @@ -5098,10 +5459,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5115,6 +5475,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } return; case 3: + return; case 5: case 6: case 4: @@ -5125,58 +5486,56 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitHookEffectListUnmount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var destroy = effect.destroy; - effect.destroy = void 0; - void 0 !== destroy && destroy(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} -function commitHookEffectListMount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var create = effect.create; - effect.destroy = create(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} function commitLifeCycles(finishedRoot, current, finishedWork) { switch (finishedWork.tag) { case 0: case 11: case 15: - case 22: - commitHookEffectListMount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + if (3 === (finishedRoot.tag & 3)) { + var create$82 = finishedRoot.create; + finishedRoot.destroy = create$82(); + } + finishedRoot = finishedRoot.next; + } while (finishedRoot !== current); + } + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + var _effect = finishedRoot; + create$82 = _effect.next; + _effect = _effect.tag; + 0 !== (_effect & 4) && + 0 !== (_effect & 1) && + (enqueuePendingPassiveHookEffectUnmount(finishedWork, finishedRoot), + enqueuePendingPassiveHookEffectMount(finishedWork, finishedRoot)); + finishedRoot = create$82; + } while (finishedRoot !== current); + } return; case 1: finishedRoot = finishedWork.stateNode; - if (finishedWork.effectTag & 4) - if (null === current) finishedRoot.componentDidMount(); - else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - finishedRoot.componentDidUpdate( - prevProps, - current.memoizedState, - finishedRoot.__reactInternalSnapshotBeforeUpdate - ); - } + finishedWork.flags & 4 && + (null === current + ? finishedRoot.componentDidMount() + : ((create$82 = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps( + finishedWork.type, + current.memoizedProps + )), + finishedRoot.componentDidUpdate( + create$82, + current.memoizedState, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ))); current = finishedWork.updateQueue; null !== current && commitUpdateQueue(finishedWork, current, finishedRoot); @@ -5197,26 +5556,23 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { } return; case 5: - if (null === current && finishedWork.effectTag & 4) - throw Error( - "The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue." - ); + null === current && finishedWork.flags & 4 && shim(); return; case 6: return; case 4: return; case 12: - prevProps = finishedWork.memoizedProps.onRender; - var commitTime$jscomp$0 = commitTime; - "function" === typeof prevProps && - prevProps( + create$82 = finishedWork.memoizedProps.onRender; + _effect = commitTime; + "function" === typeof create$82 && + create$82( finishedWork.memoizedProps.id, null === current ? "mount" : "update", finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, - commitTime$jscomp$0, + _effect, finishedRoot.memoizedInteractions ); return; @@ -5226,74 +5582,25 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: + case 23: return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitUnmount(finishedRoot, current$jscomp$0, renderPriorityLevel) { - "function" === typeof onCommitFiberUnmount && - onCommitFiberUnmount(current$jscomp$0); - switch (current$jscomp$0.tag) { - case 0: - case 11: - case 14: - case 15: - case 22: - finishedRoot = current$jscomp$0.updateQueue; - if ( - null !== finishedRoot && - ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) - ) { - var firstEffect = finishedRoot.next; - runWithPriority( - 97 < renderPriorityLevel ? 97 : renderPriorityLevel, - function() { - var effect = firstEffect; - do { - var _destroy = effect.destroy; - if (void 0 !== _destroy) { - var current = current$jscomp$0; - try { - _destroy(); - } catch (error) { - captureCommitPhaseError(current, error); - } - } - effect = effect.next; - } while (effect !== firstEffect); - } - ); - } - break; - case 1: - safelyDetachRef(current$jscomp$0); - renderPriorityLevel = current$jscomp$0.stateNode; - "function" === typeof renderPriorityLevel.componentWillUnmount && - safelyCallComponentWillUnmount(current$jscomp$0, renderPriorityLevel); - break; - case 5: - safelyDetachRef(current$jscomp$0); - break; - case 4: - createChildNodeSet(current$jscomp$0.stateNode.containerInfo); - } -} -function detachFiber(current) { - var alternate = current.alternate; - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - null !== alternate && detachFiber(alternate); +function detachFiberMutation(fiber) { + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; } function commitWork(current, finishedWork) { switch (finishedWork.tag) { @@ -5301,8 +5608,19 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: - commitHookEffectListUnmount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedWork = current = current.next; + do { + if (3 === (finishedWork.tag & 3)) { + var destroy = finishedWork.destroy; + finishedWork.destroy = void 0; + void 0 !== destroy && destroy(); + } + finishedWork = finishedWork.next; + } while (finishedWork !== current); + } return; case 12: return; @@ -5314,6 +5632,9 @@ function commitWork(current, finishedWork) { case 19: attachSuspenseRetryListeners(finishedWork); return; + case 22: + case 23: + return; } a: { switch (finishedWork.tag) { @@ -5332,87 +5653,48 @@ function commitWork(current, finishedWork) { } } function attachSuspenseRetryListeners(finishedWork) { - var thenables = finishedWork.updateQueue; - if (null !== thenables) { + var wakeables = finishedWork.updateQueue; + if (null !== wakeables) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - thenables.forEach(function(thenable) { - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); - retryCache.has(thenable) || - (!0 !== thenable.__reactDoNotTraceInteractions && + wakeables.forEach(function(wakeable) { + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + retryCache.has(wakeable) || + (!0 !== wakeable.__reactDoNotTraceInteractions && (retry = tracing.unstable_wrap(retry)), - retryCache.add(thenable), - thenable.then(retry, retry)); + retryCache.add(wakeable), + wakeable.then(retry, retry)); }); } } -var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - expirationTime.payload = { element: null }; - var error = errorInfo.value; - expirationTime.callback = function() { - hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); - logError(fiber, errorInfo); - }; - return expirationTime; -} -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - if ("function" === typeof getDerivedStateFromError) { - var error = errorInfo.value; - expirationTime.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error); - }; - } - var inst = fiber.stateNode; - null !== inst && - "function" === typeof inst.componentDidCatch && - (expirationTime.callback = function() { - "function" !== typeof getDerivedStateFromError && - (null === legacyErrorBoundariesThatAlreadyFailed - ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) - : legacyErrorBoundariesThatAlreadyFailed.add(this), - logError(fiber, errorInfo)); - var stack = errorInfo.stack; - this.componentDidCatch(errorInfo.value, { - componentStack: null !== stack ? stack : "" - }); - }); - return expirationTime; +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + return null !== current && + ((current = current.memoizedState), + null === current || null !== current.dehydrated) + ? ((finishedWork = finishedWork.memoizedState), + null !== finishedWork && null === finishedWork.dehydrated) + : !1; } var ceil = Math.ceil, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - NoContext = 0, - LegacyUnbatchedContext = 8, - RenderContext = 16, - CommitContext = 32, - RootIncomplete = 0, - RootFatalErrored = 1, - RootErrored = 2, - RootSuspended = 3, - RootSuspendedWithDelay = 4, - RootCompleted = 5, - executionContext = NoContext, + executionContext = 0, workInProgressRoot = null, workInProgress = null, - renderExpirationTime$1 = 0, - workInProgressRootExitStatus = RootIncomplete, + workInProgressRootRenderLanes = 0, + subtreeRenderLanes = 0, + subtreeRenderLanesCursor = createCursor(0), + workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestProcessedExpirationTime = 1073741823, - workInProgressRootLatestSuspenseTimeout = 1073741823, - workInProgressRootCanSuspendUsingConfig = null, - workInProgressRootNextUnprocessedUpdateTime = 0, - workInProgressRootHasPendingPing = !1, + workInProgressRootIncludedLanes = 0, + workInProgressRootSkippedLanes = 0, + workInProgressRootUpdatedLanes = 0, + workInProgressRootPingedLanes = 0, + mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, - FALLBACK_THROTTLE_MS = 500, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5420,201 +5702,192 @@ var ceil = Math.ceil, rootDoesHavePassiveEffects = !1, rootWithPendingPassiveEffects = null, pendingPassiveEffectsRenderPriority = 90, - pendingPassiveEffectsExpirationTime = 0, + pendingPassiveEffectsLanes = 0, + pendingPassiveHookEffectsMount = [], + pendingPassiveHookEffectsUnmount = [], rootsWithPendingDiscreteUpdates = null, nestedUpdateCount = 0, rootWithNestedUpdates = null, spawnedWorkDuringRender = null, - currentEventTime = 0; -function requestCurrentTimeForUpdate() { - return (executionContext & (RenderContext | CommitContext)) !== NoContext - ? 1073741821 - ((now() / 10) | 0) - : 0 !== currentEventTime + currentEventTime = -1, + currentEventWipLanes = 0, + currentEventPendingLanes = 0, + focusedInstanceHandle = null, + shouldFireAfterActiveInstanceBlur = !1; +function requestEventTime() { + return 0 !== (executionContext & 48) + ? now() + : -1 !== currentEventTime ? currentEventTime - : (currentEventTime = 1073741821 - ((now() / 10) | 0)); + : (currentEventTime = now()); } -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; - if (0 === (fiber & 2)) return 1073741823; - var priorityLevel = getCurrentPriorityLevel(); - if (0 === (fiber & 4)) return 99 === priorityLevel ? 1073741823 : 1073741822; - if ((executionContext & RenderContext) !== NoContext) - return renderExpirationTime$1; - if (null !== suspenseConfig) - currentTime = - 1073741821 - - 25 * - ((((1073741821 - - currentTime + - (suspenseConfig.timeoutMs | 0 || 5e3) / 10) / - 25) | - 0) + - 1); - else - switch (priorityLevel) { - case 99: - currentTime = 1073741823; - break; - case 98: - currentTime = - 1073741821 - 10 * ((((1073741821 - currentTime + 15) / 10) | 0) + 1); - break; - case 97: - case 96: - currentTime = - 1073741821 - 25 * ((((1073741821 - currentTime + 500) / 25) | 0) + 1); - break; - case 95: - currentTime = 2; - break; - default: - throw Error("Expected a valid priority level"); - } - null !== workInProgressRoot && - currentTime === renderExpirationTime$1 && - --currentTime; - return currentTime; -} -function scheduleWork(fiber, expirationTime) { + if (0 === (fiber & 2)) return 1; + if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; + 0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes); + if (0 !== ReactCurrentBatchConfig.transition) { + 0 !== currentEventPendingLanes && + (currentEventPendingLanes = + null !== mostRecentlyUpdatedRoot + ? mostRecentlyUpdatedRoot.pendingLanes + : 0); + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; + } + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; +} +function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), (rootWithNestedUpdates = null), Error( "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." )); - fiber = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - if (null !== fiber) { - var priorityLevel = getCurrentPriorityLevel(); - 1073741823 === expirationTime - ? (executionContext & LegacyUnbatchedContext) !== NoContext && - (executionContext & (RenderContext | CommitContext)) === NoContext - ? (schedulePendingInteractions(fiber, expirationTime), - performSyncWorkOnRoot(fiber)) - : (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, expirationTime), - executionContext === NoContext && flushSyncCallbackQueue()) - : (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, expirationTime)); - (executionContext & 4) === NoContext || - (98 !== priorityLevel && 99 !== priorityLevel) || - (null === rootsWithPendingDiscreteUpdates - ? (rootsWithPendingDiscreteUpdates = new Map([[fiber, expirationTime]])) - : ((priorityLevel = rootsWithPendingDiscreteUpdates.get(fiber)), - (void 0 === priorityLevel || priorityLevel > expirationTime) && - rootsWithPendingDiscreteUpdates.set(fiber, expirationTime))); - } -} -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - fiber.expirationTime < expirationTime && - (fiber.expirationTime = expirationTime); - var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < expirationTime && - (alternate.expirationTime = expirationTime); - var node = fiber.return, - root = null; - if (null === node && 3 === fiber.tag) root = fiber.stateNode; - else - for (; null !== node; ) { - alternate = node.alternate; - node.childExpirationTime < expirationTime && - (node.childExpirationTime = expirationTime); - null !== alternate && - alternate.childExpirationTime < expirationTime && - (alternate.childExpirationTime = expirationTime); - if (null === node.return && 3 === node.tag) { - root = node.stateNode; - break; + fiber = markUpdateLaneFromFiberToRoot(fiber, lane); + if (null === fiber) return null; + markRootUpdated(fiber, lane, eventTime); + fiber === workInProgressRoot && + ((workInProgressRootUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(fiber, workInProgressRootRenderLanes)); + var priorityLevel = getCurrentPriorityLevel(); + 1 === lane + ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) + ? (schedulePendingInteractions(fiber, lane), performSyncWorkOnRoot(fiber)) + : (ensureRootIsScheduled(fiber, eventTime), + schedulePendingInteractions(fiber, lane), + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) + : (0 === (executionContext & 4) || + (98 !== priorityLevel && 99 !== priorityLevel) || + (null === rootsWithPendingDiscreteUpdates + ? (rootsWithPendingDiscreteUpdates = new Set([fiber])) + : rootsWithPendingDiscreteUpdates.add(fiber)), + ensureRootIsScheduled(fiber, eventTime), + schedulePendingInteractions(fiber, lane)); + mostRecentlyUpdatedRoot = fiber; +} +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + sourceFiber.lanes |= lane; + var alternate = sourceFiber.alternate; + null !== alternate && (alternate.lanes |= lane); + alternate = sourceFiber; + for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + (sourceFiber.childLanes |= lane), + (alternate = sourceFiber.alternate), + null !== alternate && (alternate.childLanes |= lane), + (alternate = sourceFiber), + (sourceFiber = sourceFiber.return); + return 3 === alternate.tag ? alternate.stateNode : null; +} +function ensureRootIsScheduled(root, currentTime) { + for ( + var existingCallbackNode = root.callbackNode, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; + 0 < lanes; + + ) { + var index$5 = 31 - clz32(lanes), + lane = 1 << index$5, + expirationTime = expirationTimes[index$5]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) { + expirationTime = currentTime; + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; + expirationTimes[index$5] = + 10 <= priority + ? expirationTime + 250 + : 6 <= priority + ? expirationTime + 5e3 + : -1; } - node = node.return; - } - null !== root && - (workInProgressRoot === root && - (markUnprocessedUpdateTime(expirationTime), - workInProgressRootExitStatus === RootSuspendedWithDelay && - markRootSuspendedAtTime(root, renderExpirationTime$1)), - markRootUpdatedAtTime(root, expirationTime)); - return root; -} -function getNextRootExpirationTimeToWorkOn(root) { - var lastExpiredTime = root.lastExpiredTime; - if (0 !== lastExpiredTime) return lastExpiredTime; - lastExpiredTime = root.firstPendingTime; - if (!isRootSuspendedAtTime(root, lastExpiredTime)) return lastExpiredTime; - var lastPingedTime = root.lastPingedTime; - root = root.nextKnownPendingLevel; - root = lastPingedTime > root ? lastPingedTime : root; - return 2 >= root && lastExpiredTime !== root ? 0 : root; -} -function ensureRootIsScheduled(root) { - if (0 !== root.lastExpiredTime) - (root.callbackExpirationTime = 1073741823), - (root.callbackPriority = 99), - (root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - )); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + suspendedLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + currentTime = return_highestLanePriority; + if (0 === suspendedLanes) + null !== existingCallbackNode && + (existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode), + (root.callbackNode = null), + (root.callbackPriority = 0)); else { - var expirationTime = getNextRootExpirationTimeToWorkOn(root), - existingCallbackNode = root.callbackNode; - if (0 === expirationTime) - null !== existingCallbackNode && - ((root.callbackNode = null), - (root.callbackExpirationTime = 0), - (root.callbackPriority = 90)); - else { - var currentTime = requestCurrentTimeForUpdate(); - currentTime = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - if (null !== existingCallbackNode) { - var existingCallbackPriority = root.callbackPriority; - if ( - root.callbackExpirationTime === expirationTime && - existingCallbackPriority >= currentTime - ) - return; - existingCallbackNode !== fakeCallbackNode && - Scheduler_cancelCallback(existingCallbackNode); - } - root.callbackExpirationTime = expirationTime; - root.callbackPriority = currentTime; - expirationTime = - 1073741823 === expirationTime - ? scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)) - : scheduleCallback( - currentTime, - performConcurrentWorkOnRoot.bind(null, root), - { timeout: 10 * (1073741821 - expirationTime) - now() } - ); - root.callbackNode = expirationTime; + if (null !== existingCallbackNode) { + if (root.callbackPriority === currentTime) return; + existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode); } + 15 === currentTime + ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), + null === syncQueue + ? ((syncQueue = [existingCallbackNode]), + (immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ))) + : syncQueue.push(existingCallbackNode), + (existingCallbackNode = fakeCallbackNode)) + : 14 === currentTime + ? (existingCallbackNode = scheduleCallback( + 99, + performSyncWorkOnRoot.bind(null, root) + )) + : ((existingCallbackNode = lanePriorityToSchedulerPriority(currentTime)), + (existingCallbackNode = scheduleCallback( + existingCallbackNode, + performConcurrentWorkOnRoot.bind(null, root) + ))); + root.callbackPriority = currentTime; + root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = 0; - if (didTimeout) { - didTimeout = requestCurrentTimeForUpdate(); - var lastExpiredTime = root.lastExpiredTime; - if (0 === lastExpiredTime || lastExpiredTime > didTimeout) - root.lastExpiredTime = didTimeout; - ensureRootIsScheduled(root); - return null; - } - lastExpiredTime = getNextRootExpirationTimeToWorkOn(root); - if (0 === lastExpiredTime) return null; - didTimeout = root.callbackNode; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) +function performConcurrentWorkOnRoot(root) { + currentEventTime = -1; + currentEventPendingLanes = currentEventWipLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - flushPassiveEffects(); - var expirationTime = lastExpiredTime, - prevExecutionContext = executionContext; - executionContext |= RenderContext; - var exitStatus = pushDispatcher(); - if (root !== workInProgressRoot || expirationTime !== renderExpirationTime$1) - prepareFreshStack(root, expirationTime), - startWorkOnPendingInteractions(root, expirationTime); - expirationTime = pushInteractions(root); + var originalCallbackNode = root.callbackNode; + if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) + return null; + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + if (0 === lanes) return null; + var lanes$jscomp$0 = lanes; + var exitStatus = executionContext; + executionContext |= 16; + var prevDispatcher = pushDispatcher(); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes$jscomp$0 + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, lanes$jscomp$0), + startWorkOnPendingInteractions(root, lanes$jscomp$0); + lanes$jscomp$0 = pushInteractions(root); do try { workLoopConcurrent(); @@ -5624,205 +5897,164 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } while (1); resetContextDependencies(); - tracing.__interactionsRef.current = expirationTime; - ReactCurrentDispatcher$1.current = exitStatus; - executionContext = prevExecutionContext; + tracing.__interactionsRef.current = lanes$jscomp$0; + ReactCurrentDispatcher$2.current = prevDispatcher; + executionContext = exitStatus; null !== workInProgress - ? (exitStatus = RootIncomplete) + ? (exitStatus = 0) : ((workInProgressRoot = null), + (workInProgressRootRenderLanes = 0), (exitStatus = workInProgressRootExitStatus)); - if (exitStatus !== RootIncomplete) { - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) - throw ((didTimeout = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), - didTimeout); - prevExecutionContext = root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) + prepareFreshStack(root, 0); + else if (0 !== exitStatus) { + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) + throw ((originalCallbackNode = workInProgressRootFatalError), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); + root.finishedWork = root.current.alternate; + root.finishedLanes = lanes; switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: + case 0: + case 1: throw Error("Root did not complete. This is a bug in React."); - case RootErrored: + case 2: commitRoot(root); break; - case RootSuspended: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - prevExecutionContext - )); + case 3: + markRootSuspended$1(root, lanes); if ( - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - ((prevExecutionContext = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now()), - 10 < prevExecutionContext) + (lanes & 62914560) === lanes && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { - if ( - workInProgressRootHasPendingPing && - ((expirationTime = root.lastPingedTime), - 0 === expirationTime || expirationTime >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - expirationTime = getNextRootExpirationTimeToWorkOn(root); - if (0 !== expirationTime && expirationTime !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; + if (0 !== getNextLanes(root, 0)) break; + prevDispatcher = root.suspendedLanes; + if ((prevDispatcher & lanes) !== lanes) { + requestEventTime(); + root.pingedLanes |= root.suspendedLanes & prevDispatcher; break; } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - prevExecutionContext + exitStatus ); break; } commitRoot(root); break; - case RootSuspendedWithDelay: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - prevExecutionContext - )); - if ( - workInProgressRootHasPendingPing && - ((prevExecutionContext = root.lastPingedTime), - 0 === prevExecutionContext || prevExecutionContext >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - prevExecutionContext = getNextRootExpirationTimeToWorkOn(root); - if ( - 0 !== prevExecutionContext && - prevExecutionContext !== lastExpiredTime - ) - break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; - break; + case 4: + markRootSuspended$1(root, lanes); + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevDispatcher = -1; 0 < lanes; ) { + var index$4 = 31 - clz32(lanes); + lanes$jscomp$0 = 1 << index$4; + index$4 = exitStatus[index$4]; + index$4 > prevDispatcher && (prevDispatcher = index$4); + lanes &= ~lanes$jscomp$0; } - 1073741823 !== workInProgressRootLatestSuspenseTimeout - ? (prevExecutionContext = - 10 * (1073741821 - workInProgressRootLatestSuspenseTimeout) - - now()) - : 1073741823 === workInProgressRootLatestProcessedExpirationTime - ? (prevExecutionContext = 0) - : ((prevExecutionContext = - 10 * - (1073741821 - workInProgressRootLatestProcessedExpirationTime) - - 5e3), - (exitStatus = now()), - (lastExpiredTime = - 10 * (1073741821 - lastExpiredTime) - exitStatus), - (prevExecutionContext = exitStatus - prevExecutionContext), - 0 > prevExecutionContext && (prevExecutionContext = 0), - (prevExecutionContext = - (120 > prevExecutionContext - ? 120 - : 480 > prevExecutionContext - ? 480 - : 1080 > prevExecutionContext - ? 1080 - : 1920 > prevExecutionContext - ? 1920 - : 3e3 > prevExecutionContext - ? 3e3 - : 4320 > prevExecutionContext - ? 4320 - : 1960 * ceil(prevExecutionContext / 1960)) - - prevExecutionContext), - lastExpiredTime < prevExecutionContext && - (prevExecutionContext = lastExpiredTime)); - if (10 < prevExecutionContext) { + lanes = prevDispatcher; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; + if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - prevExecutionContext + lanes ); break; } commitRoot(root); break; - case RootCompleted: - if ( - 1073741823 !== workInProgressRootLatestProcessedExpirationTime && - null !== workInProgressRootCanSuspendUsingConfig - ) { - expirationTime = workInProgressRootLatestProcessedExpirationTime; - var suspenseConfig = workInProgressRootCanSuspendUsingConfig; - prevExecutionContext = suspenseConfig.busyMinDurationMs | 0; - 0 >= prevExecutionContext - ? (prevExecutionContext = 0) - : ((exitStatus = suspenseConfig.busyDelayMs | 0), - (expirationTime = - now() - - (10 * (1073741821 - expirationTime) - - (suspenseConfig.timeoutMs | 0 || 5e3))), - (prevExecutionContext = - expirationTime <= exitStatus - ? 0 - : exitStatus + prevExecutionContext - expirationTime)); - if (10 < prevExecutionContext) { - markRootSuspendedAtTime(root, lastExpiredTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - prevExecutionContext - ); - break; - } - } + case 5: commitRoot(root); break; default: throw Error("Unknown root exit status."); } } - ensureRootIsScheduled(root); - return root.callbackNode === didTimeout + ensureRootIsScheduled(root, now()); + return root.callbackNode === originalCallbackNode ? performConcurrentWorkOnRoot.bind(null, root) : null; } +function markRootSuspended$1(root, suspendedLanes) { + suspendedLanes &= ~workInProgressRootPingedLanes; + suspendedLanes &= ~workInProgressRootUpdatedLanes; + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; + for (root = root.expirationTimes; 0 < suspendedLanes; ) { + var index$9 = 31 - clz32(suspendedLanes), + lane = 1 << index$9; + root[index$9] = -1; + suspendedLanes &= ~lane; + } +} function performSyncWorkOnRoot(root) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - lastExpiredTime = - 0 !== lastExpiredTime - ? root === workInProgressRoot && renderExpirationTime$1 >= lastExpiredTime - ? renderExpirationTime$1 - : lastExpiredTime - : 1073741823; - var exitStatus = renderRootSync(root, lastExpiredTime); + if ( + root === workInProgressRoot && + 0 !== (root.expiredLanes & workInProgressRootRenderLanes) + ) { + var lanes = workInProgressRootRenderLanes; + var exitStatus = renderRootSync(root, lanes); + 0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes) && + ((lanes = getNextLanes(root, lanes)), + (exitStatus = renderRootSync(root, lanes))); + } else + (lanes = getNextLanes(root, 0)), (exitStatus = renderRootSync(root, lanes)); 0 !== root.tag && - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && ((root.hydrate = !1), shim(root.containerInfo)), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), exitStatus); root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + root.finishedLanes = lanes; commitRoot(root); - ensureRootIsScheduled(root); + ensureRootIsScheduled(root, now()); return null; } -function prepareFreshStack(root, expirationTime) { +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes); + subtreeRenderLanes |= lanes; + workInProgressRootIncludedLanes |= lanes; +} +function popRenderLanes() { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor); +} +function prepareFreshStack(root, lanes) { root.finishedWork = null; - root.finishedExpirationTime = 0; + root.finishedLanes = 0; var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); @@ -5840,6 +6072,7 @@ function prepareFreshStack(root, expirationTime) { popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); + resetWorkInProgressVersions(); break; case 5: popHostContext(interruptedWork); @@ -5855,26 +6088,28 @@ function prepareFreshStack(root, expirationTime) { break; case 10: popProvider(interruptedWork); + break; + case 22: + case 23: + popRenderLanes(); } timeoutHandle = timeoutHandle.return; } workInProgressRoot = root; workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = workInProgressRootLatestProcessedExpirationTime = 1073741823; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = 0; - workInProgressRootHasPendingPing = !1; + workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; spawnedWorkDuringRender = null; } function handleError(root$jscomp$0, thrownValue) { do { + var erroredWork = workInProgress; try { resetContextDependencies(); - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - if (didScheduleRenderPhaseUpdate) + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (didScheduleRenderPhaseUpdate) { for ( var hook = currentlyRenderingFiber$1.memoizedState; null !== hook; @@ -5884,51 +6119,54 @@ function handleError(root$jscomp$0, thrownValue) { null !== queue && (queue.pending = null); hook = hook.next; } - renderExpirationTime = 0; + didScheduleRenderPhaseUpdate = !1; + } + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; - didScheduleRenderPhaseUpdate = !1; - if (null === workInProgress || null === workInProgress.return) - return ( - (workInProgressRootExitStatus = RootFatalErrored), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null) - ); - workInProgress.mode & 8 && - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !0); + didScheduleRenderPhaseUpdateDuringThisPass = !1; + ReactCurrentOwner$2.current = null; + if (null === erroredWork || null === erroredWork.return) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + break; + } + erroredWork.mode & 8 && + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, !0); a: { var root = root$jscomp$0, - returnFiber = workInProgress.return, - sourceFiber = workInProgress, + returnFiber = erroredWork.return, + sourceFiber = erroredWork, value = thrownValue; - thrownValue = renderExpirationTime$1; - sourceFiber.effectTag |= 2048; + thrownValue = workInProgressRootRenderLanes; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && "object" === typeof value && "function" === typeof value.then ) { - var thenable = value; + var wakeable = value; if (0 === (sourceFiber.mode & 2)) { var currentSource = sourceFiber.alternate; currentSource ? ((sourceFiber.updateQueue = currentSource.updateQueue), (sourceFiber.memoizedState = currentSource.memoizedState), - (sourceFiber.expirationTime = currentSource.expirationTime)) + (sourceFiber.lanes = currentSource.lanes)) : ((sourceFiber.updateQueue = null), (sourceFiber.memoizedState = null)); } var hasInvisibleParentBoundary = 0 !== (suspenseStackCursor.current & 1), - _workInProgress = returnFiber; + workInProgress$77 = returnFiber; do { var JSCompiler_temp; - if ((JSCompiler_temp = 13 === _workInProgress.tag)) { - var nextState = _workInProgress.memoizedState; + if ((JSCompiler_temp = 13 === workInProgress$77.tag)) { + var nextState = workInProgress$77.memoizedState; if (null !== nextState) JSCompiler_temp = null !== nextState.dehydrated ? !0 : !1; else { - var props = _workInProgress.memoizedProps; + var props = workInProgress$77.memoizedProps; JSCompiler_temp = void 0 === props.fallback ? !1 @@ -5940,23 +6178,24 @@ function handleError(root$jscomp$0, thrownValue) { } } if (JSCompiler_temp) { - var thenables = _workInProgress.updateQueue; - if (null === thenables) { + var wakeables = workInProgress$77.updateQueue; + if (null === wakeables) { var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else thenables.add(thenable); - if (0 === (_workInProgress.mode & 2)) { - _workInProgress.effectTag |= 64; - sourceFiber.effectTag &= -2981; + updateQueue.add(wakeable); + workInProgress$77.updateQueue = updateQueue; + } else wakeables.add(wakeable); + if (0 === (workInProgress$77.mode & 2)) { + workInProgress$77.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(1073741823, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } - sourceFiber.expirationTime = 1073741823; + sourceFiber.lanes |= 1; break a; } value = void 0; @@ -5965,86 +6204,90 @@ function handleError(root$jscomp$0, thrownValue) { null === pingCache ? ((pingCache = root.pingCache = new PossiblyWeakMap()), (value = new Set()), - pingCache.set(thenable, value)) - : ((value = pingCache.get(thenable)), + pingCache.set(wakeable, value)) + : ((value = pingCache.get(wakeable)), void 0 === value && - ((value = new Set()), pingCache.set(thenable, value))); + ((value = new Set()), pingCache.set(wakeable, value))); if (!value.has(sourceFiber)) { value.add(sourceFiber); var ping = pingSuspendedRoot.bind( null, root, - thenable, + wakeable, sourceFiber ); - thenable.then(ping, ping); + wakeable.then(ping, ping); } - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; + workInProgress$77.flags |= 8192; + workInProgress$77.lanes = thrownValue; break a; } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$77 = workInProgress$77.return; + } while (null !== workInProgress$77); value = Error( (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) + " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." ); } - workInProgressRootExitStatus !== RootCompleted && - (workInProgressRootExitStatus = RootErrored); + 5 !== workInProgressRootExitStatus && + (workInProgressRootExitStatus = 2); value = createCapturedValue(value, sourceFiber); - _workInProgress = returnFiber; + workInProgress$77 = returnFiber; do { - switch (_workInProgress.tag) { + switch (workInProgress$77.tag) { case 3: - thenable = value; - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update = createRootErrorUpdate( - _workInProgress, - thenable, + root = value; + workInProgress$77.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$77.lanes |= thrownValue; + var update$78 = createRootErrorUpdate( + workInProgress$77, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update); + enqueueCapturedUpdate(workInProgress$77, update$78); break a; case 1: - thenable = value; - var ctor = _workInProgress.type, - instance = _workInProgress.stateNode; + root = value; + var ctor = workInProgress$77.type, + instance = workInProgress$77.stateNode; if ( - 0 === (_workInProgress.effectTag & 64) && + 0 === (workInProgress$77.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update2 = createClassErrorUpdate( - _workInProgress, - thenable, + workInProgress$77.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$77.lanes |= thrownValue; + var update$81 = createClassErrorUpdate( + workInProgress$77, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update2); + enqueueCapturedUpdate(workInProgress$77, update$81); break a; } } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$77 = workInProgress$77.return; + } while (null !== workInProgress$77); } - workInProgress = completeUnitOfWork(workInProgress); + completeUnitOfWork(erroredWork); } catch (yetAnotherThrownValue) { thrownValue = yetAnotherThrownValue; + workInProgress === erroredWork && + null !== erroredWork && + (workInProgress = erroredWork = erroredWork.return); continue; } break; } while (1); } function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } function pushInteractions(root) { @@ -6052,28 +6295,13 @@ function pushInteractions(root) { tracing.__interactionsRef.current = root.memoizedInteractions; return prevInteractions; } -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - expirationTime < workInProgressRootLatestProcessedExpirationTime && - 2 < expirationTime && - (workInProgressRootLatestProcessedExpirationTime = expirationTime); - null !== suspenseConfig && - expirationTime < workInProgressRootLatestSuspenseTimeout && - 2 < expirationTime && - ((workInProgressRootLatestSuspenseTimeout = expirationTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig)); -} -function markUnprocessedUpdateTime(expirationTime) { - expirationTime > workInProgressRootNextUnprocessedUpdateTime && - (workInProgressRootNextUnprocessedUpdateTime = expirationTime); -} -function renderRootSync(root, expirationTime) { +function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; - executionContext |= RenderContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - if (root !== workInProgressRoot || expirationTime !== renderExpirationTime$1) - prepareFreshStack(root, expirationTime), - startWorkOnPendingInteractions(root, expirationTime); - expirationTime = pushInteractions(root); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) + prepareFreshStack(root, lanes), startWorkOnPendingInteractions(root, lanes); + lanes = pushInteractions(root); do try { workLoopSync(); @@ -6083,187 +6311,197 @@ function renderRootSync(root, expirationTime) { } while (1); resetContextDependencies(); - tracing.__interactionsRef.current = expirationTime; + tracing.__interactionsRef.current = lanes; executionContext = prevExecutionContext; - ReactCurrentDispatcher$1.current = prevDispatcher; + ReactCurrentDispatcher$2.current = prevDispatcher; if (null !== workInProgress) throw Error( "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." ); workInProgressRoot = null; + workInProgressRootRenderLanes = 0; return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress; ) performUnitOfWork(workInProgress); } function workLoopConcurrent() { for (; null !== workInProgress && !Scheduler_shouldYield(); ) - workInProgress = performUnitOfWork(workInProgress); + performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { var current = unitOfWork.alternate; 0 !== (unitOfWork.mode & 8) ? ((profilerStartTime = now$1()), 0 > unitOfWork.actualStartTime && (unitOfWork.actualStartTime = now$1()), - (current = beginWork$1(current, unitOfWork, renderExpirationTime$1)), + (current = beginWork$1(current, unitOfWork, subtreeRenderLanes)), stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, !0)) - : (current = beginWork$1(current, unitOfWork, renderExpirationTime$1)); + : (current = beginWork$1(current, unitOfWork, subtreeRenderLanes)); unitOfWork.memoizedProps = unitOfWork.pendingProps; - null === current && (current = completeUnitOfWork(unitOfWork)); + null === current + ? completeUnitOfWork(unitOfWork) + : (workInProgress = current); ReactCurrentOwner$2.current = null; - return current; } function completeUnitOfWork(unitOfWork) { - workInProgress = unitOfWork; + var completedWork = unitOfWork; do { - var current = workInProgress.alternate; - unitOfWork = workInProgress.return; - if (0 === (workInProgress.effectTag & 2048)) { - if (0 === (workInProgress.mode & 8)) - current = completeWork(current, workInProgress, renderExpirationTime$1); + var current = completedWork.alternate; + unitOfWork = completedWork.return; + if (0 === (completedWork.flags & 4096)) { + if (0 === (completedWork.mode & 8)) + current = completeWork(current, completedWork, subtreeRenderLanes); else { - var fiber = workInProgress; + var fiber = completedWork; profilerStartTime = now$1(); 0 > fiber.actualStartTime && (fiber.actualStartTime = now$1()); - current = completeWork(current, workInProgress, renderExpirationTime$1); - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !1); + current = completeWork(current, completedWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(completedWork, !1); } - fiber = workInProgress; - if (1 === renderExpirationTime$1 || 1 !== fiber.childExpirationTime) { - var newChildExpirationTime = 0; - if (0 !== (fiber.mode & 8)) { + if (null !== current) { + workInProgress = current; + return; + } + current = completedWork; + if ( + (23 !== current.tag && 22 !== current.tag) || + null === current.memoizedState || + 0 !== (subtreeRenderLanes & 1073741824) || + 0 === (current.mode & 4) + ) { + fiber = 0; + if (0 !== (current.mode & 8)) { for ( - var actualDuration = fiber.actualDuration, - treeBaseDuration = fiber.selfBaseDuration, + var actualDuration = current.actualDuration, + treeBaseDuration = current.selfBaseDuration, shouldBubbleActualDurations = - null === fiber.alternate || - fiber.child !== fiber.alternate.child, - child = fiber.child; + null === current.alternate || + current.child !== current.alternate.child, + child = current.child; null !== child; - ) { - var childUpdateExpirationTime = child.expirationTime, - childChildExpirationTime = child.childExpirationTime; - childUpdateExpirationTime > newChildExpirationTime && - (newChildExpirationTime = childUpdateExpirationTime); - childChildExpirationTime > newChildExpirationTime && - (newChildExpirationTime = childChildExpirationTime); - shouldBubbleActualDurations && - (actualDuration += child.actualDuration); - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } - fiber.actualDuration = actualDuration; - fiber.treeBaseDuration = treeBaseDuration; + ) + (fiber |= child.lanes | child.childLanes), + shouldBubbleActualDurations && + (actualDuration += child.actualDuration), + (treeBaseDuration += child.treeBaseDuration), + (child = child.sibling); + 13 === current.tag && + null !== current.memoizedState && + ((shouldBubbleActualDurations = current.child), + null !== shouldBubbleActualDurations && + (treeBaseDuration -= + shouldBubbleActualDurations.treeBaseDuration)); + current.actualDuration = actualDuration; + current.treeBaseDuration = treeBaseDuration; } else - for (actualDuration = fiber.child; null !== actualDuration; ) - (treeBaseDuration = actualDuration.expirationTime), - (shouldBubbleActualDurations = - actualDuration.childExpirationTime), - treeBaseDuration > newChildExpirationTime && - (newChildExpirationTime = treeBaseDuration), - shouldBubbleActualDurations > newChildExpirationTime && - (newChildExpirationTime = shouldBubbleActualDurations), + for (actualDuration = current.child; null !== actualDuration; ) + (fiber |= actualDuration.lanes | actualDuration.childLanes), (actualDuration = actualDuration.sibling); - fiber.childExpirationTime = newChildExpirationTime; + current.childLanes = fiber; } - if (null !== current) return current; null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && - (unitOfWork.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && + (unitOfWork.firstEffect = completedWork.firstEffect), + null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && - (unitOfWork.lastEffect.nextEffect = workInProgress.firstEffect), - (unitOfWork.lastEffect = workInProgress.lastEffect)), - 1 < workInProgress.effectTag && + (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), + (unitOfWork.lastEffect = completedWork.lastEffect)), + 1 < completedWork.flags && (null !== unitOfWork.lastEffect - ? (unitOfWork.lastEffect.nextEffect = workInProgress) - : (unitOfWork.firstEffect = workInProgress), - (unitOfWork.lastEffect = workInProgress))); + ? (unitOfWork.lastEffect.nextEffect = completedWork) + : (unitOfWork.firstEffect = completedWork), + (unitOfWork.lastEffect = completedWork))); } else { - current = unwindWork(workInProgress); - if (0 !== (workInProgress.mode & 8)) { - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !1); - fiber = workInProgress.actualDuration; - for ( - newChildExpirationTime = workInProgress.child; - null !== newChildExpirationTime; - - ) - (fiber += newChildExpirationTime.actualDuration), - (newChildExpirationTime = newChildExpirationTime.sibling); - workInProgress.actualDuration = fiber; + current = unwindWork(completedWork); + if (null !== current) { + current.flags &= 4095; + workInProgress = current; + return; + } + if (0 !== (completedWork.mode & 8)) { + stopProfilerTimerIfRunningAndRecordDelta(completedWork, !1); + current = completedWork.actualDuration; + for (fiber = completedWork.child; null !== fiber; ) + (current += fiber.actualDuration), (fiber = fiber.sibling); + completedWork.actualDuration = current; } - if (null !== current) return (current.effectTag &= 2047), current; null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } - current = workInProgress.sibling; - if (null !== current) return current; - workInProgress = unitOfWork; - } while (null !== workInProgress); - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootCompleted); - return null; -} -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - fiber = fiber.childExpirationTime; - return updateExpirationTime > fiber ? updateExpirationTime : fiber; + completedWork = completedWork.sibling; + if (null !== completedWork) { + workInProgress = completedWork; + return; + } + workInProgress = completedWork = unitOfWork; + } while (null !== completedWork); + 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } function commitRoot(root) { var renderPriorityLevel = getCurrentPriorityLevel(); runWithPriority(99, commitRootImpl.bind(null, root, renderPriorityLevel)); return null; } -function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { +function commitRootImpl(root, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - var finishedWork = root$jscomp$1.finishedWork, - expirationTime = root$jscomp$1.finishedExpirationTime; + var finishedWork = root.finishedWork, + lanes = root.finishedLanes; if (null === finishedWork) return null; - root$jscomp$1.finishedWork = null; - root$jscomp$1.finishedExpirationTime = 0; - if (finishedWork === root$jscomp$1.current) + root.finishedWork = null; + root.finishedLanes = 0; + if (finishedWork === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - root$jscomp$1.callbackNode = null; - root$jscomp$1.callbackExpirationTime = 0; - root$jscomp$1.callbackPriority = 90; - root$jscomp$1.nextKnownPendingLevel = 0; - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - root$jscomp$1.firstPendingTime = remainingExpirationTimeBeforeCommit; - expirationTime <= root$jscomp$1.lastSuspendedTime - ? (root$jscomp$1.firstSuspendedTime = root$jscomp$1.lastSuspendedTime = root$jscomp$1.nextKnownPendingLevel = 0) - : expirationTime <= root$jscomp$1.firstSuspendedTime && - (root$jscomp$1.firstSuspendedTime = expirationTime - 1); - expirationTime <= root$jscomp$1.lastPingedTime && - (root$jscomp$1.lastPingedTime = 0); - expirationTime <= root$jscomp$1.lastExpiredTime && - (root$jscomp$1.lastExpiredTime = 0); - root$jscomp$1 === workInProgressRoot && + root.callbackNode = null; + var remainingLanes = finishedWork.lanes | finishedWork.childLanes, + remainingLanes$jscomp$0 = remainingLanes, + noLongerPendingLanes = root.pendingLanes & ~remainingLanes$jscomp$0; + root.pendingLanes = remainingLanes$jscomp$0; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes$jscomp$0; + root.mutableReadLanes &= remainingLanes$jscomp$0; + root.entangledLanes &= remainingLanes$jscomp$0; + remainingLanes$jscomp$0 = root.entanglements; + for ( + var eventTimes = root.eventTimes, expirationTimes = root.expirationTimes; + 0 < noLongerPendingLanes; + + ) { + var index$10 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$10; + remainingLanes$jscomp$0[index$10] = 0; + eventTimes[index$10] = -1; + expirationTimes[index$10] = -1; + noLongerPendingLanes &= ~lane; + } + null !== rootsWithPendingDiscreteUpdates && + 0 === (remainingLanes & 24) && + rootsWithPendingDiscreteUpdates.has(root) && + rootsWithPendingDiscreteUpdates.delete(root); + root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (renderExpirationTime$1 = 0)); - 1 < finishedWork.effectTag + (workInProgressRootRenderLanes = 0)); + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), - (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect)) - : (remainingExpirationTimeBeforeCommit = finishedWork) - : (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect); - if (null !== remainingExpirationTimeBeforeCommit) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root$jscomp$1); - ReactCurrentOwner$2.current = null; - nextEffect = remainingExpirationTimeBeforeCommit; + (remainingLanes = finishedWork.firstEffect)) + : (remainingLanes = finishedWork) + : (remainingLanes = finishedWork.firstEffect); + if (null !== remainingLanes) { + remainingLanes$jscomp$0 = executionContext; + executionContext |= 32; + eventTimes = pushInteractions(root); + focusedInstanceHandle = ReactCurrentOwner$2.current = null; + shouldFireAfterActiveInstanceBlur = !1; + nextEffect = remainingLanes; do try { commitBeforeMutationEffects(); @@ -6273,18 +6511,14 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); + focusedInstanceHandle = null; commitTime = now$1(); - nextEffect = remainingExpirationTimeBeforeCommit; + nextEffect = remainingLanes; do try { - for ( - var root = root$jscomp$1, - renderPriorityLevel = renderPriorityLevel$jscomp$1; - null !== nextEffect; - - ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + for (; null !== nextEffect; ) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6294,82 +6528,137 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: commitWork(nextEffect.alternate, nextEffect); break; case 8: - var current$jscomp$0 = nextEffect; - a: for ( - var finishedRoot = root, - root$jscomp$0 = current$jscomp$0, - renderPriorityLevel$jscomp$0 = renderPriorityLevel, - node = root$jscomp$0; - ; - - ) + expirationTimes = nextEffect; + a: for (index$10 = noLongerPendingLanes = expirationTimes; ; ) { + lane = index$10; if ( - (commitUnmount( - finishedRoot, - node, - renderPriorityLevel$jscomp$0 - ), - null !== node.child) + injectedHook && + "function" === typeof injectedHook.onCommitFiberUnmount ) - (node.child.return = node), (node = node.child); + try { + injectedHook.onCommitFiberUnmount(rendererID, lane); + } catch (err) {} + switch (lane.tag) { + case 0: + case 11: + case 14: + case 15: + var updateQueue = lane.updateQueue; + if (null !== updateQueue) { + var lastEffect = updateQueue.lastEffect; + if (null !== lastEffect) { + var firstEffect = lastEffect.next, + effect = firstEffect; + do { + var _effect2 = effect, + destroy = _effect2.destroy, + tag = _effect2.tag; + if (void 0 !== destroy) + if (0 !== (tag & 4)) + enqueuePendingPassiveHookEffectUnmount( + lane, + effect + ); + else { + _effect2 = lane; + try { + destroy(); + } catch (error) { + captureCommitPhaseError(_effect2, error); + } + } + effect = effect.next; + } while (effect !== firstEffect); + } + } + break; + case 1: + safelyDetachRef(lane); + var instance = lane.stateNode; + if ("function" === typeof instance.componentWillUnmount) + try { + (effect = lane), + (_effect2 = instance), + (_effect2.props = effect.memoizedProps), + (_effect2.state = effect.memoizedState), + _effect2.componentWillUnmount(); + } catch (unmountError) { + captureCommitPhaseError(lane, unmountError); + } + break; + case 5: + safelyDetachRef(lane); + break; + case 4: + createChildNodeSet(lane.stateNode.containerInfo); + } + if (null !== index$10.child) + (index$10.child.return = index$10), + (index$10 = index$10.child); else { - if (node === root$jscomp$0) break; - for (; null === node.sibling; ) { - if (null === node.return || node.return === root$jscomp$0) + if (index$10 === noLongerPendingLanes) break; + for (; null === index$10.sibling; ) { + if ( + null === index$10.return || + index$10.return === noLongerPendingLanes + ) break a; - node = node.return; + index$10 = index$10.return; } - node.sibling.return = node.return; - node = node.sibling; + index$10.sibling.return = index$10.return; + index$10 = index$10.sibling; } - detachFiber(current$jscomp$0); + } + var alternate = expirationTimes.alternate; + detachFiberMutation(expirationTimes); + null !== alternate && detachFiberMutation(alternate); } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$90) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$90); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - root$jscomp$1.current = finishedWork; - nextEffect = remainingExpirationTimeBeforeCommit; + root.current = finishedWork; + nextEffect = remainingLanes; do try { - for (effectTag = root$jscomp$1; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { - var instance = nextEffect.stateNode; + var instance$jscomp$0 = nextEffect.stateNode; switch (nextEffect.tag) { case 5: - current = instance.canonical; + current = instance$jscomp$0.canonical; break; default: - current = instance; + current = instance$jscomp$0; } "function" === typeof ref ? ref(current) @@ -6378,73 +6667,89 @@ function commitRootImpl(root$jscomp$1, renderPriorityLevel$jscomp$1) { } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$91) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$91); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); nextEffect = null; requestPaint(); - tracing.__interactionsRef.current = prevInteractions; - executionContext = prevExecutionContext; - } else (root$jscomp$1.current = finishedWork), (commitTime = now$1()); - if ((effectTag$jscomp$0 = rootDoesHavePassiveEffects)) + tracing.__interactionsRef.current = eventTimes; + executionContext = remainingLanes$jscomp$0; + } else (root.current = finishedWork), (commitTime = now$1()); + if ((flags$jscomp$0 = rootDoesHavePassiveEffects)) (rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root$jscomp$1), - (pendingPassiveEffectsExpirationTime = expirationTime), - (pendingPassiveEffectsRenderPriority = renderPriorityLevel$jscomp$1); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsLanes = lanes), + (pendingPassiveEffectsRenderPriority = renderPriorityLevel); else - for ( - nextEffect = remainingExpirationTimeBeforeCommit; - null !== nextEffect; - - ) - (renderPriorityLevel$jscomp$1 = nextEffect.nextEffect), + for (nextEffect = remainingLanes; null !== nextEffect; ) + (ref = nextEffect.nextEffect), (nextEffect.nextEffect = null), - (nextEffect = renderPriorityLevel$jscomp$1); - renderPriorityLevel$jscomp$1 = root$jscomp$1.firstPendingTime; - if (0 !== renderPriorityLevel$jscomp$1) { + nextEffect.flags & 8 && + ((instance$jscomp$0 = nextEffect), + (instance$jscomp$0.sibling = null), + (instance$jscomp$0.stateNode = null)), + (nextEffect = ref); + remainingLanes = root.pendingLanes; + if (0 !== remainingLanes) { if (null !== spawnedWorkDuringRender) for ( - remainingExpirationTimeBeforeCommit = spawnedWorkDuringRender, + ref = spawnedWorkDuringRender, spawnedWorkDuringRender = null, - ref = 0; - ref < remainingExpirationTimeBeforeCommit.length; - ref++ + instance$jscomp$0 = 0; + instance$jscomp$0 < ref.length; + instance$jscomp$0++ ) scheduleInteractions( - root$jscomp$1, - remainingExpirationTimeBeforeCommit[ref], - root$jscomp$1.memoizedInteractions + root, + ref[instance$jscomp$0], + root.memoizedInteractions ); - schedulePendingInteractions(root$jscomp$1, renderPriorityLevel$jscomp$1); + schedulePendingInteractions(root, remainingLanes); } else legacyErrorBoundariesThatAlreadyFailed = null; - effectTag$jscomp$0 || - finishPendingInteractions(root$jscomp$1, expirationTime); - 1073741823 === renderPriorityLevel$jscomp$1 - ? root$jscomp$1 === rootWithNestedUpdates + flags$jscomp$0 || finishPendingInteractions(root, lanes); + 1 === remainingLanes + ? root === rootWithNestedUpdates ? nestedUpdateCount++ - : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root$jscomp$1)) + : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)) : (nestedUpdateCount = 0); - "function" === typeof onCommitFiberRoot && - onCommitFiberRoot(finishedWork.stateNode, expirationTime); - ensureRootIsScheduled(root$jscomp$1); + finishedWork = finishedWork.stateNode; + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + injectedHook.onCommitFiberRoot( + rendererID, + finishedWork, + renderPriorityLevel, + 64 === (finishedWork.current.flags & 64) + ); + } catch (err) {} + ensureRootIsScheduled(root, now()); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root$jscomp$1 = firstUncaughtError), + (root = firstUncaughtError), (firstUncaughtError = null), - root$jscomp$1); - if ((executionContext & LegacyUnbatchedContext) !== NoContext) return null; + root); + if (0 !== (executionContext & 8)) return null; flushSyncCallbackQueue(); return null; } function commitBeforeMutationEffects() { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect); - 0 === (effectTag & 512) || + var current = nextEffect.alternate; + shouldFireAfterActiveInstanceBlur || + null === focusedInstanceHandle || + (0 !== (nextEffect.flags & 8) + ? doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0) + : 13 === nextEffect.tag && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0)); + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6463,56 +6768,87 @@ function flushPassiveEffects() { pendingPassiveEffectsRenderPriority = 90; return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } + return !1; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); } function flushPassiveEffectsImpl() { if (null === rootWithPendingPassiveEffects) return !1; var root = rootWithPendingPassiveEffects, - expirationTime = pendingPassiveEffectsExpirationTime; + lanes = pendingPassiveEffectsLanes; rootWithPendingPassiveEffects = null; - pendingPassiveEffectsExpirationTime = 0; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + pendingPassiveEffectsLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; - executionContext |= CommitContext; - for ( - var prevInteractions = pushInteractions(root), - _effect2 = root.current.firstEffect; - null !== _effect2; - - ) { + executionContext |= 32; + var prevInteractions = pushInteractions(root), + unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + for (var i = 0; i < unmountEffects.length; i += 2) { + var effect$96 = unmountEffects[i], + fiber = unmountEffects[i + 1], + destroy = effect$96.destroy; + effect$96.destroy = void 0; + if ("function" === typeof destroy) + try { + destroy(); + } catch (error) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error); + } + } + unmountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; + for (i = 0; i < unmountEffects.length; i += 2) { + effect$96 = unmountEffects[i]; + fiber = unmountEffects[i + 1]; try { - var finishedWork = _effect2; - if (0 !== (finishedWork.effectTag & 512)) - switch (finishedWork.tag) { - case 0: - case 11: - case 15: - case 22: - commitHookEffectListUnmount(5, finishedWork), - commitHookEffectListMount(5, finishedWork); - } - } catch (error) { - if (null === _effect2) throw Error("Should be working on an effect."); - captureCommitPhaseError(_effect2, error); + var create$100 = effect$96.create; + effect$96.destroy = create$100(); + } catch (error$101) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error$101); } - finishedWork = _effect2.nextEffect; - _effect2.nextEffect = null; - _effect2 = finishedWork; } + for (unmountEffects = root.current.firstEffect; null !== unmountEffects; ) + (create$100 = unmountEffects.nextEffect), + (unmountEffects.nextEffect = null), + unmountEffects.flags & 8 && + ((unmountEffects.sibling = null), (unmountEffects.stateNode = null)), + (unmountEffects = create$100); tracing.__interactionsRef.current = prevInteractions; - finishPendingInteractions(root, expirationTime); + finishPendingInteractions(root, lanes); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; } function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1073741823); + sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1); enqueueUpdate(rootFiber, sourceFiber); - rootFiber = markUpdateTimeFromFiberToRoot(rootFiber, 1073741823); + sourceFiber = requestEventTime(); + rootFiber = markUpdateLaneFromFiberToRoot(rootFiber, 1); null !== rootFiber && - (ensureRootIsScheduled(rootFiber), - schedulePendingInteractions(rootFiber, 1073741823)); + (markRootUpdated(rootFiber, 1, sourceFiber), + ensureRootIsScheduled(rootFiber, sourceFiber), + schedulePendingInteractions(rootFiber, 1)); } function captureCommitPhaseError(sourceFiber, error) { if (3 === sourceFiber.tag) @@ -6531,158 +6867,176 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1073741823); - enqueueUpdate(fiber, sourceFiber); - fiber = markUpdateTimeFromFiberToRoot(fiber, 1073741823); - null !== fiber && - (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, 1073741823)); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); + fiber = markUpdateLaneFromFiberToRoot(fiber, 1); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update), + schedulePendingInteractions(fiber, 1); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { +function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; - null !== pingCache && pingCache.delete(thenable); - workInProgressRoot === root && renderExpirationTime$1 === suspendedTime - ? workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ? prepareFreshStack(root, renderExpirationTime$1) - : (workInProgressRootHasPendingPing = !0) - : isRootSuspendedAtTime(root, suspendedTime) && - ((thenable = root.lastPingedTime), - (0 !== thenable && thenable < suspendedTime) || - ((root.lastPingedTime = suspendedTime), - ensureRootIsScheduled(root), - schedulePendingInteractions(root, suspendedTime))); -} -function resolveRetryThenable(boundaryFiber, thenable) { + null !== pingCache && pingCache.delete(wakeable); + wakeable = requestEventTime(); + root.pingedLanes |= root.suspendedLanes & pingedLanes; + workInProgressRoot === root && + (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && + (4 === workInProgressRootExitStatus || + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 62914560) === + workInProgressRootRenderLanes && + 500 > now() - globalMostRecentFallbackTime) + ? prepareFreshStack(root, 0) + : (workInProgressRootPingedLanes |= pingedLanes)); + ensureRootIsScheduled(root, wakeable); + schedulePendingInteractions(root, pingedLanes); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(thenable); - thenable = 0; - 0 === thenable && - ((thenable = requestCurrentTimeForUpdate()), - (thenable = computeExpirationForFiber(thenable, boundaryFiber, null))); - boundaryFiber = markUpdateTimeFromFiberToRoot(boundaryFiber, thenable); + null !== retryCache && retryCache.delete(wakeable); + wakeable = 0; + 0 === wakeable && + ((wakeable = boundaryFiber.mode), + 0 === (wakeable & 2) + ? (wakeable = 1) + : 0 === (wakeable & 4) + ? (wakeable = 99 === getCurrentPriorityLevel() ? 1 : 2) + : (0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes), + (wakeable = getHighestPriorityLane(62914560 & ~currentEventWipLanes)), + 0 === wakeable && (wakeable = 4194304))); + retryCache = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); null !== boundaryFiber && - (ensureRootIsScheduled(boundaryFiber), - schedulePendingInteractions(boundaryFiber, thenable)); + (markRootUpdated(boundaryFiber, wakeable, retryCache), + ensureRootIsScheduled(boundaryFiber, retryCache), + schedulePendingInteractions(boundaryFiber, wakeable)); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +beginWork$1 = function(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || didPerformWorkStackCursor.current ) didReceiveUpdate = !0; + else if (0 !== (renderLanes & updateLanes)) + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { - if (updateExpirationTime < renderExpirationTime) { - didReceiveUpdate = !1; - switch (workInProgress.tag) { - case 3: - pushHostRootContext(workInProgress); - break; - case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer( + didReceiveUpdate = !1; + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; + case 10: + updateLanes = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + push(valueCursor, context._currentValue2); + context._currentValue2 = updateLanes; + break; + case 12: + 0 !== (renderLanes & workInProgress.childLanes) && + (workInProgress.flags |= 4); + updateLanes = workInProgress.stateNode; + updateLanes.effectDuration = 0; + updateLanes.passiveEffectDuration = 0; + break; + case 13: + if (null !== workInProgress.memoizedState) { + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + workInProgress = bailoutOnAlreadyFinishedWork( + current, workInProgress, - workInProgress.stateNode.containerInfo + renderLanes ); - break; - case 10: - updateExpirationTime = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - push(valueCursor, context._currentValue2); - context._currentValue2 = updateExpirationTime; - break; - case 12: - workInProgress.childExpirationTime >= renderExpirationTime && - (workInProgress.effectTag |= 4); - updateExpirationTime = workInProgress.stateNode; - updateExpirationTime.effectDuration = 0; - updateExpirationTime.passiveEffectDuration = 0; - break; - case 13: - if (null !== workInProgress.memoizedState) { - updateExpirationTime = workInProgress.child.childExpirationTime; - if ( - 0 !== updateExpirationTime && - updateExpirationTime >= renderExpirationTime - ) - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - workInProgress = bailoutOnAlreadyFinishedWork( + return null !== workInProgress ? workInProgress.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + updateLanes = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 64)) { + if (updateLanes) + return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); - return null !== workInProgress ? workInProgress.sibling : null; - } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - updateExpirationTime = - workInProgress.childExpirationTime >= renderExpirationTime; - if (0 !== (current.effectTag & 64)) { - if (updateExpirationTime) - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 64; - } - context = workInProgress.memoizedState; - null !== context && - ((context.rendering = null), (context.tail = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (!updateExpirationTime) return null; - } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + workInProgress.flags |= 64; + } + context = workInProgress.memoizedState; + null !== context && + ((context.rendering = null), + (context.tail = null), + (context.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (updateLanes) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); } - didReceiveUpdate = !1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else didReceiveUpdate = !1; - workInProgress.expirationTime = 0; + workInProgress.lanes = 0; switch (workInProgress.tag) { case 2: - updateExpirationTime = workInProgress.type; + updateLanes = workInProgress.type; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); context = renderWithHooks( null, workInProgress, - updateExpirationTime, + updateLanes, current, context, - renderExpirationTime + renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -6692,7 +7046,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress.tag = 1; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - if (isContextProvider(updateExpirationTime)) { + if (isContextProvider(updateLanes)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; @@ -6701,53 +7055,41 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ? context.state : null; initializeUpdateQueue(workInProgress); - var getDerivedStateFromProps = - updateExpirationTime.getDerivedStateFromProps; + var getDerivedStateFromProps = updateLanes.getDerivedStateFromProps; "function" === typeof getDerivedStateFromProps && applyDerivedStateFromProps( workInProgress, - updateExpirationTime, + updateLanes, getDerivedStateFromProps, current ); context.updater = classComponentUpdater; workInProgress.stateNode = context; - context._reactInternalFiber = workInProgress; - mountClassInstance( - workInProgress, - updateExpirationTime, - current, - renderExpirationTime - ); + context._reactInternals = workInProgress; + mountClassInstance(workInProgress, updateLanes, current, renderLanes); workInProgress = finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, hasContext, - renderExpirationTime + renderLanes ); } else (workInProgress.tag = 0), - reconcileChildren( - null, - workInProgress, - context, - renderExpirationTime - ), + reconcileChildren(null, workInProgress, context, renderLanes), (workInProgress = workInProgress.child); return workInProgress; case 16: + context = workInProgress.elementType; a: { - context = workInProgress.elementType; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; - initializeLazyComponentType(context); - if (1 !== context._status) throw context._result; - context = context._result; + hasContext = context._init; + context = hasContext(context._payload); workInProgress.type = context; hasContext = workInProgress.tag = resolveLazyComponentTag(context); current = resolveDefaultProps(context, current); @@ -6758,7 +7100,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 1: @@ -6767,7 +7109,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 11: @@ -6776,7 +7118,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 14: @@ -6785,8 +7127,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, resolveDefaultProps(context.type, current), - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); break a; } @@ -6799,126 +7141,106 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return workInProgress; case 0: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateFunctionComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 1: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateClassComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 3: pushHostRootContext(workInProgress); - updateExpirationTime = workInProgress.updateQueue; - if (null === current || null === updateExpirationTime) + updateLanes = workInProgress.updateQueue; + if (null === current || null === updateLanes) throw Error( "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue." ); - updateExpirationTime = workInProgress.pendingProps; + updateLanes = workInProgress.pendingProps; context = workInProgress.memoizedState; context = null !== context ? context.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue( - workInProgress, - updateExpirationTime, - null, - renderExpirationTime - ); - updateExpirationTime = workInProgress.memoizedState.element; - updateExpirationTime === context + processUpdateQueue(workInProgress, updateLanes, null, renderLanes); + updateLanes = workInProgress.memoizedState.element; + updateLanes === context ? (workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes )) - : (reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + : (reconcileChildren(current, workInProgress, updateLanes, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; case 5: return ( pushHostContext(workInProgress), - (updateExpirationTime = workInProgress.pendingProps.children), + (updateLanes = workInProgress.pendingProps.children), markRef(current, workInProgress), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), - (workInProgress = workInProgress.child), - workInProgress + reconcileChildren(current, workInProgress, updateLanes, renderLanes), + workInProgress.child ); case 6: return null; case 13: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case 4: return ( pushHostContainer( workInProgress, workInProgress.stateNode.containerInfo ), - (updateExpirationTime = workInProgress.pendingProps), + (updateLanes = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, null, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes )) : reconcileChildren( current, workInProgress, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ), workInProgress.child ); case 11: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateForwardRef( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 7: @@ -6927,7 +7249,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -6937,27 +7259,27 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 12: return ( - (workInProgress.effectTag |= 4), - (updateExpirationTime = workInProgress.stateNode), - (updateExpirationTime.effectDuration = 0), - (updateExpirationTime.passiveEffectDuration = 0), + (workInProgress.flags |= 4), + (updateLanes = workInProgress.stateNode), + (updateLanes.effectDuration = 0), + (updateLanes.passiveEffectDuration = 0), reconcileChildren( current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 10: a: { - updateExpirationTime = workInProgress.type._context; + updateLanes = workInProgress.type._context; context = workInProgress.pendingProps; getDerivedStateFromProps = workInProgress.memoizedProps; hasContext = context.value; @@ -6969,9 +7291,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ((context$jscomp$0 = getDerivedStateFromProps.value), (hasContext = objectIs(context$jscomp$0, hasContext) ? 0 - : ("function" === - typeof updateExpirationTime._calculateChangedBits - ? updateExpirationTime._calculateChangedBits( + : ("function" === typeof updateLanes._calculateChangedBits + ? updateLanes._calculateChangedBits( context$jscomp$0, hasContext ) @@ -6985,7 +7306,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); break a; } @@ -7006,25 +7327,24 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ) { if ( - dependency.context === updateExpirationTime && + dependency.context === updateLanes && 0 !== (dependency.observedBits & hasContext) ) { 1 === context$jscomp$0.tag && - ((dependency = createUpdate(renderExpirationTime, null)), + ((dependency = createUpdate( + -1, + renderLanes & -renderLanes + )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); - context$jscomp$0.expirationTime < renderExpirationTime && - (context$jscomp$0.expirationTime = renderExpirationTime); + context$jscomp$0.lanes |= renderLanes; dependency = context$jscomp$0.alternate; - null !== dependency && - dependency.expirationTime < renderExpirationTime && - (dependency.expirationTime = renderExpirationTime); + null !== dependency && (dependency.lanes |= renderLanes); scheduleWorkOnParentPath( context$jscomp$0.return, - renderExpirationTime + renderLanes ); - list.expirationTime < renderExpirationTime && - (list.expirationTime = renderExpirationTime); + list.lanes |= renderLanes; break; } dependency = dependency.next; @@ -7062,7 +7382,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, context.children, - renderExpirationTime + renderLanes ); workInProgress = workInProgress.child; } @@ -7071,17 +7391,12 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return ( (context = workInProgress.type), (hasContext = workInProgress.pendingProps), - (updateExpirationTime = hasContext.children), - prepareToReadContext(workInProgress, renderExpirationTime), + (updateLanes = hasContext.children), + prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), - (updateExpirationTime = updateExpirationTime(context)), - (workInProgress.effectTag |= 1), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + (updateLanes = updateLanes(context)), + (workInProgress.flags |= 1), + reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); case 14: @@ -7097,8 +7412,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, hasContext, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); case 15: @@ -7107,48 +7422,43 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); case 17: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), - isContextProvider(updateExpirationTime) + isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) : (current = !1), - prepareToReadContext(workInProgress, renderExpirationTime), - constructClassInstance(workInProgress, updateExpirationTime, context), - mountClassInstance( - workInProgress, - updateExpirationTime, - context, - renderExpirationTime - ), + prepareToReadContext(workInProgress, renderLanes), + constructClassInstance(workInProgress, updateLanes, context), + mountClassInstance(workInProgress, updateLanes, context, renderLanes), finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, current, - renderExpirationTime + renderLanes ) ); case 19: - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + case 22: + return updateOffscreenComponent(current, workInProgress, renderLanes); + case 23: + return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( "Unknown unit of work tag (" + @@ -7156,16 +7466,21 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { "). This error is likely caused by a bug in React. Please file an issue." ); }; -function scheduleInteractions(root, expirationTime, interactions) { +function markSpawnedWork(lane) { + null === spawnedWorkDuringRender + ? (spawnedWorkDuringRender = [lane]) + : spawnedWorkDuringRender.push(lane); +} +function scheduleInteractions(root, lane, interactions) { if (0 < interactions.size) { var pendingInteractionMap = root.pendingInteractionMap, - pendingInteractions = pendingInteractionMap.get(expirationTime); + pendingInteractions = pendingInteractionMap.get(lane); null != pendingInteractions ? interactions.forEach(function(interaction) { pendingInteractions.has(interaction) || interaction.__count++; pendingInteractions.add(interaction); }) - : (pendingInteractionMap.set(expirationTime, new Set(interactions)), + : (pendingInteractionMap.set(lane, new Set(interactions)), interactions.forEach(function(interaction) { interaction.__count++; })); @@ -7173,20 +7488,20 @@ function scheduleInteractions(root, expirationTime, interactions) { if (null !== pendingInteractionMap) pendingInteractionMap.onWorkScheduled( interactions, - 1e3 * expirationTime + root.interactionThreadID + 1e3 * lane + root.interactionThreadID ); } } -function schedulePendingInteractions(root, expirationTime) { - scheduleInteractions(root, expirationTime, tracing.__interactionsRef.current); +function schedulePendingInteractions(root, lane) { + scheduleInteractions(root, lane, tracing.__interactionsRef.current); } -function startWorkOnPendingInteractions(root, expirationTime) { +function startWorkOnPendingInteractions(root, lanes) { var interactions = new Set(); root.pendingInteractionMap.forEach(function( scheduledInteractions, - scheduledExpirationTime + scheduledLane ) { - scheduledExpirationTime >= expirationTime && + 0 !== (lanes & scheduledLane) && scheduledInteractions.forEach(function(interaction) { return interactions.add(interaction); }); @@ -7195,7 +7510,7 @@ function startWorkOnPendingInteractions(root, expirationTime) { if (0 < interactions.size) { var subscriber = tracing.__subscriberRef.current; if (null !== subscriber) { - root = 1e3 * expirationTime + root.interactionThreadID; + root = 1e3 * lanes + root.interactionThreadID; try { subscriber.onWorkStarted(interactions, root); } catch (error) { @@ -7206,14 +7521,14 @@ function startWorkOnPendingInteractions(root, expirationTime) { } } } -function finishPendingInteractions(root, committedExpirationTime) { - var earliestRemainingTimeAfterCommit = root.firstPendingTime; +function finishPendingInteractions(root, committedLanes) { + var remainingLanesAfterCommit = root.pendingLanes; try { var subscriber = tracing.__subscriberRef.current; if (null !== subscriber && 0 < root.memoizedInteractions.size) subscriber.onWorkStopped( root.memoizedInteractions, - 1e3 * committedExpirationTime + root.interactionThreadID + 1e3 * committedLanes + root.interactionThreadID ); } catch (error) { scheduleCallback(99, function() { @@ -7221,54 +7536,23 @@ function finishPendingInteractions(root, committedExpirationTime) { }); } finally { var pendingInteractionMap = root.pendingInteractionMap; - pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - scheduledExpirationTime > earliestRemainingTimeAfterCommit && - (pendingInteractionMap.delete(scheduledExpirationTime), + pendingInteractionMap.forEach(function(scheduledInteractions, lane) { + 0 === (remainingLanesAfterCommit & lane) && + (pendingInteractionMap.delete(lane), scheduledInteractions.forEach(function(interaction) { interaction.__count--; if (null !== subscriber && 0 === interaction.__count) try { subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error) { + } catch (error$102) { scheduleCallback(99, function() { - throw error; + throw error$102; }); } })); }); } } -var onCommitFiberRoot = null, - onCommitFiberUnmount = null, - isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__; -function injectInternals(internals) { - if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled || !hook.supportsFiber) return !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = function(root, expirationTime) { - try { - var didError = 64 === (root.current.effectTag & 64), - currentTime = 1073741821 - ((now() / 10) | 0), - priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - hook.onCommitFiberRoot(rendererID, root, priorityLevel, didError); - } catch (err) {} - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) {} - }; - } catch (err) {} - return !0; -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -7278,14 +7562,17 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; - this.childExpirationTime = this.expirationTime = 0; + this.childLanes = this.lanes = 0; this.alternate = null; this.actualDuration = 0; this.actualStartTime = -1; this.treeBaseDuration = this.selfBaseDuration = 0; } +function createFiber(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); +} function shouldConstruct(Component) { Component = Component.prototype; return !(!Component || !Component.isReactComponent); @@ -7303,7 +7590,7 @@ function resolveLazyComponentTag(Component) { function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress - ? ((workInProgress = new FiberNode( + ? ((workInProgress = createFiber( current.tag, pendingProps, current.key, @@ -7315,14 +7602,15 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.alternate = current), (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), - (workInProgress.effectTag = 0), + (workInProgress.type = current.type), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null), (workInProgress.actualDuration = 0), (workInProgress.actualStartTime = -1)); - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -7331,11 +7619,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.dependencies = null === pendingProps ? null - : { - expirationTime: pendingProps.expirationTime, - firstContext: pendingProps.firstContext, - responders: pendingProps.responders - }; + : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext }; workInProgress.sibling = current.sibling; workInProgress.index = current.index; workInProgress.ref = current.ref; @@ -7349,7 +7633,7 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { var fiberTag = 2; owner = type; @@ -7358,15 +7642,10 @@ function createFiberFromTypeAndProps( else a: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_CONCURRENT_MODE_TYPE: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = 8; - mode |= 7; + mode |= 16; break; case REACT_STRICT_MODE_TYPE: fiberTag = 8; @@ -7374,26 +7653,35 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: return ( - (type = new FiberNode(12, pendingProps, key, mode | 8)), + (type = createFiber(12, pendingProps, key, mode | 8)), (type.elementType = REACT_PROFILER_TYPE), (type.type = REACT_PROFILER_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), (type.stateNode = { effectDuration: 0, passiveEffectDuration: 0 }), type ); case REACT_SUSPENSE_TYPE: return ( - (type = new FiberNode(13, pendingProps, key, mode)), + (type = createFiber(13, pendingProps, key, mode)), (type.type = REACT_SUSPENSE_TYPE), (type.elementType = REACT_SUSPENSE_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_LIST_TYPE: return ( - (type = new FiberNode(19, pendingProps, key, mode)), + (type = createFiber(19, pendingProps, key, mode)), (type.elementType = REACT_SUSPENSE_LIST_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), + type + ); + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + case REACT_LEGACY_HIDDEN_TYPE: + return ( + (type = createFiber(23, pendingProps, key, mode)), + (type.elementType = REACT_LEGACY_HIDDEN_TYPE), + (type.lanes = lanes), type ); default: @@ -7415,9 +7703,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7425,30 +7710,36 @@ function createFiberFromTypeAndProps( "." ); } - key = new FiberNode(fiberTag, pendingProps, key, mode); + key = createFiber(fiberTag, pendingProps, key, mode); key.elementType = type; key.type = owner; - key.expirationTime = expirationTime; + key.lanes = lanes; return key; } -function createFiberFromFragment(elements, mode, expirationTime, key) { - elements = new FiberNode(7, elements, key, mode); - elements.expirationTime = expirationTime; +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; return elements; } -function createFiberFromText(content, mode, expirationTime) { - content = new FiberNode(6, content, null, mode); - content.expirationTime = expirationTime; +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; return content; } -function createFiberFromPortal(portal, mode, expirationTime) { - mode = new FiberNode( +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( 4, null !== portal.children ? portal.children : [], portal.key, mode ); - mode.expirationTime = expirationTime; + mode.lanes = lanes; mode.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -7458,54 +7749,34 @@ function createFiberFromPortal(portal, mode, expirationTime) { } function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; - this.pingCache = this.pendingChildren = null; - this.finishedExpirationTime = 0; - this.finishedWork = null; + this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; this.timeoutHandle = -1; this.pendingContext = this.context = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = 90; - this.lastExpiredTime = this.lastPingedTime = this.nextKnownPendingLevel = this.lastSuspendedTime = this.firstSuspendedTime = this.firstPendingTime = 0; + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; + this.entanglements = createLaneMap(0); this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); } -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - root = root.lastSuspendedTime; - return ( - 0 !== firstSuspendedTime && - firstSuspendedTime >= expirationTime && - root <= expirationTime - ); -} -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime, - lastSuspendedTime = root.lastSuspendedTime; - firstSuspendedTime < expirationTime && - (root.firstSuspendedTime = expirationTime); - if (lastSuspendedTime > expirationTime || 0 === firstSuspendedTime) - root.lastSuspendedTime = expirationTime; - expirationTime <= root.lastPingedTime && (root.lastPingedTime = 0); - expirationTime <= root.lastExpiredTime && (root.lastExpiredTime = 0); -} -function markRootUpdatedAtTime(root, expirationTime) { - expirationTime > root.firstPendingTime && - (root.firstPendingTime = expirationTime); - var firstSuspendedTime = root.firstSuspendedTime; - 0 !== firstSuspendedTime && - (expirationTime >= firstSuspendedTime - ? (root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = 0) - : expirationTime >= root.lastSuspendedTime && - (root.lastSuspendedTime = expirationTime + 1), - expirationTime > root.nextKnownPendingLevel && - (root.nextKnownPendingLevel = expirationTime)); +function createPortal(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } function findHostInstance(component) { - var fiber = component._reactInternalFiber; + var fiber = component._reactInternals; if (void 0 === fiber) { if ("function" === typeof component.render) throw Error("Unable to find node on an unmounted component."); @@ -7519,11 +7790,10 @@ function findHostInstance(component) { } function updateContainer(element, container, parentComponent, callback) { var current = container.current, - currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, current, suspenseConfig); + eventTime = requestEventTime(), + lane = requestUpdateLane(current); a: if (parentComponent) { - parentComponent = parentComponent._reactInternalFiber; + parentComponent = parentComponent._reactInternals; b: { if ( getNearestMountedFiber(parentComponent) !== parentComponent || @@ -7532,22 +7802,23 @@ function updateContainer(element, container, parentComponent, callback) { throw Error( "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." ); - var parentContext = parentComponent; + var JSCompiler_inline_result = parentComponent; do { - switch (parentContext.tag) { + switch (JSCompiler_inline_result.tag) { case 3: - parentContext = parentContext.stateNode.context; + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; break b; case 1: - if (isContextProvider(parentContext.type)) { - parentContext = - parentContext.stateNode + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode .__reactInternalMemoizedMergedChildContext; break b; } } - parentContext = parentContext.return; - } while (null !== parentContext); + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); throw Error( "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." ); @@ -7558,34 +7829,26 @@ function updateContainer(element, container, parentComponent, callback) { parentComponent = processChildContext( parentComponent, Component, - parentContext + JSCompiler_inline_result ); break a; } } - parentComponent = parentContext; + parentComponent = JSCompiler_inline_result; } else parentComponent = emptyContextObject; null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(currentTime, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); enqueueUpdate(current, container); - scheduleWork(current, currentTime); - return currentTime; + scheduleUpdateOnFiber(current, lane, eventTime); + return lane; } -function createPortal(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; +function emptyFindFiberByHostInstance() { + return null; } function findNodeHandle(componentOrHandle) { if (null == componentOrHandle) return null; @@ -7607,53 +7870,70 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - executionContext === NoContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; -var roots = new Map(); -(function(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: null, - overrideProps: null, - setSuspenseHandler: null, - scheduleUpdate: null, - currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - fiber = findCurrentHostFiber(fiber); - return null === fiber ? null : fiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - return findFiberByHostInstance ? findFiberByHostInstance(instance) : null; - }, - findHostInstancesForRefresh: null, - scheduleRefresh: null, - scheduleRoot: null, - setRefreshHandler: null, - getCurrentFiber: null - }); -})({ - findFiberByHostInstance: getInstanceFromInstance, - bundleType: 0, - version: "16.13.0", - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: function() { - throw Error( - "getInspectorDataForViewTag() is not available in production" - ); - }, - getInspectorDataForViewAtPoint: function() { - throw Error( - "getInspectorDataForViewAtPoint() is not available in production." - ); - }.bind(null, findNodeHandle) - } -}); +var roots = new Map(), + devToolsConfig$jscomp$inline_887 = { + findFiberByHostInstance: getInstanceFromInstance, + bundleType: 0, + version: "17.0.1-454c2211c", + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: function() { + throw Error( + "getInspectorDataForViewTag() is not available in production" + ); + }, + getInspectorDataForViewAtPoint: function() { + throw Error( + "getInspectorDataForViewAtPoint() is not available in production." + ); + }.bind(null, findNodeHandle) + } + }; +var internals$jscomp$inline_1087 = { + bundleType: devToolsConfig$jscomp$inline_887.bundleType, + version: devToolsConfig$jscomp$inline_887.version, + rendererPackageName: devToolsConfig$jscomp$inline_887.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_887.rendererConfig, + overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, + overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, + setSuspenseHandler: null, + scheduleUpdate: null, + currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, + findHostInstanceByFiber: function(fiber) { + fiber = findCurrentHostFiber(fiber); + return null === fiber ? null : fiber.stateNode; + }, + findFiberByHostInstance: + devToolsConfig$jscomp$inline_887.findFiberByHostInstance || + emptyFindFiberByHostInstance, + findHostInstancesForRefresh: null, + scheduleRefresh: null, + scheduleRoot: null, + setRefreshHandler: null, + getCurrentFiber: null +}; +if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { + var hook$jscomp$inline_1088 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if ( + !hook$jscomp$inline_1088.isDisabled && + hook$jscomp$inline_1088.supportsFiber + ) + try { + (rendererID = hook$jscomp$inline_1088.inject( + internals$jscomp$inline_1087 + )), + (injectedHook = hook$jscomp$inline_1088); + } catch (err) {} +} exports.createPortal = function(children, containerTag) { return createPortal( children, @@ -7693,12 +7973,17 @@ exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { root = new FiberRootNode(containerTag, 0, !1); - var uninitializedFiber = 0; - isDevToolsPresent && (uninitializedFiber |= 8); - uninitializedFiber = new FiberNode(3, null, null, uninitializedFiber); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - initializeUpdateQueue(uninitializedFiber); + var JSCompiler_inline_result = 0; + isDevToolsPresent && (JSCompiler_inline_result |= 8); + JSCompiler_inline_result = createFiber( + 3, + null, + null, + JSCompiler_inline_result + ); + root.current = JSCompiler_inline_result; + JSCompiler_inline_result.stateNode = root; + initializeUpdateQueue(JSCompiler_inline_result); roots.set(containerTag, root); } updateContainer(element, root, null, callback); diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index c88a74b6a040b1..6b9ea503d3866e 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -139,7 +139,7 @@ var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; ) { // If document doesn't exist we know for sure we will crash in this method // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebookincubator/create-react-app/issues/3482 + // errors: https://github.com/facebook/create-react-app/issues/3482 // So we preemptively throw with a better message instead. if (!(typeof document !== "undefined")) { throw Error( @@ -263,7 +263,7 @@ var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; error = new Error( "A cross-origin error was thrown. React doesn't have access to " + "the actual error object in development. " + - "See https://fb.me/react-crossorigin-error for more information." + "See https://reactjs.org/link/crossorigin-error for more information." ); } @@ -806,13 +806,6 @@ addEventPoolingTo(SyntheticEvent); */ function getPooledWarningPropertyDefinition(propName, getVal) { - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; - function set(val) { var action = isFunction ? "setting the method" : "setting the property"; warn(action, "This is effectively a no-op"); @@ -834,13 +827,20 @@ function getPooledWarningPropertyDefinition(propName, getVal) { "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", + "See https://reactjs.org/link/event-pooling for more information.", action, propName, result ); } } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; } function createOrGetPooledEvent( @@ -1239,9 +1239,8 @@ var DehydratedFragment = 18; var SuspenseListComponent = 19; var FundamentalComponent = 20; var ScopeComponent = 21; -var Block = 22; -var OffscreenComponent = 23; -var LegacyHiddenComponent = 24; +var OffscreenComponent = 22; +var LegacyHiddenComponent = 23; /** * Instance of element that should respond to touch/move types of interactions, @@ -2865,8 +2864,6 @@ var REACT_SUSPENSE_TYPE = 0xead1; var REACT_SUSPENSE_LIST_TYPE = 0xead8; var REACT_MEMO_TYPE = 0xead3; var REACT_LAZY_TYPE = 0xead4; -var REACT_BLOCK_TYPE = 0xead9; -var REACT_SERVER_BLOCK_TYPE = 0xeada; var REACT_FUNDAMENTAL_TYPE = 0xead5; var REACT_SCOPE_TYPE = 0xead7; var REACT_OPAQUE_ID_TYPE = 0xeae0; @@ -2888,8 +2885,6 @@ if (typeof Symbol === "function" && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); - REACT_SERVER_BLOCK_TYPE = symbolFor("react.server.block"); REACT_FUNDAMENTAL_TYPE = symbolFor("react.fundamental"); REACT_SCOPE_TYPE = symbolFor("react.scope"); REACT_OPAQUE_ID_TYPE = symbolFor("react.opaque.id"); @@ -2987,9 +2982,6 @@ function getComponentName(type) { case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); - case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; @@ -3007,9 +2999,15 @@ function getComponentName(type) { return null; } +// The rest of the flags are static for better dead code elimination. +var enableProfilerTimer = true; +var enableFundamentalAPI = false; +var warnAboutStringRefs = false; +var enableNewReconciler = false; + // Don't change these two values. They're used by React Dev Tools. -var NoEffect = - /* */ +var NoFlags = + /* */ 0; var PerformedWork = /* */ @@ -3044,41 +3042,32 @@ var Snapshot = 256; var Passive = /* */ - 512; // TODO (effects) Remove this bit once the new reconciler is synced to the old. - -var PassiveUnmountPendingDev = - /* */ - 8192; + 512; var Hydrating = /* */ 1024; var HydratingAndUpdate = /* */ - 1028; // Passive & Update & Callback & Ref & Snapshot - -var LifecycleEffectMask = - /* */ - 932; // Union of all host effects + 1028; +var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ - 2047; // These are not really side effects, but we still reuse this field. + 4095; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ - 2048; + 4096; var ShouldCapture = /* */ - 4096; + 8192; // TODO (effects) Remove this bit once the new reconciler is synced to the old. + +var PassiveUnmountPendingDev = + /* */ + 16384; var ForceUpdateForLegacySuspense = /* */ - 16384; // Static tags describe aspects of a fiber that are not specific to a render, - -// The rest of the flags are static for better dead code elimination. -var enableProfilerTimer = true; -var enableFundamentalAPI = false; -var warnAboutStringRefs = false; -var enableNewReconciler = false; + 32768; // Static tags describe aspects of a fiber that are not specific to a render, var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -3093,7 +3082,7 @@ function getNearestMountedFiber(fiber) { do { node = nextNode; - if ((node.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { // This is an insertion or in-progress hydration. The nearest possible // mounted fiber is the parent but we need to continue to figure out // if that one is still mounted. @@ -3873,104 +3862,102 @@ function warnForStyleProps(props, validAttributes) { } } -var ReactNativeFiberHostComponent = - /*#__PURE__*/ - (function() { - function ReactNativeFiberHostComponent( - tag, - viewConfig, - internalInstanceHandleDEV - ) { - this._nativeTag = tag; - this._children = []; - this.viewConfig = viewConfig; +var ReactNativeFiberHostComponent = /*#__PURE__*/ (function() { + function ReactNativeFiberHostComponent( + tag, + viewConfig, + internalInstanceHandleDEV + ) { + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; - { - this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; - } + { + this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; } + } - var _proto = ReactNativeFiberHostComponent.prototype; + var _proto = ReactNativeFiberHostComponent.prototype; - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; - _proto.measure = function measure(callback) { - ReactNativePrivateInterface.UIManager.measure( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + _proto.measure = function measure(callback) { + ReactNativePrivateInterface.UIManager.measure( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - _proto.measureInWindow = function measureInWindow(callback) { - ReactNativePrivateInterface.UIManager.measureInWindow( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + _proto.measureInWindow = function measureInWindow(callback) { + ReactNativePrivateInterface.UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - var relativeNode; + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ + { + var relativeNode; - if (typeof relativeToNativeNode === "number") { - // Already a node handle - relativeNode = relativeToNativeNode; - } else { - var nativeNode = relativeToNativeNode; + if (typeof relativeToNativeNode === "number") { + // Already a node handle + relativeNode = relativeToNativeNode; + } else { + var nativeNode = relativeToNativeNode; - if (nativeNode._nativeTag) { - relativeNode = nativeNode._nativeTag; - } + if (nativeNode._nativeTag) { + relativeNode = nativeNode._nativeTag; } + } - if (relativeNode == null) { - { - error( - "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." - ); - } - - return; + if (relativeNode == null) { + { + error( + "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." + ); } - ReactNativePrivateInterface.UIManager.measureLayout( - this._nativeTag, - relativeNode, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; + return; + } - _proto.setNativeProps = function setNativeProps(nativeProps) { - { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); - } + ReactNativePrivateInterface.UIManager.measureLayout( + this._nativeTag, + relativeNode, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + }; - var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. - // This is an expensive no-op for Android, and causes an unnecessary - // view invalidation for certain components (eg RCTTextInput) on iOS. + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } - if (updatePayload != null) { - ReactNativePrivateInterface.UIManager.updateView( - this._nativeTag, - this.viewConfig.uiViewClassName, - updatePayload - ); - } - }; + var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. - return ReactNativeFiberHostComponent; - })(); // eslint-disable-next-line no-unused-expressions + if (updatePayload != null) { + ReactNativePrivateInterface.UIManager.updateView( + this._nativeTag, + this.viewConfig.uiViewClassName, + updatePayload + ); + } + }; + + return ReactNativeFiberHostComponent; +})(); // eslint-disable-next-line no-unused-expressions // can re-export everything from this module. @@ -4547,9 +4534,6 @@ function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { // Memo may contain any component type so we recursively resolve it. return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); - case REACT_BLOCK_TYPE: - return describeFunctionComponentFrame(type._render, source, ownerFn); - case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; @@ -4890,7 +4874,7 @@ function processChildContext(fiber, type, parentContext) { checkPropTypes(childContextTypes, childContext, "child context", name); } - return Object.assign({}, parentContext, {}, childContext); + return Object.assign({}, parentContext, childContext); } } @@ -5017,7 +5001,7 @@ function injectInternals(internals) { error( "The installed version of React DevTools is too old and will not work " + "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" + "https://reactjs.org/link/react-devtools" ); } // DevTools exists, even though it doesn't support Fiber. @@ -5058,7 +5042,7 @@ function onScheduleRoot(root, children) { function onCommitRoot(root, priorityLevel) { if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { try { - var didError = (root.current.effectTag & DidCapture) === DidCapture; + var didError = (root.current.flags & DidCapture) === DidCapture; if (enableProfilerTimer) { injectedHook.onCommitFiberRoot( @@ -5111,7 +5095,7 @@ var Scheduler_now = Scheduler.unstable_now; ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } @@ -5127,18 +5111,16 @@ var IdlePriority = 95; // NoPriority is the absence of priority. Also React-only var NoPriority = 90; var initialTimeMs = Scheduler_now(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. -var SyncLanePriority = 17; -var SyncBatchedLanePriority = 16; -var InputDiscreteHydrationLanePriority = 15; -var InputDiscreteLanePriority = 14; -var InputContinuousHydrationLanePriority = 13; -var InputContinuousLanePriority = 12; -var DefaultHydrationLanePriority = 11; -var DefaultLanePriority = 10; -var TransitionShortHydrationLanePriority = 9; -var TransitionShortLanePriority = 8; -var TransitionLongHydrationLanePriority = 7; -var TransitionLongLanePriority = 6; +var SyncLanePriority = 15; +var SyncBatchedLanePriority = 14; +var InputDiscreteHydrationLanePriority = 13; +var InputDiscreteLanePriority = 12; +var InputContinuousHydrationLanePriority = 11; +var InputContinuousLanePriority = 10; +var DefaultHydrationLanePriority = 9; +var DefaultLanePriority = 8; +var TransitionHydrationPriority = 7; +var TransitionPriority = 6; var RetryLanePriority = 5; var SelectiveHydrationLanePriority = 4; var IdleHydrationLanePriority = 3; @@ -5176,21 +5158,18 @@ var DefaultHydrationLane = var DefaultLanes = /* */ 3584; -var TransitionShortHydrationLane = - /* */ +var TransitionHydrationLane = + /* */ 4096; -var TransitionShortLanes = - /* */ - 122880; -var TransitionLongHydrationLane = - /* */ - 131072; -var TransitionLongLanes = - /* */ - 3932160; +var TransitionLanes = + /* */ + 4186112; var RetryLanes = /* */ 62914560; +var SomeRetryLane = + /* */ + 33554432; var SelectiveHydrationLane = /* */ 67108864; @@ -5207,7 +5186,6 @@ var OffscreenLane = /* */ 1073741824; var NoTimestamp = -1; -function setCurrentUpdateLanePriority(newLanePriority) {} // "Registers" used to "return" multiple values // Used by getHighestPriorityLanes and getNextLanes: var return_highestLanePriority = DefaultLanePriority; @@ -5259,28 +5237,16 @@ function getHighestPriorityLanes(lanes) { return defaultLanes; } - if ((lanes & TransitionShortHydrationLane) !== NoLanes) { - return_highestLanePriority = TransitionShortHydrationLanePriority; - return TransitionShortHydrationLane; - } - - var transitionShortLanes = TransitionShortLanes & lanes; - - if (transitionShortLanes !== NoLanes) { - return_highestLanePriority = TransitionShortLanePriority; - return transitionShortLanes; - } - - if ((lanes & TransitionLongHydrationLane) !== NoLanes) { - return_highestLanePriority = TransitionLongHydrationLanePriority; - return TransitionLongHydrationLane; + if ((lanes & TransitionHydrationLane) !== NoLanes) { + return_highestLanePriority = TransitionHydrationPriority; + return TransitionHydrationLane; } - var transitionLongLanes = TransitionLongLanes & lanes; + var transitionLanes = TransitionLanes & lanes; - if (transitionLongLanes !== NoLanes) { - return_highestLanePriority = TransitionLongLanePriority; - return transitionLongLanes; + if (transitionLanes !== NoLanes) { + return_highestLanePriority = TransitionPriority; + return transitionLanes; } var retryLanes = RetryLanes & lanes; @@ -5354,10 +5320,8 @@ function lanePriorityToSchedulerPriority(lanePriority) { case DefaultHydrationLanePriority: case DefaultLanePriority: - case TransitionShortHydrationLanePriority: - case TransitionShortLanePriority: - case TransitionLongHydrationLanePriority: - case TransitionLongLanePriority: + case TransitionHydrationPriority: + case TransitionPriority: case SelectiveHydrationLanePriority: case RetryLanePriority: return NormalPriority; @@ -5515,8 +5479,22 @@ function computeExpirationTime(lane, currentTime) { if (priority >= InputContinuousLanePriority) { // User interactions should expire slightly more quickly. - return currentTime + 1000; - } else if (priority >= TransitionLongLanePriority) { + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. When + // we made it larger, a product metric in www regressed, suggesting there's + // a user interaction that's being starved by a series of synchronous + // updates. If that theory is correct, the proper solution is to fix the + // starvation. However, this scenario supports the idea that expiration + // times are an important safeguard when starvation does happen. + // + // Also note that, in the case of user input specifically, this will soon no + // longer be an issue because we plan to make user input synchronous by + // default (until you enter `startTransition`, of course.) + // + // If weren't planning to make these updates synchronous soon anyway, I + // would probably make this number a configurable parameter. + return currentTime + 250; + } else if (priority >= TransitionPriority) { return currentTime + 5000; } else { // Anything idle priority or lower should never expire. @@ -5582,6 +5560,9 @@ function includesNonIdleWork(lanes) { } function includesOnlyRetries(lanes) { return (lanes & RetryLanes) === lanes; +} +function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; } // To ensure consistency across multiple updates in the same event, this should // be a pure function, so that it always returns the same lane for given inputs. @@ -5624,9 +5605,7 @@ function findUpdateLane(lanePriority, wipLanes) { if (_lane3 === NoLane) { // If all the default lanes are already being worked on, look for a // lane in the transition range. - _lane3 = pickArbitraryLane( - (TransitionShortLanes | TransitionLongLanes) & ~wipLanes - ); + _lane3 = pickArbitraryLane(TransitionLanes & ~wipLanes); if (_lane3 === NoLane) { // All the transition lanes are taken, too. This should be very @@ -5639,9 +5618,8 @@ function findUpdateLane(lanePriority, wipLanes) { return _lane3; } - case TransitionShortLanePriority: // Should be handled by findTransitionLane instead + case TransitionPriority: // Should be handled by findTransitionLane instead - case TransitionLongLanePriority: case RetryLanePriority: // Should be handled by findRetryLane instead break; @@ -5664,54 +5642,24 @@ function findUpdateLane(lanePriority, wipLanes) { } // To ensure consistency across multiple updates in the same event, this should // be pure function, so that it always returns the same lane for given inputs. -function findTransitionLane(lanePriority, wipLanes, pendingLanes) { - if (lanePriority === TransitionShortLanePriority) { - // First look for lanes that are completely unclaimed, i.e. have no - // pending work. - var lane = pickArbitraryLane(TransitionShortLanes & ~pendingLanes); - - if (lane === NoLane) { - // If all lanes have pending work, look for a lane that isn't currently - // being worked on. - lane = pickArbitraryLane(TransitionShortLanes & ~wipLanes); - - if (lane === NoLane) { - // If everything is being worked on, pick any lane. This has the - // effect of interrupting the current work-in-progress. - lane = pickArbitraryLane(TransitionShortLanes); - } - } - - return lane; - } - - if (lanePriority === TransitionLongLanePriority) { - // First look for lanes that are completely unclaimed, i.e. have no - // pending work. - var _lane4 = pickArbitraryLane(TransitionLongLanes & ~pendingLanes); +function findTransitionLane(wipLanes, pendingLanes) { + // First look for lanes that are completely unclaimed, i.e. have no + // pending work. + var lane = pickArbitraryLane(TransitionLanes & ~pendingLanes); - if (_lane4 === NoLane) { - // If all lanes have pending work, look for a lane that isn't currently - // being worked on. - _lane4 = pickArbitraryLane(TransitionLongLanes & ~wipLanes); + if (lane === NoLane) { + // If all lanes have pending work, look for a lane that isn't currently + // being worked on. + lane = pickArbitraryLane(TransitionLanes & ~wipLanes); - if (_lane4 === NoLane) { - // If everything is being worked on, pick any lane. This has the - // effect of interrupting the current work-in-progress. - _lane4 = pickArbitraryLane(TransitionLongLanes); - } + if (lane === NoLane) { + // If everything is being worked on, pick any lane. This has the + // effect of interrupting the current work-in-progress. + lane = pickArbitraryLane(TransitionLanes); } - - return _lane4; } - { - throw Error( - "Invalid transition priority: " + - lanePriority + - ". This is a bug in React." - ); - } + return lane; } // To ensure consistency across multiple updates in the same event, this should // be pure function, so that it always returns the same lane for given inputs. @@ -5776,7 +5724,15 @@ function laneToLanes(lane) { return lane; } function createLaneMap(initial) { - return new Array(TotalLanes).fill(initial); + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; + + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } + + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But @@ -5817,9 +5773,6 @@ function markRootSuspended(root, suspendedLanes) { function markRootPinged(root, pingedLanes, eventTime) { root.pingedLanes |= root.suspendedLanes & pingedLanes; } -function markRootExpired(root, expiredLanes) { - root.expiredLanes |= expiredLanes & root.pendingLanes; -} function hasDiscreteLanes(lanes) { return (lanes & InputDiscreteLanes) !== NoLanes; } @@ -5903,7 +5856,7 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } @@ -6032,88 +5985,40 @@ function flushSyncCallbackQueueImpl() { isFlushingSyncQueue = true; var i = 0; - try { - var _isSync = true; - var queue = syncQueue; - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediatePriority$1, function() { - for (; i < queue.length; i++) { - var callback = queue[i]; - - do { - callback = callback(_isSync); - } while (callback !== null); - } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick - - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue - ); - throw error; - } finally { - isFlushingSyncQueue = false; + { + try { + var _isSync2 = true; + var _queue = syncQueue; + runWithPriority(ImmediatePriority$1, function() { + for (; i < _queue.length; i++) { + var callback = _queue[i]; + + do { + callback = callback(_isSync2); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick + + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue + ); + throw error; + } finally { + isFlushingSyncQueue = false; + } } } } -function describeFiber(fiber) { - var owner = fiber._debugOwner ? fiber._debugOwner.type : null; - var source = fiber._debugSource; - - switch (fiber.tag) { - case HostComponent: - return describeBuiltInComponentFrame(fiber.type, source, owner); - - case LazyComponent: - return describeBuiltInComponentFrame("Lazy", source, owner); - - case SuspenseComponent: - return describeBuiltInComponentFrame("Suspense", source, owner); - - case SuspenseListComponent: - return describeBuiltInComponentFrame("SuspenseList", source, owner); - - case FunctionComponent: - case IndeterminateComponent: - case SimpleMemoComponent: - return describeFunctionComponentFrame(fiber.type, source, owner); - - case ForwardRef: - return describeFunctionComponentFrame(fiber.type.render, source, owner); - - case Block: - return describeFunctionComponentFrame(fiber.type._render, source, owner); - - case ClassComponent: - return describeClassComponentFrame(fiber.type, source, owner); - - default: - return ""; - } -} - -function getStackByFiberInDevAndProd(workInProgress) { - try { - var info = ""; - var node = workInProgress; - - do { - info += describeFiber(node); - node = node.return; - } while (node); - - return info; - } catch (x) { - return "\nError generating stack: " + x.message + "\n" + x.stack; - } -} +// TODO: this is special because it gets imported during build. +var ReactVersion = "17.0.1-454c2211c"; var NoMode = 0; var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root @@ -6124,6 +6029,12 @@ var ConcurrentMode = 4; var ProfileMode = 8; var DebugTracingMode = 16; +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var NoTransition = 0; +function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; +} + /** * inlined Object.is polyfill to avoid requiring consumers ship their own * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is @@ -6176,6 +6087,55 @@ function shallowEqual(objA, objB) { return true; } +function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; + + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); + + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); + + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); + + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); + + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); + + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); + + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); + + default: + return ""; + } +} + +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; + + do { + info += describeFiber(node); + node = node.return; + } while (node); + + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } +} + var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; var current = null; var isRendering = false; @@ -6404,7 +6364,7 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + "\nPlease update the following components: %s", sortedNames @@ -6419,11 +6379,11 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* If you're updating state whenever props change, " + "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + "\nPlease update the following components: %s", _sortedNames ); @@ -6437,7 +6397,7 @@ var ReactStrictModeWarnings = { error( "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "\nPlease update the following components: %s", _sortedNames2 @@ -6449,7 +6409,7 @@ var ReactStrictModeWarnings = { warn( "componentWillMount has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + @@ -6467,11 +6427,11 @@ var ReactStrictModeWarnings = { warn( "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* If you're updating state whenever props change, refactor your " + "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + "To rename all deprecated lifecycles to their new names, you can run " + @@ -6486,7 +6446,7 @@ var ReactStrictModeWarnings = { warn( "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + "* Move data fetching code or side effects to componentDidUpdate.\n" + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + @@ -6559,7 +6519,7 @@ var ReactStrictModeWarnings = { "\n\nThe old API will be supported in all 16.x releases, but applications " + "using it should migrate to the new version." + "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://fb.me/react-legacy-context", + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", sortedNames ); } finally { @@ -6750,8 +6710,7 @@ function propagateContextChange( // Schedule a force update on the work-in-progress. var update = createUpdate( NoTimestamp, - pickArbitraryLane(renderLanes), - null + pickArbitraryLane(renderLanes) ); update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the // update to the current fiber, too, which means it will persist even if @@ -6937,11 +6896,10 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue = clone; } } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { var update = { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: UpdateState, payload: null, callback: null, @@ -7016,7 +6974,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: update.eventTime, lane: update.lane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, @@ -7108,8 +7065,8 @@ function getStateFromUpdate( } case CaptureUpdate: { - workInProgress.effectTag = - (workInProgress.effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; } // Intentional fallthrough @@ -7235,7 +7192,6 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { var clone = { eventTime: updateEventTime, lane: updateLane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, @@ -7259,21 +7215,13 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { // it. Using NoLane works because 0 is a subset of all bitmasks, so // this will never be skipped by the check above. lane: NoLane, - suspenseConfig: update.suspenseConfig, tag: update.tag, payload: update.payload, callback: update.callback, next: null }; newLastBaseUpdate = newLastBaseUpdate.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reversible value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig(updateEventTime, update.suspenseConfig); // Process this update. + } // Process this update. newState = getStateFromUpdate( workInProgress, @@ -7286,7 +7234,7 @@ function processUpdateQueue(workInProgress, props, instance, renderLanes) { var callback = update.callback; if (callback !== null) { - workInProgress.effectTag |= Callback; + workInProgress.flags |= Callback; var effects = queue.effects; if (effects === null) { @@ -7378,11 +7326,6 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -function requestCurrentSuspenseConfig() { - return ReactCurrentBatchConfig.suspense; -} - var fakeInternalInstance = {}; var isArray = Array.isArray; // React.Component uses a shared frozen object by default. // We'll use it to determine whether we need to initialize legacy refs. @@ -7507,9 +7450,8 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.payload = payload; if (callback !== undefined && callback !== null) { @@ -7526,9 +7468,8 @@ var classComponentUpdater = { enqueueReplaceState: function(inst, payload, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ReplaceState; update.payload = payload; @@ -7546,9 +7487,8 @@ var classComponentUpdater = { enqueueForceUpdate: function(inst, callback) { var fiber = get(inst); var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); - var update = createUpdate(eventTime, lane, suspenseConfig); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ForceUpdate; if (callback !== undefined && callback !== null) { @@ -8008,7 +7948,7 @@ function constructClassInstance(workInProgress, ctor, props) { "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + "The above lifecycles should be removed. Learn more about this warning here:\n" + - "https://fb.me/react-unsafe-component-lifecycles", + "https://reactjs.org/link/unsafe-component-lifecycles", _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : "", @@ -8170,7 +8110,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -8232,7 +8172,7 @@ function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } return false; @@ -8278,13 +8218,13 @@ function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // If shouldComponentUpdate returned false, we should still update the // memoized state to indicate that this work can be reused. @@ -8372,7 +8312,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -8381,7 +8321,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -8428,11 +8368,11 @@ function updateClassInstance( } if (typeof instance.componentDidUpdate === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } else { // If an update was already in progress, we should schedule an Update @@ -8442,7 +8382,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -8451,7 +8391,7 @@ function updateClassInstance( unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -8514,7 +8454,7 @@ var warnForMissingKey = function(child, returnFiber) {}; error( "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + "more information." ); }; @@ -8552,7 +8492,7 @@ function coerceRef(returnFiber, current, element) { "String refs are a source of potential bugs and should be avoided. " + "We recommend using useRef() or createRef() instead. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-string-ref", + "https://reactjs.org/link/strict-mode-string-ref", mixedRef ); } @@ -8571,7 +8511,7 @@ function coerceRef(returnFiber, current, element) { if (!(ownerFiber.tag === ClassComponent)) { throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); } @@ -8625,7 +8565,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + mixedRef + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } } @@ -8664,7 +8604,7 @@ function warnOnFunctionType(returnFiber) { "Or maybe you meant to call this function rather than return it." ); } -} // We avoid inlining this to avoid potential deopts from using try/catch. +} // This wrapper function exists because I expect to clone the code in each path // to be able to optimize each path individually by branching early. This needs // a compiler or we can do it manually. Helpers that don't need this branching // live outside of this function. @@ -8690,7 +8630,7 @@ function ChildReconciler(shouldTrackSideEffects) { } childToDelete.nextEffect = null; - childToDelete.effectTag = Deletion; + childToDelete.flags = Deletion; } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -8754,7 +8694,7 @@ function ChildReconciler(shouldTrackSideEffects) { if (oldIndex < lastPlacedIndex) { // This is a move. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } else { // This item can stay in place. @@ -8762,7 +8702,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } else { // This is an insertion. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } } @@ -8771,7 +8711,7 @@ function ChildReconciler(shouldTrackSideEffects) { // This is simpler for the single child case. We only need to do a // placement for inserting new children. if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.effectTag = Placement; + newFiber.flags = Placement; } return newFiber; @@ -9522,11 +9462,6 @@ function ChildReconciler(shouldTrackSideEffects) { break; } - case Block: - - // We intentionally fallthrough here if enableBlocksAPI is not on. - // eslint-disable-next-lined no-fallthrough - default: { if ( child.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -9534,17 +9469,17 @@ function ChildReconciler(shouldTrackSideEffects) { ) { deleteRemainingChildren(returnFiber, child.sibling); - var _existing3 = useFiber(child, element.props); + var _existing = useFiber(child, element.props); - _existing3.ref = coerceRef(returnFiber, child, element); - _existing3.return = returnFiber; + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; { - _existing3._debugSource = element._source; - _existing3._debugOwner = element._owner; + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; } - return _existing3; + return _existing; } break; @@ -9725,12 +9660,12 @@ function ChildReconciler(shouldTrackSideEffects) { // functions and classes // eslint-disable-next-lined no-fallthrough - case FunctionComponent: { - var Component = returnFiber.type; - + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { { throw Error( - (Component.displayName || Component.name || "Component") + + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." ); } @@ -9894,13 +9829,6 @@ function popSuspenseContext(fiber) { pop(suspenseStackCursor, fiber); } -// A non-null SuspenseState means that it is blocked for one reason or another. -// - A non-null dehydrated field means it's blocked pending hydration. -// - A non-null dehydrated field can use isSuspenseInstancePending or -// isSuspenseInstanceFallback to query the reason for being dehydrated. -// - A null dehydrated field means it's blocked by something suspending and -// we're currently showing a fallback instead. - function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { // If it was the primary children that just suspended, capture and render the // fallback. Otherwise, don't capture and bubble to the next boundary. @@ -9955,7 +9883,7 @@ function findFirstSuspended(row) { // keep track of whether it suspended or not. node.memoizedProps.revealOrder !== undefined ) { - var didSuspend = (node.effectTag & DidCapture) !== NoEffect; + var didSuspend = (node.flags & DidCapture) !== NoFlags; if (didSuspend) { return node; @@ -9985,7 +9913,7 @@ function findFirstSuspended(row) { return null; } -var NoEffect$1 = +var NoFlags$1 = /* */ 0; // Represents whether effect should fire. @@ -10209,7 +10137,7 @@ function warnOnHookMismatchInDev(currentHookName) { error( "React has detected a change in the order of Hooks called by %s. " + "This will lead to bugs and errors if not fixed. " + - "For more information, read the Rules of Hooks: https://fb.me/rules-of-hooks\n\n" + + "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + " Previous render Next render\n" + " ------------------------------------------------------\n" + "%s" + @@ -10225,7 +10153,7 @@ function warnOnHookMismatchInDev(currentHookName) { function throwInvalidHookError() { { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } } @@ -10395,7 +10323,7 @@ function renderWithHooks( } function bailoutHooks(current, workInProgress, lanes) { workInProgress.updateQueue = current.updateQueue; - workInProgress.effectTag &= ~(Passive | Update); + workInProgress.flags &= ~(Passive | Update); current.lanes = removeLanes(current.lanes, lanes); } function resetHooksAfterThrow() { @@ -10611,18 +10539,14 @@ function updateReducer(reducer, initialArg, init) { var update = first; do { - var suspenseConfig = update.suspenseConfig; var updateLane = update.lane; - var updateEventTime = update.eventTime; if (!isSubsetOfLanes(renderLanes, updateLane)) { // Priority is insufficient. Skip this update. If this is the first // skipped update, the previous update/state is the new base // update/state. var clone = { - eventTime: updateEventTime, lane: updateLane, - suspenseConfig: suspenseConfig, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, @@ -10647,26 +10571,17 @@ function updateReducer(reducer, initialArg, init) { // This update does have sufficient priority. if (newBaseQueueLast !== null) { var _clone = { - eventTime: updateEventTime, // This update is going to be committed so we never want uncommit // it. Using NoLane works because 0 is a subset of all bitmasks, so // this will never be skipped by the check above. lane: NoLane, - suspenseConfig: update.suspenseConfig, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }; newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reversible value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig); // Process this update. + } // Process this update. if (update.eagerReducer === reducer) { // If this update was processed eagerly, and its reducer matches the @@ -10893,8 +10808,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { if (!objectIs(snapshot, maybeNewSnapshot)) { setSnapshot(maybeNewSnapshot); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); markRootMutableRead(root, lane); } // If the source mutated between render and now, // there may be state updates already scheduled from the old source. @@ -10915,8 +10829,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { try { latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); markRootMutableRead(root, lane); } catch (error) { // A selector might throw after a source mutation. @@ -11065,16 +10978,14 @@ function pushEffect(tag, create, destroy, deps) { function mountRef(initialValue) { var hook = mountWorkInProgressHook(); - var ref = { - current: initialValue - }; { - Object.seal(ref); + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } - - hook.memoizedState = ref; - return ref; } function updateRef(initialValue) { @@ -11082,19 +10993,19 @@ function updateRef(initialValue) { return hook.memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, undefined, nextDeps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; var destroy = undefined; @@ -11107,15 +11018,15 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { - pushEffect(hookEffectTag, create, destroy, nextDeps); + pushEffect(hookFlags, create, destroy, nextDeps); return; } } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, destroy, nextDeps @@ -11289,128 +11200,124 @@ function updateMemo(nextCreate, deps) { return nextValue; } -function mountDeferredValue(value, config) { +function mountDeferredValue(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function updateDeferredValue(value, config) { +function updateDeferredValue(value) { var _updateState = updateState(), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function rerenderDeferredValue(value, config) { +function rerenderDeferredValue(value) { var _rerenderState = rerenderState(), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); - runWithPriority( - priorityLevel < UserBlockingPriority$1 - ? UserBlockingPriority$1 - : priorityLevel, - function() { - setPending(true); - } - ); // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. - runWithPriority( - priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, - function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + { + runWithPriority( + priorityLevel < UserBlockingPriority$1 + ? UserBlockingPriority$1 + : priorityLevel, + function() { + setPending(true); } - } - ); + ); + runWithPriority( + priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, + function() { + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; + + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig$1.transition = prevTransition; + } + } + ); + } } -function mountTransition(config) { +function mountTransition() { var _mountState2 = mountState(false), isPending = _mountState2[0], - setPending = _mountState2[1]; + setPending = _mountState2[1]; // The `start` method never changes. - var start = mountCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; return [start, isPending]; } -function updateTransition(config) { +function updateTransition() { var _updateState2 = updateState(), - isPending = _updateState2[0], - setPending = _updateState2[1]; + isPending = _updateState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } -function rerenderTransition(config) { +function rerenderTransition() { var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0], - setPending = _rerenderState2[1]; + isPending = _rerenderState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } @@ -11474,12 +11381,9 @@ function dispatchAction(fiber, queue, action) { } var eventTime = requestEventTime(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(fiber, suspenseConfig); + var lane = requestUpdateLane(fiber); var update = { - eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, action: action, eagerReducer: null, eagerState: null, @@ -11605,7 +11509,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + "You can only call Hooks at the top level of your React function. " + "For more information, see " + - "https://fb.me/rules-of-hooks" + "https://reactjs.org/link/rules-of-hooks" ); }; @@ -11689,15 +11593,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11786,15 +11690,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11883,15 +11787,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -11980,15 +11884,15 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -12088,17 +11992,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -12200,17 +12104,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -12312,17 +12216,17 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, useMutableSource: function(source, getSnapshot, subscribe) { currentHookNameInDev = "useMutableSource"; @@ -12540,7 +12444,7 @@ function updateForwardRef( return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12605,7 +12509,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -12646,7 +12550,7 @@ function updateMemoComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; var newChild = createWorkInProgress(currentChild, nextProps); newChild.ref = workInProgress.ref; newChild.return = workInProgress; @@ -12729,10 +12633,7 @@ function updateSimpleMemoComponent( workInProgress, renderLanes ); - } else if ( - (current.effectTag & ForceUpdateForLegacySuspense) !== - NoEffect - ) { + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { // This is a special case that only exists for legacy mode. // See https://github.com/facebook/react/pull/19216. didReceiveUpdate = true; @@ -12841,7 +12742,7 @@ function updateMode(current, workInProgress, renderLanes) { function updateProfiler(current, workInProgress, renderLanes) { { - workInProgress.effectTag |= Update; // Reset effect durations for the next eventual effect phase. + workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, var stateNode = workInProgress.stateNode; @@ -12863,7 +12764,7 @@ function markRef(current, workInProgress) { (current !== null && current.ref !== ref) ) { // Schedule a Ref effect - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } } @@ -12938,7 +12839,7 @@ function updateFunctionComponent( return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12991,7 +12892,7 @@ function updateClassComponent( current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // In the initial pass we might need to construct the instance. constructClassInstance(workInProgress, Component, nextProps); @@ -13053,7 +12954,7 @@ function finishClassComponent( ) { // Refs should update even if shouldComponentUpdate returns false markRef(current, workInProgress); - var didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; if (!shouldUpdate && !didCaptureError) { // Context providers should defer to sCU for rendering @@ -13102,7 +13003,7 @@ function finishClassComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; if (current !== null && didCaptureError) { // If we're recovering from an error, reconcile without reusing any of @@ -13189,7 +13090,7 @@ function updateHostRoot(current, workInProgress, renderLanes) { // Conceptually this is similar to Placement in that a new subtree is // inserted into the React tree here. It just happens to not need DOM // mutations because it already exists. - node.effectTag = (node.effectTag & ~Placement) | Hydrating; + node.flags = (node.flags & ~Placement) | Hydrating; node = node.sibling; } } else { @@ -13212,7 +13113,7 @@ function updateHostComponent(current, workInProgress, renderLanes) { if (prevProps !== null && shouldSetTextContent()) { // If we're switching from a direct text child to a normal child, or to // empty, we need to schedule the text content to be reset. - workInProgress.effectTag |= ContentReset; + workInProgress.flags |= ContentReset; } markRef(current, workInProgress); @@ -13241,7 +13142,7 @@ function mountLazyComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -13375,7 +13276,7 @@ function mountIncompleteClassComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // Promote the fiber to a class and try rendering again. workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` @@ -13419,7 +13320,7 @@ function mountIndeterminateComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -13469,7 +13370,7 @@ function mountIndeterminateComponent( setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; { // Support for module components is deprecated and is removed behind a flag. @@ -13683,7 +13584,7 @@ function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { return { baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes) }; -} +} // TODO: Probably should inline this back function shouldRemainOnFallback( suspenseContext, @@ -13719,19 +13620,19 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { { if (shouldSuspend(workInProgress)) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } } var suspenseContext = suspenseStackCursor.current; var showFallback = false; - var didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { // Something in this boundary's subtree already suspended. Switch to // rendering the fallback children. showFallback = true; - workInProgress.effectTag &= ~DidCapture; + workInProgress.flags &= ~DidCapture; } else { // Attempting the main content if (current === null || current.memoizedState !== null) { @@ -13782,9 +13683,10 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { // But only if this has a fallback. if (nextProps.fallback !== undefined); + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; + if (showFallback) { - var nextPrimaryChildren = nextProps.children; - var nextFallbackChildren = nextProps.fallback; var fallbackFragment = mountSuspenseFallbackChildren( workInProgress, nextPrimaryChildren, @@ -13797,11 +13699,41 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { ); workInProgress.memoizedState = SUSPENDED_MARKER; return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + + return _fallbackFragment; } else { - var _nextPrimaryChildren = nextProps.children; return mountSuspensePrimaryChildren( workInProgress, - _nextPrimaryChildren, + nextPrimaryChildren, renderLanes ); } @@ -13814,63 +13746,63 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { if (prevState !== null) { if (showFallback) { var _nextFallbackChildren2 = nextProps.fallback; - var _nextPrimaryChildren3 = nextProps.children; + var _nextPrimaryChildren2 = nextProps.children; var _fallbackChildFragment = updateSuspenseFallbackChildren( current, workInProgress, - _nextPrimaryChildren3, + _nextPrimaryChildren2, _nextFallbackChildren2, renderLanes ); - var _primaryChildFragment2 = workInProgress.child; + var _primaryChildFragment3 = workInProgress.child; var prevOffscreenState = current.child.memoizedState; - _primaryChildFragment2.memoizedState = + _primaryChildFragment3.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); - _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree( + _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes ); workInProgress.memoizedState = SUSPENDED_MARKER; return _fallbackChildFragment; } else { - var _nextPrimaryChildren4 = nextProps.children; + var _nextPrimaryChildren3 = nextProps.children; - var _primaryChildFragment3 = updateSuspensePrimaryChildren( + var _primaryChildFragment4 = updateSuspensePrimaryChildren( current, workInProgress, - _nextPrimaryChildren4, + _nextPrimaryChildren3, renderLanes ); workInProgress.memoizedState = null; - return _primaryChildFragment3; + return _primaryChildFragment4; } } else { // The current tree is not already showing a fallback. if (showFallback) { // Timed out. var _nextFallbackChildren3 = nextProps.fallback; - var _nextPrimaryChildren5 = nextProps.children; + var _nextPrimaryChildren4 = nextProps.children; var _fallbackChildFragment2 = updateSuspenseFallbackChildren( current, workInProgress, - _nextPrimaryChildren5, + _nextPrimaryChildren4, _nextFallbackChildren3, renderLanes ); - var _primaryChildFragment4 = workInProgress.child; + var _primaryChildFragment5 = workInProgress.child; var _prevOffscreenState = current.child.memoizedState; - _primaryChildFragment4.memoizedState = + _primaryChildFragment5.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); - _primaryChildFragment4.childLanes = getRemainingWorkInPrimaryTree( + _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( current, renderLanes ); // Skip the primary children, and continue working on the @@ -13881,17 +13813,17 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { } else { // Still haven't timed out. Continue rendering the children, like we // normally do. - var _nextPrimaryChildren6 = nextProps.children; + var _nextPrimaryChildren5 = nextProps.children; - var _primaryChildFragment5 = updateSuspensePrimaryChildren( + var _primaryChildFragment6 = updateSuspensePrimaryChildren( current, workInProgress, - _nextPrimaryChildren6, + _nextPrimaryChildren5, renderLanes ); workInProgress.memoizedState = null; - return _primaryChildFragment5; + return _primaryChildFragment6; } } } @@ -14011,7 +13943,7 @@ function updateSuspensePrimaryChildren( if (currentFallbackChildFragment !== null) { // Delete the fallback child fragment currentFallbackChildFragment.nextEffect = null; - currentFallbackChildFragment.effectTag = Deletion; + currentFallbackChildFragment.flags = Deletion; workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment; } @@ -14102,7 +14034,7 @@ function updateSuspenseFallbackChildren( ); // Needs a placement effect because the parent (the Suspense boundary) already // mounted but this is a new fiber. - fallbackChildFragment.effectTag |= Placement; + fallbackChildFragment.flags |= Placement; } fallbackChildFragment.return = workInProgress; @@ -14365,7 +14297,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }; @@ -14376,7 +14307,6 @@ function initSuspenseListRenderState( renderState.renderingStartTime = 0; renderState.last = lastContentRow; renderState.tail = tail; - renderState.tailExpiration = 0; renderState.tailMode = tailMode; renderState.lastEffect = lastEffectBeforeRendering; } @@ -14408,10 +14338,10 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { suspenseContext, ForceSuspenseFallback ); - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } else { var didSuspendBefore = - current !== null && (current.effectTag & DidCapture) !== NoEffect; + current !== null && (current.flags & DidCapture) !== NoFlags; if (didSuspendBefore) { // If we previously forced a fallback, we need to schedule work @@ -14653,7 +14583,7 @@ function updateContextConsumer(current, workInProgress, renderLanes) { setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } @@ -14736,8 +14666,8 @@ function remountFiber(current, oldWorkInProgress, newWorkInProgress) { } current.nextEffect = null; - current.effectTag = Deletion; - newWorkInProgress.effectTag |= Placement; // Restart work from the new fiber. + current.flags = Deletion; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. return newWorkInProgress; } @@ -14822,7 +14752,7 @@ function beginWork(current, workInProgress, renderLanes) { ); if (hasChildWork) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, @@ -14886,7 +14816,7 @@ function beginWork(current, workInProgress, renderLanes) { } case SuspenseListComponent: { - var didSuspendBefore = (current.effectTag & DidCapture) !== NoEffect; + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; var _hasChildWork = includesSomeLane( renderLanes, @@ -14909,7 +14839,7 @@ function beginWork(current, workInProgress, renderLanes) { // them got retried so they'll still be blocked in the same way // as before. We can fast bail out. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } // If nothing suspended before and we're rendering the same children, // then the tail doesn't matter. Anything new that suspends will work // in the "together" mode, so we can continue from the state we had. @@ -14953,7 +14883,7 @@ function beginWork(current, workInProgress, renderLanes) { return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else { - if ((current.effectTag & ForceUpdateForLegacySuspense) !== NoEffect) { + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { // This is a special case that only exists for legacy mode. // See https://github.com/facebook/react/pull/19216. didReceiveUpdate = true; @@ -15151,10 +15081,6 @@ function beginWork(current, workInProgress, renderLanes) { break; } - case Block: { - break; - } - case OffscreenComponent: { return updateOffscreenComponent(current, workInProgress, renderLanes); } @@ -15176,11 +15102,11 @@ function beginWork(current, workInProgress, renderLanes) { function markUpdate(workInProgress) { // Tag the fiber with an update effect. This turns a Placement into // a PlacementAndUpdate. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } function markRef$1(workInProgress) { - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } var appendAllChildren; @@ -15395,7 +15321,7 @@ function completeWork(current, workInProgress, renderLanes) { // This handles the case of React rendering into a container with previous children. // It's also safe to do for updates too, because current.child would only be null // if the previous render was null (so the the container would already be empty). - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -15517,7 +15443,7 @@ function completeWork(current, workInProgress, renderLanes) { popSuspenseContext(workInProgress); var nextState = workInProgress.memoizedState; - if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + if ((workInProgress.flags & DidCapture) !== NoFlags) { // Something suspended. Re-render with the fallback children. workInProgress.lanes = renderLanes; // Do not reset the effect list. @@ -15582,7 +15508,7 @@ function completeWork(current, workInProgress, renderLanes) { // primary children. In mutation mode, we also need the flag to // *unhide* children that were previously hidden, so check if this // is currently timed out, too. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -15626,8 +15552,7 @@ function completeWork(current, workInProgress, renderLanes) { return null; } - var didSuspendAlready = - (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; var renderedTail = renderState.rendering; if (renderedTail === null) { @@ -15644,7 +15569,7 @@ function completeWork(current, workInProgress, renderLanes) { // findFirstSuspended. var cannotBeSuspended = renderHasNotSuspendedYet() && - (current === null || (current.effectTag & DidCapture) === NoEffect); + (current === null || (current.flags & DidCapture) === NoFlags); if (!cannotBeSuspended) { var row = workInProgress.child; @@ -15654,7 +15579,7 @@ function completeWork(current, workInProgress, renderLanes) { if (suspended !== null) { didSuspendAlready = true; - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to // its thennables. Instead, we'll transfer its thennables to the @@ -15672,7 +15597,7 @@ function completeWork(current, workInProgress, renderLanes) { if (newThennables !== null) { workInProgress.updateQueue = newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect list before doing the second pass since that's now invalid. @@ -15699,6 +15624,28 @@ function completeWork(current, workInProgress, renderLanes) { row = row.sibling; } } + + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + } } else { cutOffTailIfNeeded(renderState, false); } // Next we're going to render the tail. @@ -15708,7 +15655,7 @@ function completeWork(current, workInProgress, renderLanes) { var _suspended = findFirstSuspended(renderedTail); if (_suspended !== null) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. @@ -15716,7 +15663,7 @@ function completeWork(current, workInProgress, renderLanes) { if (_newThennables !== null) { workInProgress.updateQueue = _newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } cutOffTailIfNeeded(renderState, true); // This might have been modified. @@ -15740,27 +15687,31 @@ function completeWork(current, workInProgress, renderLanes) { return null; } } else if ( - // The time it took to render last row is greater than time until - // the expiration. + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. now() * 2 - renderState.renderingStartTime > - renderState.tailExpiration && + getRenderTargetTime() && renderLanes !== OffscreenLane ) { // We have now passed our CPU deadline and we'll just give up further // attempts to render the main content and only render fallbacks. // The assumption is that this is usually faster. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. If we can show - // them, then they really have the same priority as this render. - // So we'll pick it back up the very next render pass once we've had - // an opportunity to yield for paint. + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - workInProgress.lanes = renderLanes; + workInProgress.lanes = SomeRetryLane; { - markSpawnedWork(renderLanes); + markSpawnedWork(SomeRetryLane); } } } @@ -15788,18 +15739,7 @@ function completeWork(current, workInProgress, renderLanes) { if (renderState.tail !== null) { // We still have tail rows to render. - if (renderState.tailExpiration === 0) { - // Heuristic for how long we're willing to spend rendering rows - // until we just give up and show what we have so far. - var TAIL_EXPIRATION_TIMEOUT_MS = 500; - renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS; // TODO: This is meant to mimic the train model or JND but this - // is a per component value. It should really be since the start - // of the total render or last commit. Consider using something like - // globalMostRecentFallbackTime. That doesn't account for being - // suspended for part of the time or when it's a new render. - // It should probably use a global start time value instead. - } // Pop a row. - + // Pop a row. var next = renderState.tail; renderState.rendering = next; renderState.tail = next.sibling; @@ -15836,9 +15776,6 @@ function completeWork(current, workInProgress, renderLanes) { break; } - case Block: - break; - case OffscreenComponent: case LegacyHiddenComponent: { popRenderLanes(workInProgress); @@ -15853,7 +15790,7 @@ function completeWork(current, workInProgress, renderLanes) { prevIsHidden !== nextIsHidden && newProps.mode !== "unstable-defer-without-hiding" ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -15879,10 +15816,10 @@ function unwindWork(workInProgress, renderLanes) { popContext(workInProgress); } - var effectTag = workInProgress.effectTag; + var flags = workInProgress.flags; - if (effectTag & ShouldCapture) { - workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; if ((workInProgress.mode & ProfileMode) !== NoMode) { transferActualDuration(workInProgress); @@ -15898,15 +15835,15 @@ function unwindWork(workInProgress, renderLanes) { popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); resetWorkInProgressVersions(); - var _effectTag = workInProgress.effectTag; + var _flags = workInProgress.flags; - if (!((_effectTag & DidCapture) === NoEffect)) { + if (!((_flags & DidCapture) === NoFlags)) { throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); } - workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; return workInProgress; } @@ -15919,10 +15856,10 @@ function unwindWork(workInProgress, renderLanes) { case SuspenseComponent: { popSuspenseContext(workInProgress); - var _effectTag2 = workInProgress.effectTag; + var _flags2 = workInProgress.flags; - if (_effectTag2 & ShouldCapture) { - workInProgress.effectTag = (_effectTag2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. if ((workInProgress.mode & ProfileMode) !== NoMode) { transferActualDuration(workInProgress); @@ -16089,7 +16026,7 @@ function logCapturedError(boundary, errorInfo) { } else { errorBoundaryMessage = "Consider adding an error boundary to your tree to customize error handling behavior.\n" + - "Visit https://fb.me/react-error-boundaries to learn more about error boundaries."; + "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; } var combinedMessage = @@ -16123,7 +16060,7 @@ function logCapturedError(boundary, errorInfo) { var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane, null); // Unmount the root by rendering null. + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property // being called "element". @@ -16142,7 +16079,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { } function createClassErrorUpdate(fiber, errorInfo, lane) { - var update = createUpdate(NoTimestamp, lane, null); + var update = createUpdate(NoTimestamp, lane); update.tag = CaptureUpdate; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; @@ -16240,7 +16177,7 @@ function throwException( rootRenderLanes ) { // The source fiber did not complete. - sourceFiber.effectTag |= Incomplete; // Its effect list is no longer valid. + sourceFiber.flags |= Incomplete; // Its effect list is no longer valid. sourceFiber.firstEffect = sourceFiber.lastEffect = null; @@ -16300,12 +16237,12 @@ function throwException( // should *not* suspend the commit. if ((_workInProgress.mode & BlockingMode) === NoMode) { - _workInProgress.effectTag |= DidCapture; - sourceFiber.effectTag |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + _workInProgress.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. // But we shouldn't call any lifecycle methods or callbacks. Remove // all lifecycle effect tags. - sourceFiber.effectTag &= ~(LifecycleEffectMask | Incomplete); + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); if (sourceFiber.tag === ClassComponent) { var currentSourceFiber = sourceFiber.alternate; @@ -16319,7 +16256,7 @@ function throwException( // When we try rendering again, we should not reuse the current fiber, // since it's known to be in an inconsistent state. Use a force update to // prevent a bail out. - var update = createUpdate(NoTimestamp, SyncLane, null); + var update = createUpdate(NoTimestamp, SyncLane); update.tag = ForceUpdate; enqueueUpdate(sourceFiber, update); } @@ -16354,8 +16291,8 @@ function throwException( // that we can show the initial loading state as quickly as possible. // // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. SuspenseConfig applies to - // this case. If none is defined, JND is used instead. + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. // // If we're already showing a fallback and it gets "retried", allowing us to show // another level, but there's still an inner boundary that would show a fallback, @@ -16371,7 +16308,7 @@ function throwException( // ensure that new initial loading states can commit as soon as possible. attachPingListener(root, wakeable, rootRenderLanes); - _workInProgress.effectTag |= ShouldCapture; + _workInProgress.flags |= ShouldCapture; _workInProgress.lanes = rootRenderLanes; return; } // This boundary already captured during this render. Continue to the next @@ -16400,7 +16337,7 @@ function throwException( switch (workInProgress.tag) { case HostRoot: { var _errorInfo = value; - workInProgress.effectTag |= ShouldCapture; + workInProgress.flags |= ShouldCapture; var lane = pickArbitraryLane(rootRenderLanes); workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); @@ -16417,13 +16354,13 @@ function throwException( var instance = workInProgress.stateNode; if ( - (workInProgress.effectTag & DidCapture) === NoEffect && + (workInProgress.flags & DidCapture) === NoFlags && (typeof ctor.getDerivedStateFromError === "function" || (instance !== null && typeof instance.componentDidCatch === "function" && !isAlreadyFailedLegacyErrorBoundary(instance))) ) { - workInProgress.effectTag |= ShouldCapture; + workInProgress.flags |= ShouldCapture; var _lane = pickArbitraryLane(rootRenderLanes); @@ -16486,7 +16423,9 @@ function safelyDetachRef(current) { if (ref !== null) { if (typeof ref === "function") { { - invokeGuardedCallback(null, ref, null, null); + { + invokeGuardedCallback(null, ref, null, null); + } if (hasCaughtError()) { var refError = clearCaughtError(); @@ -16514,13 +16453,12 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { return; } case ClassComponent: { - if (finishedWork.effectTag & Snapshot) { + if (finishedWork.flags & Snapshot) { if (current !== null) { var prevProps = current.memoizedProps; var prevState = current.memoizedState; @@ -16587,7 +16525,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case HostRoot: { { - if (finishedWork.effectTag & Snapshot) { + if (finishedWork.flags & Snapshot) { var root = finishedWork.stateNode; clearContainer(root.containerInfo); } @@ -16672,7 +16610,7 @@ function commitHookEffectListMount(tag, finishedWork) { " }\n" + " fetchData();\n" + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + - "Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching"; + "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; } else { addendum = " You returned: " + destroy; } @@ -16704,10 +16642,7 @@ function schedulePassiveEffects(finishedWork) { next = _effect.next, tag = _effect.tag; - if ( - (tag & Passive$1) !== NoEffect$1 && - (tag & HasEffect) !== NoEffect$1 - ) { + if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) { enqueuePendingPassiveHookEffectUnmount(finishedWork, effect); enqueuePendingPassiveHookEffectMount(finishedWork, effect); } @@ -16721,8 +16656,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // At this point layout effects have already been destroyed (during mutation phase). // This is done to prevent sibling component effects from interfering with each other, // e.g. a destroy function in one component should never override a ref set @@ -16738,7 +16672,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { case ClassComponent: { var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update) { + if (finishedWork.flags & Update) { if (current === null) { // We could update instance props and state here, // but instead we rely on them being set during last render. @@ -16896,7 +16830,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { // These effects should only be committed when components are first mounted, // aka when there is no current/alternate. - if (current === null && finishedWork.effectTag & Update) { + if (current === null && finishedWork.flags & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; } @@ -17030,7 +16964,9 @@ function commitAttachRef(finishedWork) { } // Moved outside to ensure DCE works with this flag if (typeof ref === "function") { - ref(instanceToUse); + { + ref(instanceToUse); + } } else { { if (!ref.hasOwnProperty("current")) { @@ -17052,7 +16988,9 @@ function commitDetachRef(current) { if (currentRef !== null) { if (typeof currentRef === "function") { - currentRef(null); + { + currentRef(null); + } } else { currentRef.current = null; } @@ -17068,8 +17006,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { var updateQueue = current.updateQueue; if (updateQueue !== null) { @@ -17085,7 +17022,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { tag = _effect2.tag; if (destroy !== undefined) { - if ((tag & Passive$1) !== NoEffect$1) { + if ((tag & Passive$1) !== NoFlags$1) { enqueuePendingPassiveHookEffectUnmount(current, effect); } else { { @@ -17267,7 +17204,7 @@ function getHostSibling(fiber) { ) { // If it is not host node and, we might have a host node inside it. // Try to search down until we find one. - if (node.effectTag & Placement) { + if (node.flags & Placement) { // If we don't have a child, try the siblings instead. continue siblings; } // If we don't have a child, try the siblings instead. @@ -17281,7 +17218,7 @@ function getHostSibling(fiber) { } } // Check if this host node is stable or about to be placed. - if (!(node.effectTag & Placement)) { + if (!(node.flags & Placement)) { // Found it! return node.stateNode; } @@ -17322,8 +17259,8 @@ function commitPlacement(finishedWork) { } } - if (parentFiber.effectTag & ContentReset) { - parentFiber.effectTag &= ~ContentReset; + if (parentFiber.flags & ContentReset) { + parentFiber.flags &= ~ContentReset; } var before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its @@ -17512,8 +17449,7 @@ function commitWork(current, finishedWork) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // Layout effects are destroyed during the mutation phase so that all // destroy functions for all fibers are called before any create functions. // This prevents sibling component effects from interfering with each other, @@ -17757,9 +17693,7 @@ var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root complet var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown -var workInProgressRootFatalError = null; -var workInProgressRootLatestSuspenseTimeout = NoTimestamp; -var workInProgressRootCanSuspendUsingConfig = null; // "Included" lanes refer to lanes that were worked on during this render. It's +var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's // slightly different than `renderLanes` because `renderLanes` can change as you // enter and exit an Offscreen tree. This value is the combination of all render // lanes for the entire render phase. @@ -17776,8 +17710,21 @@ var mostRecentlyUpdatedRoot = null; // The most recent time we committed a fallb // model where we don't commit new loading states in too quick succession. var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; -var DEFAULT_TIMEOUT_MS = 5000; +var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering +// more and prefer CPU suspense heuristics instead. + +var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU +// suspense heuristics and opt out of rendering more content. + +var RENDER_TIMEOUT_MS = 500; + +function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; +} + +function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; +} var nextEffect = null; var hasUncaughtError = false; var firstUncaughtError = null; @@ -17829,7 +17776,7 @@ function requestEventTime() { currentEventTime = now(); return currentEventTime; } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { // Special cases var mode = fiber.mode; @@ -17858,16 +17805,9 @@ function requestUpdateLane(fiber, suspenseConfig) { currentEventWipLanes = workInProgressRootIncludedLanes; } - if (suspenseConfig !== null) { - // Use the size of the timeout as a heuristic to prioritize shorter - // transitions over longer ones. - // TODO: This will coerce numbers larger than 31 bits to 0. - var timeoutMs = suspenseConfig.timeoutMs; - var transitionLanePriority = - timeoutMs === undefined || (timeoutMs | 0) < 10000 - ? TransitionShortLanePriority - : TransitionLongLanePriority; + var isTransition = requestCurrentTransition() !== NoTransition; + if (isTransition) { if (currentEventPendingLanes !== NoLanes) { currentEventPendingLanes = mostRecentlyUpdatedRoot !== null @@ -17875,11 +17815,7 @@ function requestUpdateLane(fiber, suspenseConfig) { : NoLanes; } - return findTransitionLane( - transitionLanePriority, - currentEventWipLanes, - currentEventPendingLanes - ); + return findTransitionLane(currentEventWipLanes, currentEventPendingLanes); } // TODO: Remove this dependency on the Scheduler priority. // To do that, we're replacing it with an update lane priority. @@ -17992,6 +17928,7 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { // scheduleCallbackForFiber to preserve the ability to schedule a callback // without immediately flushing it. We only do this for user-initiated // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); flushSyncCallbackQueue(); } } @@ -18038,7 +17975,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { { if ( alternate === null && - (sourceFiber.effectTag & (Placement | Hydrating)) !== NoEffect + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags ) { warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } @@ -18055,7 +17992,7 @@ function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { alternate.childLanes = mergeLanes(alternate.childLanes, lane); } else { { - if ((parent.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); } } @@ -18141,7 +18078,7 @@ function ensureRootIsScheduled(root, currentTime) { } // This is the entry point for every concurrent task, i.e. anything that // goes through Scheduler. -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { // Since we know we're in a React event, we can clear the current // event time. The next update will compute a new event time. currentEventTime = NoTimestamp; @@ -18176,18 +18113,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { if (lanes === NoLanes) { // Defensive coding. This is never expected to happen. return null; - } // TODO: We only check `didTimeout` defensively, to account for a Scheduler - // bug where `shouldYield` sometimes returns `true` even if `didTimeout` is - // true, which leads to an infinite loop. Once the bug in Scheduler is - // fixed, we can remove this, since we track expiration ourselves. - - if (didTimeout) { - // Something expired. Flush synchronously until there's no expired - // work left. - markRootExpired(root, lanes); // This will schedule a synchronous callback. - - ensureRootIsScheduled(root, now()); - return null; } var exitStatus = renderRootConcurrent(root, lanes); @@ -18237,7 +18162,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { var finishedWork = root.current.alternate; root.finishedWork = finishedWork; root.finishedLanes = lanes; - finishConcurrentRender(root, finishedWork, exitStatus, lanes); + finishConcurrentRender(root, exitStatus, lanes); } ensureRootIsScheduled(root, now()); @@ -18251,7 +18176,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { return null; } -function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { +function finishConcurrentRender(root, exitStatus, lanes) { switch (exitStatus) { case RootIncomplete: case RootFatalErrored: { @@ -18320,64 +18245,36 @@ function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { case RootSuspendedWithDelay: { markRootSuspended$1(root, lanes); - if ( - // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() - ) { - // We're suspended in a state that should be avoided. We'll try to - // avoid committing it for as long as the timeouts let us. - var _nextLanes = getNextLanes(root, NoLanes); - - if (_nextLanes !== NoLanes) { - // There's additional work on this root. - break; - } - - var _suspendedLanes = root.suspendedLanes; - - if (!isSubsetOfLanes(_suspendedLanes, lanes)) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - // FIXME: What if the suspended lanes are Idle? Should not restart. - var _eventTime = requestEventTime(); - - markRootPinged(root, _suspendedLanes); - break; - } + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + break; + } + if (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; - var _msUntilTimeout; - - if (workInProgressRootLatestSuspenseTimeout !== NoTimestamp) { - // We have processed a suspense config whose expiration time we - // can use as the timeout. - _msUntilTimeout = workInProgressRootLatestSuspenseTimeout - now(); - } else if (mostRecentEventTime === NoTimestamp) { - // This should never normally happen because only new updates - // cause delayed states, so we should have processed something. - // However, this could also happen in an offscreen tree. - _msUntilTimeout = 0; - } else { - // If we didn't process a suspense config, compute a JND based on - // the amount of time elapsed since the most recent event time. - var eventTimeMs = mostRecentEventTime; - var timeElapsedMs = now() - eventTimeMs; - _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; - } // Don't bother with a very short suspense time. + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. if (_msUntilTimeout > 10) { - // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. + // Instead of committing the fallback immediately, wait for more data + // to arrive. root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), _msUntilTimeout ); break; } - } // The work expired. Commit immediately. + } // Commit the placeholder. commitRoot(root); break; @@ -18385,33 +18282,6 @@ function finishConcurrentRender(root, finishedWork, exitStatus, lanes) { case RootCompleted: { // The work completed. Ready to commit. - var _mostRecentEventTime = getMostRecentEventTime(root, lanes); - - if ( - // do not delay if we're inside an act() scope - !shouldForceFlushFallbacksInDEV() && - _mostRecentEventTime !== NoTimestamp && - workInProgressRootCanSuspendUsingConfig !== null - ) { - // If we have exceeded the minimum loading delay, which probably - // means we have shown a spinner already, we might have to suspend - // a bit longer to ensure that the spinner is shown for - // enough time. - var _msUntilTimeout2 = computeMsUntilSuspenseLoadingDelay( - _mostRecentEventTime, - workInProgressRootCanSuspendUsingConfig - ); - - if (_msUntilTimeout2 > 10) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout2 - ); - break; - } - } - commitRoot(root); break; } @@ -18524,6 +18394,7 @@ function batchedUpdates$1(fn, a) { if (executionContext === NoContext) { // Flush the immediate callbacks that were scheduled during this batch + resetRenderTimer(); flushSyncCallbackQueue(); } } @@ -18545,20 +18416,20 @@ function flushSync(fn, a) { executionContext |= BatchedContext; - try { - setCurrentUpdateLanePriority(SyncLanePriority); + { + try { + if (fn) { + return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); + } else { + return undefined; + } + } finally { + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - if (fn) { - return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); - } else { - return undefined; + flushSyncCallbackQueue(); } - } finally { - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - - flushSyncCallbackQueue(); } } function pushRenderLanes(fiber, lanes) { @@ -18601,8 +18472,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = RootIncomplete; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = NoTimestamp; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootSkippedLanes = NoLanes; workInProgressRootUpdatedLanes = NoLanes; workInProgressRootPingedLanes = NoLanes; @@ -18681,7 +18550,7 @@ function handleError(root, thrownValue) { } while (true); } -function pushDispatcher(root) { +function pushDispatcher() { var prevDispatcher = ReactCurrentDispatcher$2.current; ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; @@ -18716,27 +18585,6 @@ function popInteractions(prevInteractions) { function markCommitTimeOfFallback() { globalMostRecentFallbackTime = now(); } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - // Track the largest/latest timeout deadline in this batch. - // TODO: If there are two transitions in the same batch, shouldn't we - // choose the smaller one? Maybe this is because when an intermediate - // transition is superseded, we should ignore its suspense config, but - // we don't currently. - if (suspenseConfig !== null) { - // If `timeoutMs` is not specified, we default to 5 seconds. We have to - // resolve this default here because `suspenseConfig` is owned - // by userspace. - // TODO: Store this on the root instead (transition -> timeoutMs) - // TODO: Should this default to a JND instead? - var timeoutMs = suspenseConfig.timeoutMs | 0 || DEFAULT_TIMEOUT_MS; - var timeoutTime = eventTime + timeoutMs; - - if (timeoutTime > workInProgressRootLatestSuspenseTimeout) { - workInProgressRootLatestSuspenseTimeout = timeoutTime; - workInProgressRootCanSuspendUsingConfig = suspenseConfig; - } - } -} function markSkippedUpdateLanes(lane) { workInProgressRootSkippedLanes = mergeLanes( lane, @@ -18846,6 +18694,7 @@ function renderRootConcurrent(root, lanes) { // and prepare a fresh one. Otherwise we'll continue where we left off. if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + resetRenderTimer(); prepareFreshStack(root, lanes); startWorkOnPendingInteractions(root, lanes); } @@ -18929,7 +18778,7 @@ function completeUnitOfWork(unitOfWork) { var current = completedWork.alternate; var returnFiber = completedWork.return; // Check if the work completed or if something threw. - if ((completedWork.effectTag & Incomplete) === NoEffect) { + if ((completedWork.flags & Incomplete) === NoFlags) { setCurrentFiber(completedWork); var next = void 0; @@ -18954,7 +18803,7 @@ function completeUnitOfWork(unitOfWork) { if ( returnFiber !== null && // Do not append effects to parents if a sibling failed to complete - (returnFiber.effectTag & Incomplete) === NoEffect + (returnFiber.flags & Incomplete) === NoFlags ) { // Append all the effects of the subtree and this fiber onto the effect // list of the parent. The completion order of the children affects the @@ -18976,11 +18825,11 @@ function completeUnitOfWork(unitOfWork) { // reusing children we'll schedule this effect onto itself since we're // at the end. - var effectTag = completedWork.effectTag; // Skip both NoWork and PerformedWork tags when creating the effect + var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect // list. PerformedWork effect is read by React DevTools but shouldn't be // committed. - if (effectTag > PerformedWork) { + if (flags > PerformedWork) { if (returnFiber.lastEffect !== null) { returnFiber.lastEffect.nextEffect = completedWork; } else { @@ -19001,7 +18850,7 @@ function completeUnitOfWork(unitOfWork) { // back here again. // Since we're restarting, remove anything that is not a host effect // from the effect tag. - _next.effectTag &= HostEffectMask; + _next.flags &= HostEffectMask; workInProgress = _next; return; } @@ -19024,7 +18873,7 @@ function completeUnitOfWork(unitOfWork) { if (returnFiber !== null) { // Mark the parent fiber as incomplete and clear its effect list. returnFiber.firstEffect = returnFiber.lastEffect = null; - returnFiber.effectTag |= Incomplete; + returnFiber.flags |= Incomplete; } } @@ -19189,14 +19038,11 @@ function commitRootImpl(root, renderPriorityLevel) { workInProgressRoot = null; workInProgress = null; workInProgressRootRenderLanes = NoLanes; - } // This indicates that the last root we worked on is not the same one that - // we're committing now. This most commonly happens when a suspended root - // times out. - // Get the list of effects. + } // Get the list of effects. var firstEffect; - if (finishedWork.effectTag > PerformedWork) { + if (finishedWork.flags > PerformedWork) { // A fiber's effect list consists only of its children, not itself. So if // the root has an effect, we need to add it to the end of the list. The // resulting list is the set that would belong to the root's parent, if it @@ -19314,7 +19160,7 @@ function commitRootImpl(root, renderPriorityLevel) { popInteractions(prevInteractions); } - executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. + executionContext = prevExecutionContext; } else { // No effects. root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were @@ -19345,7 +19191,7 @@ function commitRootImpl(root, renderPriorityLevel) { var nextNextEffect = nextEffect.nextEffect; nextEffect.nextEffect = null; - if (nextEffect.effectTag & Deletion) { + if (nextEffect.flags & Deletion) { detachFiberAfterEffects(nextEffect); } @@ -19431,7 +19277,7 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { - if ((nextEffect.effectTag & Deletion) !== NoEffect) { + if ((nextEffect.flags & Deletion) !== NoFlags) { if (doesFiberContain(nextEffect, focusedInstanceHandle)) { shouldFireAfterActiveInstanceBlur = true; } @@ -19447,15 +19293,15 @@ function commitBeforeMutationEffects() { } } - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if ((effectTag & Snapshot) !== NoEffect) { + if ((flags & Snapshot) !== NoFlags) { setCurrentFiber(nextEffect); commitBeforeMutationLifeCycles(current, nextEffect); resetCurrentFiber(); } - if ((effectTag & Passive) !== NoEffect) { + if ((flags & Passive) !== NoFlags) { // If there are passive effects, schedule a callback to flush at // the earliest opportunity. if (!rootDoesHavePassiveEffects) { @@ -19475,13 +19321,13 @@ function commitMutationEffects(root, renderPriorityLevel) { // TODO: Should probably move the bulk of this function to commitWork. while (nextEffect !== null) { setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if (effectTag & ContentReset) { + if (flags & ContentReset) { commitResetTextContent(nextEffect); } - if (effectTag & Ref) { + if (flags & Ref) { var current = nextEffect.alternate; if (current !== null) { @@ -19492,17 +19338,16 @@ function commitMutationEffects(root, renderPriorityLevel) { // bitmap value, we remove the secondary effects from the effect tag and // switch on that value. - var primaryEffectTag = - effectTag & (Placement | Update | Deletion | Hydrating); + var primaryFlags = flags & (Placement | Update | Deletion | Hydrating); - switch (primaryEffectTag) { + switch (primaryFlags) { case Placement: { commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is // inserted, before any life-cycles like componentDidMount gets called. // TODO: findDOMNode doesn't rely on this any more but isMounted does // and isMounted is deprecated anyway so we should be able to kill this. - nextEffect.effectTag &= ~Placement; + nextEffect.flags &= ~Placement; break; } @@ -19511,7 +19356,7 @@ function commitMutationEffects(root, renderPriorityLevel) { commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is // inserted, before any life-cycles like componentDidMount gets called. - nextEffect.effectTag &= ~Placement; // Update + nextEffect.flags &= ~Placement; // Update var _current = nextEffect.alternate; commitWork(_current, nextEffect); @@ -19519,12 +19364,12 @@ function commitMutationEffects(root, renderPriorityLevel) { } case Hydrating: { - nextEffect.effectTag &= ~Hydrating; + nextEffect.flags &= ~Hydrating; break; } case HydratingAndUpdate: { - nextEffect.effectTag &= ~Hydrating; // Update + nextEffect.flags &= ~Hydrating; // Update var _current2 = nextEffect.alternate; commitWork(_current2, nextEffect); @@ -19551,15 +19396,15 @@ function commitMutationEffects(root, renderPriorityLevel) { function commitLayoutEffects(root, committedLanes) { while (nextEffect !== null) { setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + var flags = nextEffect.flags; - if (effectTag & (Update | Callback)) { + if (flags & (Update | Callback)) { var current = nextEffect.alternate; commitLifeCycles(root, current, nextEffect); } { - if (effectTag & Ref) { + if (flags & Ref) { commitAttachRef(nextEffect); } } @@ -19578,12 +19423,8 @@ function flushPassiveEffects() { : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = NoPriority$1; - try { - setCurrentUpdateLanePriority( - schedulerPriorityToLanePriority(priorityLevel) - ); + { return runWithPriority(priorityLevel, flushPassiveEffectsImpl); - } finally { } } @@ -19604,11 +19445,11 @@ function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { pendingPassiveHookEffectsUnmount.push(effect, fiber); { - fiber.effectTag |= PassiveUnmountPendingDev; + fiber.flags |= PassiveUnmountPendingDev; var alternate = fiber.alternate; if (alternate !== null) { - alternate.effectTag |= PassiveUnmountPendingDev; + alternate.flags |= PassiveUnmountPendingDev; } } @@ -19664,11 +19505,11 @@ function flushPassiveEffectsImpl() { _effect.destroy = undefined; { - fiber.effectTag &= ~PassiveUnmountPendingDev; + fiber.flags &= ~PassiveUnmountPendingDev; var alternate = fiber.alternate; if (alternate !== null) { - alternate.effectTag &= ~PassiveUnmountPendingDev; + alternate.flags &= ~PassiveUnmountPendingDev; } } @@ -19731,7 +19572,7 @@ function flushPassiveEffectsImpl() { effect.nextEffect = null; - if (effect.effectTag & Deletion) { + if (effect.flags & Deletion) { detachFiberAfterEffects(effect); } @@ -19826,6 +19667,24 @@ function captureCommitPhaseError(sourceFiber, error) { markRootUpdated(root, SyncLane, eventTime); ensureRootIsScheduled(root, eventTime); schedulePendingInteractions(root, SyncLane); + } else { + // This component has already been unmounted. + // We can't schedule any follow up work for the root because the fiber is already unmounted, + // but we can still call the log-only boundary so the error isn't swallowed. + // + // TODO This is only a temporary bandaid for the old reconciler fork. + // We can delete this special case once the new fork is merged. + if ( + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance) + ) { + try { + instance.componentDidCatch(error, errorInfo); + } catch (errorToIgnore) { + // TODO Ignore this error? Rethrow it? + // This is kind of an edge case. + } + } } return; @@ -19940,33 +19799,6 @@ function jnd(timeElapsed) { : ceil(timeElapsed / 1960) * 1960; } -function computeMsUntilSuspenseLoadingDelay( - mostRecentEventTime, - suspenseConfig -) { - var busyMinDurationMs = suspenseConfig.busyMinDurationMs | 0; - - if (busyMinDurationMs <= 0) { - return 0; - } - - var busyDelayMs = suspenseConfig.busyDelayMs | 0; // Compute the time until this render pass would expire. - - var currentTimeMs = now(); - var eventTimeMs = mostRecentEventTime; - var timeElapsed = currentTimeMs - eventTimeMs; - - if (timeElapsed <= busyDelayMs) { - // If we haven't yet waited longer than the initial delay, we don't - // have to wait any additional time. - return 0; - } - - var msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed; // This is the value that is passed to `setTimeout`. - - return msUntilTimeout; -} - function checkForNestedUpdates() { if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { nestedUpdateCount = 0; @@ -20025,8 +19857,7 @@ function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block + tag !== SimpleMemoComponent ) { // Only warn for user-defined components, not internal ones like Suspense. return; @@ -20078,15 +19909,14 @@ function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block + tag !== SimpleMemoComponent ) { // Only warn for user-defined components, not internal ones like Suspense. return; } // If there are pending passive effects unmounts for this Fiber, // we can assume that they would have prevented this update. - if ((fiber.effectTag & PassiveUnmountPendingDev) !== NoEffect) { + if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) { return; } // We show the whole stack but dedupe on the top component's name because // the problematic code almost always lies inside that component. @@ -20219,7 +20049,7 @@ function warnAboutRenderPhaseUpdatesInDEV(fiber) { error( "Cannot update a component (`%s`) while rendering a " + "different component (`%s`). To locate the bad setState() call inside `%s`, " + - "follow the stack trace as described in https://fb.me/setstate-in-render", + "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", setStateComponentName, renderingComponentName, renderingComponentName @@ -20303,7 +20133,7 @@ function warnIfNotCurrentlyActingEffectsInDEV(fiber) { "/* assert on the output */\n\n" + "This ensures that you're testing the behavior the user would see " + "in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act", + " Learn more at https://reactjs.org/link/wrap-tests-with-act", getComponentName(fiber.type) ); } @@ -20332,7 +20162,7 @@ function warnIfNotCurrentlyActingUpdatesInDEV(fiber) { "/* assert on the output */\n\n" + "This ensures that you're testing the behavior the user would see " + "in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act", + " Learn more at https://reactjs.org/link/wrap-tests-with-act", getComponentName(fiber.type) ); } finally { @@ -20368,7 +20198,7 @@ function warnIfUnmockedScheduler(fiber) { "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" + "For more info, visit https://reactjs.org/link/mock-scheduler" ); } else { didWarnAboutUnmockedScheduler = true; @@ -20379,7 +20209,7 @@ function warnIfUnmockedScheduler(fiber) { "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" + "For more info, visit https://reactjs.org/link/mock-scheduler" ); } } @@ -20523,16 +20353,14 @@ function finishPendingInteractions(root, committedLanes) { }); } } // `act` testing API -// -// TODO: This is mostly a copy-paste from the legacy `act`, which does not have -// access to the same internals that we do here. Some trade offs in the -// implementation no longer make sense. - -var isFlushingAct = false; function shouldForceFlushFallbacksInDEV() { - return isFlushingAct; + // Never force flush in production. This function should get stripped out. + return actingUpdatesScopeDepth > 0; } +// so we can tell if any async act() calls try to run in parallel. + +var actingUpdatesScopeDepth = 0; function detachFiberAfterEffects(fiber) { fiber.sibling = null; @@ -21014,7 +20842,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.dependencies = null; this.mode = mode; // Effects - this.effectTag = NoEffect; + this.flags = NoFlags; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null; @@ -21144,7 +20972,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.type = current.type; // We already have an alternate. // Reset the effect tag. - workInProgress.effectTag = NoEffect; // The effect list is no longer valid. + workInProgress.flags = NoFlags; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -21218,7 +21046,7 @@ function resetWorkInProgress(workInProgress, renderLanes) { // avoid doing another reconciliation. // Reset the effect tag but keep any Placement tags, since that's something // that child fiber is setting, not the reconciliation. - workInProgress.effectTag &= Placement; // The effect list is no longer valid. + workInProgress.flags &= Placement; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -21382,10 +21210,6 @@ function createFiberFromTypeAndProps( fiberTag = LazyComponent; resolvedType = null; break getTag; - - case REACT_BLOCK_TYPE: - fiberTag = Block; - break getTag; } } @@ -21427,6 +21251,11 @@ function createFiberFromTypeAndProps( fiber.elementType = type; fiber.type = resolvedType; fiber.lanes = lanes; + + { + fiber._debugOwner = owner; + } + return fiber; } function createFiberFromElement(element, mode, lanes) { @@ -21579,7 +21408,7 @@ function assignFiberPropertiesInDEV(target, source) { target.memoizedState = source.memoizedState; target.dependencies = source.dependencies; target.mode = source.mode; - target.effectTag = source.effectTag; + target.flags = source.flags; target.nextEffect = source.nextEffect; target.firstEffect = source.firstEffect; target.lastEffect = source.lastEffect; @@ -21745,7 +21574,7 @@ function findHostInstanceWithWarning(component, methodName) { "%s was passed an instance of %s which is inside StrictMode. " + "Instead, add a ref directly to the element you want to reference. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node", + "https://reactjs.org/link/strict-mode-find-node", methodName, methodName, componentName @@ -21756,7 +21585,7 @@ function findHostInstanceWithWarning(component, methodName) { "%s was passed an instance of %s which renders StrictMode children. " + "Instead, add a ref directly to the element you want to reference. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node", + "https://reactjs.org/link/strict-mode-find-node", methodName, methodName, componentName @@ -21797,8 +21626,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var suspenseConfig = requestCurrentSuspenseConfig(); - var lane = requestUpdateLane(current$1, suspenseConfig); + var lane = requestUpdateLane(current$1); var context = getContextForSubtree(parentComponent); @@ -21822,7 +21650,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var update = createUpdate(eventTime, lane, suspenseConfig); // Caution: React DevTools currently depends on this property + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property // being called "element". update.payload = { @@ -21872,28 +21700,102 @@ function shouldSuspend(fiber) { return shouldSuspendImpl(fiber); } var overrideHookState = null; +var overrideHookStateDeletePath = null; +var overrideHookStateRenamePath = null; var overrideProps = null; +var overridePropsDeletePath = null; +var overridePropsRenamePath = null; var scheduleUpdate = null; var setSuspenseHandler = null; { - var copyWithSetImpl = function(obj, path, idx, value) { - if (idx >= path.length) { + var copyWithDeleteImpl = function(obj, path, index) { + var key = path[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === path.length) { + if (Array.isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } + + return updated; + } // $FlowFixMe number or string is fine here + + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; + + var copyWithDelete = function(obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; + + var copyWithRenameImpl = function(obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here + + updated[newKey] = updated[oldKey]; + + if (Array.isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } + + return updated; + }; + + var copyWithRename = function(obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); + + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); + + return; + } + } + } + + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; + + var copyWithSetImpl = function(obj, path, index, value) { + if (index >= path.length) { return value; } - var key = path[idx]; + var key = path[index]; var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); // $FlowFixMe number or string is fine here - updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); return updated; }; var copyWithSet = function(obj, path, value) { return copyWithSetImpl(obj, path, 0, value); - }; // Support DevTools editable values for useState and useReducer. + }; - overrideHookState = function(fiber, id, path, value) { + var findHook = function(fiber, id) { // For now, the "id" of stateful hooks is just the stateful hook index. // This may change in the future with e.g. nested hooks. var currentHook = fiber.memoizedState; @@ -21903,10 +21805,50 @@ var setSuspenseHandler = null; id--; } - if (currentHook !== null) { - var newState = copyWithSet(currentHook.memoizedState, path, value); - currentHook.memoizedState = newState; - currentHook.baseState = newState; // We aren't actually adding an update to the queue, + return currentHook; + }; // Support DevTools editable values for useState and useReducer. + + overrideHookState = function(fiber, id, path, value) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateDeletePath = function(fiber, id, path) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, // because there is no update we can add for useReducer hooks that won't trigger an error. // (There's no appropriate action type for DevTools overrides.) // As a result though, React will see the scheduled update as a noop and bailout. @@ -21927,6 +21869,26 @@ var setSuspenseHandler = null; scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; + overridePropsDeletePath = function(fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsRenamePath = function(fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + scheduleUpdate = function(fiber) { scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; @@ -21963,7 +21925,11 @@ function injectIntoDevTools(devToolsConfig) { rendererPackageName: devToolsConfig.rendererPackageName, rendererConfig: devToolsConfig.rendererConfig, overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, setSuspenseHandler: setSuspenseHandler, scheduleUpdate: scheduleUpdate, currentDispatcherRef: ReactCurrentDispatcher, @@ -21980,9 +21946,6 @@ function injectIntoDevTools(devToolsConfig) { }); } -// TODO: this is special because it gets imported during build. -var ReactVersion = "17.0.0-alpha.0"; - var emptyObject$1 = {}; { @@ -22360,6 +22323,31 @@ function dispatchCommand(handle, command, args) { } } +function sendAccessibilityEvent(handle, eventType) { + if (handle._nativeTag == null) { + { + error( + "sendAccessibilityEvent was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ); + } + + return; + } + + if (handle._internalInstanceHandle) { + nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ); + } else { + ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + ); + } +} + function render(element, containerTag, callback) { var root = roots.get(containerTag); @@ -22433,6 +22421,7 @@ exports.dispatchCommand = dispatchCommand; exports.findHostInstance_DEPRECATED = findHostInstance_DEPRECATED; exports.findNodeHandle = findNodeHandle; exports.render = render; +exports.sendAccessibilityEvent = sendAccessibilityEvent; exports.unmountComponentAtNode = unmountComponentAtNode; exports.unmountComponentAtNodeAndRemoveContainer = unmountComponentAtNodeAndRemoveContainer; exports.unstable_batchedUpdates = batchedUpdates; diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js index d837754c50d25c..33085b40dcd9ec 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js @@ -24,21 +24,7 @@ var Scheduler = require("scheduler"); var tracing = require("scheduler/tracing"); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Prevent newer renderers from RTE when used with older react package versions. -// Current owner and dispatcher used to share the same ref, -// but PR #14548 split them out to better support the react-debug-tools package. - -if (!ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher")) { - ReactSharedInternals.ReactCurrentDispatcher = { - current: null - }; -} - -if (!ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig")) { - ReactSharedInternals.ReactCurrentBatchConfig = { - suspense: null - }; -} + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // by calls to these methods by a Babel plugin. // @@ -80,19 +66,12 @@ function printWarning(level, format, args) { // When changing this logic, you might want to also // update consoleWithStackDev.www.js as well. { - var hasExistingStack = - args.length > 0 && - typeof args[args.length - 1] === "string" && - args[args.length - 1].indexOf("\n in") === 0; + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); - if (!hasExistingStack) { - var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - var stack = ReactDebugCurrentFrame.getStackAddendum(); - - if (stack !== "") { - format += "%s"; - args = args.concat([stack]); - } + if (stack !== "") { + format += "%s"; + args = args.concat([stack]); } var argsWithFormat = args.map(function(item) { @@ -104,161 +83,10 @@ function printWarning(level, format, args) { // eslint-disable-next-line react-internal/no-production-logging Function.prototype.apply.call(console[level], console, argsWithFormat); - - try { - // --- Welcome to debugging React --- - // This error was thrown as a convenience so that you can use this stack - // to find the callsite that caused this warning to fire. - var argIndex = 0; - var message = - "Warning: " + - format.replace(/%s/g, function() { - return args[argIndex++]; - }); - throw new Error(message); - } catch (x) {} - } -} - -var FunctionComponent = 0; -var ClassComponent = 1; -var IndeterminateComponent = 2; // Before we know whether it is function or class - -var HostRoot = 3; // Root of a host tree. Could be nested inside another node. - -var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. - -var HostComponent = 5; -var HostText = 6; -var Fragment = 7; -var Mode = 8; -var ContextConsumer = 9; -var ContextProvider = 10; -var ForwardRef = 11; -var Profiler = 12; -var SuspenseComponent = 13; -var MemoComponent = 14; -var SimpleMemoComponent = 15; -var LazyComponent = 16; -var IncompleteClassComponent = 17; -var DehydratedFragment = 18; -var SuspenseListComponent = 19; -var FundamentalComponent = 20; -var ScopeComponent = 21; -var Block = 22; - -function getParent(inst) { - do { - inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); - - if (inst) { - return inst; - } - - return null; -} -/** - * Return the lowest common ancestor of A and B, or null if they are in - * different trees. - */ - -function getLowestCommonAncestor(instA, instB) { - var depthA = 0; - - for (var tempA = instA; tempA; tempA = getParent(tempA)) { - depthA++; - } - - var depthB = 0; - - for (var tempB = instB; tempB; tempB = getParent(tempB)) { - depthB++; - } // If A is deeper, crawl up. - - while (depthA - depthB > 0) { - instA = getParent(instA); - depthA--; - } // If B is deeper, crawl up. - - while (depthB - depthA > 0) { - instB = getParent(instB); - depthB--; - } // Walk in lockstep until we find a match. - - var depth = depthA; - - while (depth--) { - if (instA === instB || instA === instB.alternate) { - return instA; - } - - instA = getParent(instA); - instB = getParent(instB); - } - - return null; -} -/** - * Return if A is an ancestor of B. - */ - -function isAncestor(instA, instB) { - while (instB) { - if (instA === instB || instA === instB.alternate) { - return true; - } - - instB = getParent(instB); - } - - return false; -} -/** - * Return the parent instance of the passed-in instance. - */ - -function getParentInstance(inst) { - return getParent(inst); -} -/** - * Simulates the traversal of a two-phase, capture/bubble event dispatch. - */ - -function traverseTwoPhase(inst, fn, arg) { - var path = []; - - while (inst) { - path.push(inst); - inst = getParent(inst); - } - - var i; - - for (i = path.length; i-- > 0; ) { - fn(path[i], "captured", arg); - } - - for (i = 0; i < path.length; i++) { - fn(path[i], "bubbled", arg); } } -var invokeGuardedCallbackImpl = function( - name, - func, - context, - a, - b, - c, - d, - e, - f -) { +function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -266,7 +94,9 @@ var invokeGuardedCallbackImpl = function( } catch (error) { this.onError(error); } -}; +} + +var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; { // In DEV mode, we swap out invokeGuardedCallback for a special version @@ -297,7 +127,7 @@ var invokeGuardedCallbackImpl = function( ) { var fakeNode = document.createElement("react"); - var invokeGuardedCallbackDev = function( + invokeGuardedCallbackImpl = function invokeGuardedCallbackDev( name, func, context, @@ -310,7 +140,7 @@ var invokeGuardedCallbackImpl = function( ) { // If document doesn't exist we know for sure we will crash in this method // when we call document.createEvent(). However this can cause confusing - // errors: https://github.com/facebookincubator/create-react-app/issues/3482 + // errors: https://github.com/facebook/create-react-app/issues/3482 // So we preemptively throw with a better message instead. if (!(typeof document !== "undefined")) { throw Error( @@ -318,7 +148,8 @@ var invokeGuardedCallbackImpl = function( ); } - var evt = document.createEvent("Event"); // Keeps track of whether the user-provided callback threw an error. We + var evt = document.createEvent("Event"); + var didCall = false; // Keeps track of whether the user-provided callback threw an error. We // set this to true at the beginning, then set it to false right after // calling the function. If the function errors, `didError` will never be // set to false. This strategy works even if the browser is flaky and @@ -335,13 +166,9 @@ var invokeGuardedCallbackImpl = function( var windowEventDescriptor = Object.getOwnPropertyDescriptor( window, "event" - ); // Create an event handler for our fake event. We will synchronously - // dispatch our fake event using `dispatchEvent`. Inside the handler, we - // call the user-provided callback. - - var funcArgs = Array.prototype.slice.call(arguments, 3); + ); - function callCallback() { + function restoreAfterDispatch() { // We immediately remove the callback from event listeners so that // nested `invokeGuardedCallback` calls do not clash. Otherwise, a // nested call would trigger the fake event handlers of any call higher @@ -357,7 +184,15 @@ var invokeGuardedCallbackImpl = function( ) { window.event = windowEvent; } + } // Create an event handler for our fake event. We will synchronously + // dispatch our fake event using `dispatchEvent`. Inside the handler, we + // call the user-provided callback. + var funcArgs = Array.prototype.slice.call(arguments, 3); + + function callCallback() { + didCall = true; + restoreAfterDispatch(); func.apply(context, funcArgs); didError = false; } // Create a global error event handler. We use this to capture the value @@ -412,7 +247,7 @@ var invokeGuardedCallbackImpl = function( Object.defineProperty(window, "event", windowEventDescriptor); } - if (didError) { + if (didCall && didError) { if (!didSetError) { // The callback errored, but the error event never fired. error = new Error( @@ -429,7 +264,7 @@ var invokeGuardedCallbackImpl = function( error = new Error( "A cross-origin error was thrown. React doesn't have access to " + "the actual error object in development. " + - "See https://fb.me/react-crossorigin-error for more information." + "See https://reactjs.org/link/crossorigin-error for more information." ); } @@ -437,9 +272,16 @@ var invokeGuardedCallbackImpl = function( } // Remove our event listeners window.removeEventListener("error", handleWindowError); - }; - invokeGuardedCallbackImpl = invokeGuardedCallbackDev; + if (!didCall) { + // Something went really wrong, and our event was not dispatched. + // https://github.com/facebook/react/issues/16734 + // https://github.com/facebook/react/issues/16585 + // Fall back to the production implementation. + restoreAfterDispatch(); + return invokeGuardedCallbackProd.apply(this, arguments); + } + }; } } @@ -708,293 +550,53 @@ function hasDispatches(event) { return !!event._dispatchListeners; } -function isInteractive(tag) { - return ( - tag === "button" || - tag === "input" || - tag === "select" || - tag === "textarea" - ); -} - -function shouldPreventMouseEvent(name, type, props) { - switch (name) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - return !!(props.disabled && isInteractive(type)); - - default: - return false; - } -} +var EVENT_POOL_SIZE = 10; /** - * @param {object} inst The instance, which is the source of events. - * @param {string} registrationName Name of listener (e.g. `onClick`). - * @return {?function} The stored callback. + * @interface Event + * @see http://www.w3.org/TR/DOM-Level-3-Events/ */ -function getListener(inst, registrationName) { - var listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not - // live here; needs to be moved to a better place soon - - var stateNode = inst.stateNode; - - if (!stateNode) { - // Work in progress (ex: onload events in incremental mode). - return null; - } - - var props = getFiberCurrentPropsFromNode(stateNode); - - if (!props) { - // Work in progress. - return null; - } - - listener = props[registrationName]; - - if (shouldPreventMouseEvent(registrationName, inst.type, props)) { +var EventInterface = { + type: null, + target: null, + // currentTarget is set when dispatching; no use in copying it here + currentTarget: function() { return null; - } - - if (!(!listener || typeof listener === "function")) { - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - } + }, + eventPhase: null, + bubbles: null, + cancelable: null, + timeStamp: function(event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: null, + isTrusted: null +}; - return listener; +function functionThatReturnsTrue() { + return true; } +function functionThatReturnsFalse() { + return false; +} /** - * Accumulates items that must not be null or undefined into the first one. This - * is used to conserve memory by avoiding array allocations, and thus sacrifices - * API cleanness. Since `current` can be null before being passed in and not - * null after this function, make sure to assign it back to `current`: + * Synthetic events are dispatched by event plugins, typically in response to a + * top-level event delegation handler. * - * `a = accumulateInto(a, b);` + * These systems should generally use pooling to reduce the frequency of garbage + * collection. The system should check `isPersistent` to determine whether the + * event should be released into the pool after being dispatched. Users that + * need a persisted event should invoke `persist`. * - * This API should be sparingly used. Try `accumulate` for something cleaner. + * Synthetic events (and subclasses) implement the DOM Level 3 Events API by + * normalizing browser quirks. Subclasses do not necessarily have to implement a + * DOM interface; custom application-specific events can also subclass this. * - * @return {*|array<*>} An accumulation of items. - */ - -function accumulateInto(current, next) { - if (!(next != null)) { - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - } - - if (current == null) { - return next; - } // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). - - if (Array.isArray(current)) { - if (Array.isArray(next)) { - current.push.apply(current, next); - return current; - } - - current.push(next); - return current; - } - - if (Array.isArray(next)) { - // A bit too dangerous to mutate `next`. - return [current].concat(next); - } - - return [current, next]; -} - -/** - * @param {array} arr an "accumulation" of items which is either an Array or - * a single item. Useful when paired with the `accumulate` module. This is a - * simple utility that allows us to reason about a collection of items, but - * handling the case when there is exactly one item (and we do not need to - * allocate an array). - * @param {function} cb Callback invoked with each element or a collection. - * @param {?} [scope] Scope used as `this` in a callback. - */ -function forEachAccumulated(arr, cb, scope) { - if (Array.isArray(arr)) { - arr.forEach(cb, scope); - } else if (arr) { - cb.call(scope, arr); - } -} - -/** - * Some event types have a notion of different registration names for different - * "phases" of propagation. This finds listeners by a given phase. - */ -function listenerAtPhase(inst, event, propagationPhase) { - var registrationName = - event.dispatchConfig.phasedRegistrationNames[propagationPhase]; - return getListener(inst, registrationName); -} -/** - * A small set of propagation patterns, each of which will accept a small amount - * of information, and generate a set of "dispatch ready event objects" - which - * are sets of events that have already been annotated with a set of dispatched - * listener functions/ids. The API is designed this way to discourage these - * propagation strategies from actually executing the dispatches, since we - * always want to collect the entire set of dispatches before executing even a - * single one. - */ - -/** - * Tags a `SyntheticEvent` with dispatched listeners. Creating this function - * here, allows us to not have to bind or create functions for each event. - * Mutating the event's members allows us to not have to create a wrapping - * "dispatch" object that pairs the event with the listener. - */ - -function accumulateDirectionalDispatches(inst, phase, event) { - { - if (!inst) { - error("Dispatching inst must not be null"); - } - } - - var listener = listenerAtPhase(inst, event, phase); - - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } -} -/** - * Collect dispatches (must be entirely collected before dispatching - see unit - * tests). Lazily allocate the array to conserve memory. We must loop through - * each event and perform the traversal for each one. We cannot perform a - * single traversal for the entire collection of events because each event may - * have a different target. - */ - -function accumulateTwoPhaseDispatchesSingle(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); - } -} -/** - * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. - */ - -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - var parentInst = targetInst ? getParentInstance(targetInst) : null; - traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); - } -} -/** - * Accumulates without regard to direction, does not look for phased - * registration names. Same as `accumulateDirectDispatchesSingle` but without - * requiring that the `dispatchMarker` be the same as the dispatched ID. - */ - -function accumulateDispatches(inst, ignoredDirection, event) { - if (inst && event && event.dispatchConfig.registrationName) { - var registrationName = event.dispatchConfig.registrationName; - var listener = getListener(inst, registrationName); - - if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); - } - } -} -/** - * Accumulates dispatches on an `SyntheticEvent`, but only for the - * `dispatchMarker`. - * @param {SyntheticEvent} event - */ - -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - accumulateDispatches(event._targetInst, null, event); - } -} - -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); -} -function accumulateTwoPhaseDispatchesSkipTarget(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); -} -function accumulateDirectDispatches(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle); -} - -var EVENT_POOL_SIZE = 10; -/** - * @interface Event - * @see http://www.w3.org/TR/DOM-Level-3-Events/ - */ - -var EventInterface = { - type: null, - target: null, - // currentTarget is set when dispatching; no use in copying it here - currentTarget: function() { - return null; - }, - eventPhase: null, - bubbles: null, - cancelable: null, - timeStamp: function(event) { - return event.timeStamp || Date.now(); - }, - defaultPrevented: null, - isTrusted: null -}; - -function functionThatReturnsTrue() { - return true; -} - -function functionThatReturnsFalse() { - return false; -} -/** - * Synthetic events are dispatched by event plugins, typically in response to a - * top-level event delegation handler. - * - * These systems should generally use pooling to reduce the frequency of garbage - * collection. The system should check `isPersistent` to determine whether the - * event should be released into the pool after being dispatched. Users that - * need a persisted event should invoke `persist`. - * - * Synthetic events (and subclasses) implement the DOM Level 3 Events API by - * normalizing browser quirks. Subclasses do not necessarily have to implement a - * DOM interface; custom application-specific events can also subclass this. - * - * @param {object} dispatchConfig Configuration used to dispatch this event. - * @param {*} targetInst Marker identifying the event target. - * @param {object} nativeEvent Native browser event. - * @param {DOMEventTarget} nativeEventTarget Target node. + * @param {object} dispatchConfig Configuration used to dispatch this event. + * @param {*} targetInst Marker identifying the event target. + * @param {object} nativeEvent Native browser event. + * @param {DOMEventTarget} nativeEventTarget Target node. */ function SyntheticEvent( @@ -1015,6 +617,8 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchListeners = null; + this._dispatchInstances = null; var Interface = this.constructor.Interface; for (var propName in Interface) { @@ -1203,13 +807,6 @@ addEventPoolingTo(SyntheticEvent); */ function getPooledWarningPropertyDefinition(propName, getVal) { - var isFunction = typeof getVal === "function"; - return { - configurable: true, - set: set, - get: get - }; - function set(val) { var action = isFunction ? "setting the method" : "setting the property"; warn(action, "This is effectively a no-op"); @@ -1231,16 +828,28 @@ function getPooledWarningPropertyDefinition(propName, getVal) { "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", + "See https://reactjs.org/link/event-pooling for more information.", action, propName, result ); } } + + var isFunction = typeof getVal === "function"; + return { + configurable: true, + set: set, + get: get + }; } -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { var EventConstructor = this; if (EventConstructor.eventPool.length) { @@ -1280,8 +889,8 @@ function releasePooledEvent(event) { } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } @@ -1547,51 +1156,139 @@ function accumulate(current, next) { } /** - * Instance of element that should respond to touch/move types of interactions, - * as indicated explicitly by relevant callbacks. + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. + * + * @return {*|array<*>} An accumulation of items. */ -var responderInst = null; -/** - * Count of current touches. A textInput should become responder iff the - * selection changes while there is a touch on the screen. - */ +function accumulateInto(current, next) { + if (!(next != null)) { + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + } -var trackedTouchCount = 0; + if (current == null) { + return next; + } // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). -var changeResponder = function(nextResponderInst, blockHostResponder) { - var oldResponderInst = responderInst; - responderInst = nextResponderInst; + if (Array.isArray(current)) { + if (Array.isArray(next)) { + current.push.apply(current, next); + return current; + } - if (ResponderEventPlugin.GlobalResponderHandler !== null) { - ResponderEventPlugin.GlobalResponderHandler.onChange( - oldResponderInst, - nextResponderInst, - blockHostResponder - ); + current.push(next); + return current; } -}; -var eventTypes = { - /** - * On a `touchStart`/`mouseDown`, is it desired that this element become the - * responder? - */ - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, + if (Array.isArray(next)) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } - /** - * On a `scroll`, is it desired that this element become the responder? This - * is usually not needed, but should be used to retroactively infer that a - * `touchStart` had occurred during momentum scroll. During a momentum scroll, - * a touch start will be immediately followed by a scroll event if the view is - * currently scrolling. - * + return [current, next]; +} + +/** + * @param {array} arr an "accumulation" of items which is either an Array or + * a single item. Useful when paired with the `accumulate` module. This is a + * simple utility that allows us to reason about a collection of items, but + * handling the case when there is exactly one item (and we do not need to + * allocate an array). + * @param {function} cb Callback invoked with each element or a collection. + * @param {?} [scope] Scope used as `this` in a callback. + */ +function forEachAccumulated(arr, cb, scope) { + if (Array.isArray(arr)) { + arr.forEach(cb, scope); + } else if (arr) { + cb.call(scope, arr); + } +} + +var FunctionComponent = 0; +var ClassComponent = 1; +var IndeterminateComponent = 2; // Before we know whether it is function or class + +var HostRoot = 3; // Root of a host tree. Could be nested inside another node. + +var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. + +var HostComponent = 5; +var HostText = 6; +var Fragment = 7; +var Mode = 8; +var ContextConsumer = 9; +var ContextProvider = 10; +var ForwardRef = 11; +var Profiler = 12; +var SuspenseComponent = 13; +var MemoComponent = 14; +var SimpleMemoComponent = 15; +var LazyComponent = 16; +var IncompleteClassComponent = 17; +var DehydratedFragment = 18; +var SuspenseListComponent = 19; +var FundamentalComponent = 20; +var ScopeComponent = 21; +var OffscreenComponent = 22; +var LegacyHiddenComponent = 23; + +/** + * Instance of element that should respond to touch/move types of interactions, + * as indicated explicitly by relevant callbacks. + */ + +var responderInst = null; +/** + * Count of current touches. A textInput should become responder iff the + * selection changes while there is a touch on the screen. + */ + +var trackedTouchCount = 0; + +var changeResponder = function(nextResponderInst, blockHostResponder) { + var oldResponderInst = responderInst; + responderInst = nextResponderInst; + + if (ResponderEventPlugin.GlobalResponderHandler !== null) { + ResponderEventPlugin.GlobalResponderHandler.onChange( + oldResponderInst, + nextResponderInst, + blockHostResponder + ); + } +}; + +var eventTypes = { + /** + * On a `touchStart`/`mouseDown`, is it desired that this element become the + * responder? + */ + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" + }, + dependencies: startDependencies + }, + + /** + * On a `scroll`, is it desired that this element become the responder? This + * is usually not needed, but should be used to retroactively infer that a + * `touchStart` had occurred during momentum scroll. During a momentum scroll, + * a touch start will be immediately followed by a scroll event if the view is + * currently scrolling. + * * TODO: This shouldn't bubble. */ scrollShouldSetResponder: { @@ -1664,610 +1361,818 @@ var eventTypes = { registrationName: "onResponderTerminate", dependencies: [] } -}; +}; // Start of inline: the below functions were inlined from +// EventPropagator.js, as they deviated from ReactDOM's newer +// implementations. + +function getParent(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + + if (inst) { + return inst; + } + + return null; +} /** - * - * Responder System: - * ---------------- - * - * - A global, solitary "interaction lock" on a view. - * - If a node becomes the responder, it should convey visual feedback - * immediately to indicate so, either by highlighting or moving accordingly. - * - To be the responder means, that touches are exclusively important to that - * responder view, and no other view. - * - While touches are still occurring, the responder lock can be transferred to - * a new view, but only to increasingly "higher" views (meaning ancestors of - * the current responder). - * - * Responder being granted: - * ------------------------ - * - * - Touch starts, moves, and scrolls can cause an ID to become the responder. - * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to - * the "appropriate place". - * - If nothing is currently the responder, the "appropriate place" is the - * initiating event's `targetID`. - * - If something *is* already the responder, the "appropriate place" is the - * first common ancestor of the event target and the current `responderInst`. - * - Some negotiation happens: See the timing diagram below. - * - Scrolled views automatically become responder. The reasoning is that a - * platform scroll view that isn't built on top of the responder system has - * began scrolling, and the active responder must now be notified that the - * interaction is no longer locked to it - the system has taken over. - * - * - Responder being released: - * As soon as no more touches that *started* inside of descendants of the - * *current* responderInst, an `onResponderRelease` event is dispatched to the - * current responder, and the responder lock is released. - * - * TODO: - * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that - * determines if the responder lock should remain. - * - If a view shouldn't "remain" the responder, any active touches should by - * default be considered "dead" and do not influence future negotiations or - * bubble paths. It should be as if those touches do not exist. - * -- For multitouch: Usually a translate-z will choose to "remain" responder - * after one out of many touches ended. For translate-y, usually the view - * doesn't wish to "remain" responder after one of many touches end. - * - Consider building this on top of a `stopPropagation` model similar to - * `W3C` events. - * - Ensure that `onResponderTerminate` is called on touch cancels, whether or - * not `onResponderTerminationRequest` returns `true` or `false`. - * + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. */ -/* Negotiation Performed - +-----------------------+ - / \ -Process low level events to + Current Responder + wantsResponderID -determine who to perform negot-| (if any exists at all) | -iation/transition | Otherwise just pass through| --------------------------------+----------------------------+------------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchStart| | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderReject - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderStart| - | | +----------------+ -Bubble to find first ID | | -to return true:wantsResponderID| | - | | - +-------------+ | | - | onTouchMove | | | - +------+------+ none | | - | return| | -+-----------v-------------+true| +------------------------+ | -|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ -+-----------+-------------+ | +------------------------+ | | - | | | +--------+-------+ - | returned true for| false:REJECT +-------->|onResponderRejec| - | wantsResponderID | | | +----------------+ - | (now attempt | +------------------+-----+ | - | handoff) | | onResponder | | - +------------------->| TerminationRequest| | - | +------------------+-----+ | - | | | +----------------+ - | true:GRANT +-------->|onResponderGrant| - | | +--------+-------+ - | +------------------------+ | | - | | onResponderTerminate |<-----------+ - | +------------------+-----+ | - | | | +----------------+ - | +-------->|onResponderMove | - | | +----------------+ - | | - | | - Some active touch started| | - inside current responder | +------------------------+ | - +------------------------->| onResponderEnd | | - | | +------------------------+ | - +---+---------+ | | - | onTouchEnd | | | - +---+---------+ | | - | | +------------------------+ | - +------------------------->| onResponderEnd | | - No active touches started| +-----------+------------+ | - inside current responder | | | - | v | - | +------------------------+ | - | | onResponderRelease | | - | +------------------------+ | - | | - + + */ +function getLowestCommonAncestor(instA, instB) { + var depthA = 0; -/** - * A note about event ordering in the `EventPluginRegistry`. - * - * Suppose plugins are injected in the following order: - * - * `[R, S, C]` - * - * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for - * `onClick` etc) and `R` is `ResponderEventPlugin`. - * - * "Deferred-Dispatched Events": - * - * - The current event plugin system will traverse the list of injected plugins, - * in order, and extract events by collecting the plugin's return value of - * `extractEvents()`. - * - These events that are returned from `extractEvents` are "deferred - * dispatched events". - * - When returned from `extractEvents`, deferred-dispatched events contain an - * "accumulation" of deferred dispatches. - * - These deferred dispatches are accumulated/collected before they are - * returned, but processed at a later time by the `EventPluginRegistry` (hence the - * name deferred). - * - * In the process of returning their deferred-dispatched events, event plugins - * themselves can dispatch events on-demand without returning them from - * `extractEvents`. Plugins might want to do this, so that they can use event - * dispatching as a tool that helps them decide which events should be extracted - * in the first place. - * - * "On-Demand-Dispatched Events": - * - * - On-demand-dispatched events are not returned from `extractEvents`. - * - On-demand-dispatched events are dispatched during the process of returning - * the deferred-dispatched events. - * - They should not have side effects. - * - They should be avoided, and/or eventually be replaced with another - * abstraction that allows event plugins to perform multiple "rounds" of event - * extraction. - * - * Therefore, the sequence of event dispatches becomes: - * - * - `R`s on-demand events (if any) (dispatched by `R` on-demand) - * - `S`s on-demand events (if any) (dispatched by `S` on-demand) - * - `C`s on-demand events (if any) (dispatched by `C` on-demand) - * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) - * - * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` - * on-demand dispatch returns `true` (and some other details are satisfied) the - * `onResponderGrant` deferred dispatched event is returned from - * `extractEvents`. The sequence of dispatch executions in this case - * will appear as follows: - * - * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) - * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) - * - `touchStart` (`EventPluginRegistry` dispatches as usual) - * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) - */ - -function setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget -) { - var shouldSetEventType = isStartish(topLevelType) - ? eventTypes.startShouldSetResponder - : isMoveish(topLevelType) - ? eventTypes.moveShouldSetResponder - : topLevelType === TOP_SELECTION_CHANGE - ? eventTypes.selectionChangeShouldSetResponder - : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. - - var bubbleShouldSetFrom = !responderInst - ? targetInst - : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target - // (deepest ID) if it happens to be the current responder. The reasoning: - // It's strange to get an `onMoveShouldSetResponder` when you're *already* - // the responder. - - var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; - var shouldSetEvent = ResponderSyntheticEvent.getPooled( - shouldSetEventType, - bubbleShouldSetFrom, - nativeEvent, - nativeEventTarget - ); - shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - - if (skipOverBubbleShouldSetFrom) { - accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); - } else { - accumulateTwoPhaseDispatches(shouldSetEvent); + for (var tempA = instA; tempA; tempA = getParent(tempA)) { + depthA++; } - var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + var depthB = 0; - if (!shouldSetEvent.isPersistent()) { - shouldSetEvent.constructor.release(shouldSetEvent); - } + for (var tempB = instB; tempB; tempB = getParent(tempB)) { + depthB++; + } // If A is deeper, crawl up. - if (!wantsResponderInst || wantsResponderInst === responderInst) { - return null; - } + while (depthA - depthB > 0) { + instA = getParent(instA); + depthA--; + } // If B is deeper, crawl up. - var extracted; - var grantEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderGrant, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(grantEvent); - var blockHostResponder = executeDirectDispatch(grantEvent) === true; + while (depthB - depthA > 0) { + instB = getParent(instB); + depthB--; + } // Walk in lockstep until we find a match. - if (responderInst) { - var terminationRequestEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminationRequest, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminationRequestEvent.touchHistory = - ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminationRequestEvent); - var shouldSwitch = - !hasDispatches(terminationRequestEvent) || - executeDirectDispatch(terminationRequestEvent); + var depth = depthA; - if (!terminationRequestEvent.isPersistent()) { - terminationRequestEvent.constructor.release(terminationRequestEvent); + while (depth--) { + if (instA === instB || instA === instB.alternate) { + return instA; } - if (shouldSwitch) { - var terminateEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderTerminate, - responderInst, - nativeEvent, - nativeEventTarget - ); - terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(terminateEvent); - extracted = accumulate(extracted, [grantEvent, terminateEvent]); - changeResponder(wantsResponderInst, blockHostResponder); - } else { - var rejectEvent = ResponderSyntheticEvent.getPooled( - eventTypes.responderReject, - wantsResponderInst, - nativeEvent, - nativeEventTarget - ); - rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(rejectEvent); - extracted = accumulate(extracted, rejectEvent); - } - } else { - extracted = accumulate(extracted, grantEvent); - changeResponder(wantsResponderInst, blockHostResponder); + instA = getParent(instA); + instB = getParent(instB); } - return extracted; + return null; } /** - * A transfer is a negotiation between a currently set responder and the next - * element to claim responder status. Any start event could trigger a transfer - * of responderInst. Any move event could trigger a transfer. - * - * @param {string} topLevelType Record from `BrowserEventConstants`. - * @return {boolean} True if a transfer of responder could possibly occur. + * Return if A is an ancestor of B. */ -function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { - return ( - topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically - // tracking native scroll events here and responderIgnoreScroll indicates we - // will send topTouchCancel to handle canceling touch events instead - ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || - (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || - isStartish(topLevelType) || - isMoveish(topLevelType)) - ); +function isAncestor(instA, instB) { + while (instB) { + if (instA === instB || instA === instB.alternate) { + return true; + } + + instB = getParent(instB); + } + + return false; } /** - * Returns whether or not this touch end event makes it such that there are no - * longer any touches that started inside of the current `responderInst`. - * - * @param {NativeEvent} nativeEvent Native touch end event. - * @return {boolean} Whether or not this touch end event ends the responder. + * Simulates the traversal of a two-phase, capture/bubble event dispatch. */ -function noResponderTouches(nativeEvent) { - var touches = nativeEvent.touches; +function traverseTwoPhase(inst, fn, arg) { + var path = []; - if (!touches || touches.length === 0) { - return true; + while (inst) { + path.push(inst); + inst = getParent(inst); } - for (var i = 0; i < touches.length; i++) { - var activeTouch = touches[i]; - var target = activeTouch.target; - - if (target !== null && target !== undefined && target !== 0) { - // Is the original touch location inside of the current responder? - var targetInst = getInstanceFromNode(target); + var i; - if (isAncestor(responderInst, targetInst)) { - return false; - } - } + for (i = path.length; i-- > 0; ) { + fn(path[i], "captured", arg); } - return true; + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } } -var ResponderEventPlugin = { - /* For unit testing only */ - _getResponder: function() { - return responderInst; - }, - eventTypes: eventTypes, +function getListener(inst, registrationName) { + var stateNode = inst.stateNode; - /** - * We must be resilient to `targetInst` being `null` on `touchMove` or - * `touchEnd`. On certain platforms, this means that a native scroll has - * assumed control and the original touch targets are destroyed. - */ - extractEvents: function( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget, - eventSystemFlags - ) { - if (isStartish(topLevelType)) { - trackedTouchCount += 1; - } else if (isEndish(topLevelType)) { - if (trackedTouchCount >= 0) { - trackedTouchCount -= 1; - } else { - { - warn( - "Ended a touch event which was not counted in `trackedTouchCount`." - ); - } + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } - return null; - } - } + var props = getFiberCurrentPropsFromNode(stateNode); - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); - var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) - ? setResponderAndExtractTransfer( - topLevelType, - targetInst, - nativeEvent, - nativeEventTarget - ) - : null; // Responder may or may not have transferred on a new touch start/move. - // Regardless, whoever is the responder after any potential transfer, we - // direct all touch start/move/ends to them in the form of - // `onResponderMove/Start/End`. These will be called for *every* additional - // finger that move/start/end, dispatched directly to whoever is the - // current responder at that moment, until the responder is "released". - // - // These multiple individual change touch events are are always bookended - // by `onResponderGrant`, and one of - // (`onResponderRelease/onResponderTerminate`). + if (props === null) { + // Work in progress. + return null; + } - var isResponderTouchStart = responderInst && isStartish(topLevelType); - var isResponderTouchMove = responderInst && isMoveish(topLevelType); - var isResponderTouchEnd = responderInst && isEndish(topLevelType); - var incrementalTouch = isResponderTouchStart - ? eventTypes.responderStart - : isResponderTouchMove - ? eventTypes.responderMove - : isResponderTouchEnd - ? eventTypes.responderEnd - : null; + var listener = props[registrationName]; - if (incrementalTouch) { - var gesture = ResponderSyntheticEvent.getPooled( - incrementalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(gesture); - extracted = accumulate(extracted, gesture); - } + if (!(!listener || typeof listener === "function")) { + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } - var isResponderTerminate = - responderInst && topLevelType === TOP_TOUCH_CANCEL; - var isResponderRelease = - responderInst && - !isResponderTerminate && - isEndish(topLevelType) && - noResponderTouches(nativeEvent); - var finalTouch = isResponderTerminate - ? eventTypes.responderTerminate - : isResponderRelease - ? eventTypes.responderRelease - : null; + return listener; +} - if (finalTouch) { - var finalEvent = ResponderSyntheticEvent.getPooled( - finalTouch, - responderInst, - nativeEvent, - nativeEventTarget - ); - finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; - accumulateDirectDispatches(finalEvent); - extracted = accumulate(extracted, finalEvent); - changeResponder(null); - } +function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); +} - return extracted; - }, - GlobalResponderHandler: null, - injection: { - /** - * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler - * Object that handles any change in responder. Use this to inject - * integration with an existing touch handling system etc. - */ - injectGlobalResponderHandler: function(GlobalResponderHandler) { - ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; +function accumulateDirectionalDispatches(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); } } -}; -/** - * Injectable ordering of event plugins. - */ -var eventPluginOrder = null; -/** - * Injectable mapping from names to event plugin modules. - */ + var listener = listenerAtPhase(inst, event, phase); -var namesToPlugins = {}; + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} /** - * Recomputes the plugin list using the injected plugins and plugin ordering. - * - * @private + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. */ -function recomputePluginOrdering() { - if (!eventPluginOrder) { - // Wait until an `eventPluginOrder` is injected. - return; - } - - for (var pluginName in namesToPlugins) { - var pluginModule = namesToPlugins[pluginName]; - var pluginIndex = eventPluginOrder.indexOf(pluginName); - - if (!(pluginIndex > -1)) { - throw Error( - "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + - pluginName + - "`." - ); - } - - if (plugins[pluginIndex]) { - continue; - } +function accumulateDispatches(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); - if (!pluginModule.extractEvents) { - throw Error( - "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + - pluginName + - "` does not." + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener ); - } - - plugins[pluginIndex] = pluginModule; - var publishedEvents = pluginModule.eventTypes; - - for (var eventName in publishedEvents) { - if ( - !publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName - ) - ) { - throw Error( - "EventPluginRegistry: Failed to publish event `" + - eventName + - "` for plugin `" + - pluginName + - "`." - ); - } + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); } } } /** - * Publishes an event so that it can be dispatched by the supplied plugin. - * - * @param {object} dispatchConfig Dispatch configuration for the event. - * @param {object} PluginModule Plugin publishing the event. - * @return {boolean} True if the event was successfully published. - * @private + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event */ -function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { - if (!!eventNameDispatchConfigs.hasOwnProperty(eventName)) { - throw Error( - "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + - eventName + - "`." - ); +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); } +} - eventNameDispatchConfigs[eventName] = dispatchConfig; - var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; - - if (phasedRegistrationNames) { - for (var phaseName in phasedRegistrationNames) { - if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - var phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName( - phasedRegistrationName, - pluginModule, - eventName - ); - } - } +function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); +} - return true; - } else if (dispatchConfig.registrationName) { - publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName - ); - return true; +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); } +} - return false; +function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); } -/** - * Publishes a registration name that is used to identify dispatched events. - * - * @param {string} registrationName Registration name to add. - * @param {object} PluginModule Plugin publishing the event. - * @private - */ -function publishRegistrationName(registrationName, pluginModule, eventName) { - if (!!registrationNameModules[registrationName]) { - throw Error( - "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + - registrationName + - "`." - ); +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } +} - registrationNameModules[registrationName] = pluginModule; - registrationNameDependencies[registrationName] = - pluginModule.eventTypes[eventName].dependencies; +function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); +} // End of inline - { - var lowerCasedName = registrationName.toLowerCase(); - } -} /** - * Registers plugins so that they can extract and dispatch events. + * + * Responder System: + * ---------------- + * + * - A global, solitary "interaction lock" on a view. + * - If a node becomes the responder, it should convey visual feedback + * immediately to indicate so, either by highlighting or moving accordingly. + * - To be the responder means, that touches are exclusively important to that + * responder view, and no other view. + * - While touches are still occurring, the responder lock can be transferred to + * a new view, but only to increasingly "higher" views (meaning ancestors of + * the current responder). + * + * Responder being granted: + * ------------------------ + * + * - Touch starts, moves, and scrolls can cause an ID to become the responder. + * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to + * the "appropriate place". + * - If nothing is currently the responder, the "appropriate place" is the + * initiating event's `targetID`. + * - If something *is* already the responder, the "appropriate place" is the + * first common ancestor of the event target and the current `responderInst`. + * - Some negotiation happens: See the timing diagram below. + * - Scrolled views automatically become responder. The reasoning is that a + * platform scroll view that isn't built on top of the responder system has + * began scrolling, and the active responder must now be notified that the + * interaction is no longer locked to it - the system has taken over. + * + * - Responder being released: + * As soon as no more touches that *started* inside of descendants of the + * *current* responderInst, an `onResponderRelease` event is dispatched to the + * current responder, and the responder lock is released. + * + * TODO: + * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that + * determines if the responder lock should remain. + * - If a view shouldn't "remain" the responder, any active touches should by + * default be considered "dead" and do not influence future negotiations or + * bubble paths. It should be as if those touches do not exist. + * -- For multitouch: Usually a translate-z will choose to "remain" responder + * after one out of many touches ended. For translate-y, usually the view + * doesn't wish to "remain" responder after one of many touches end. + * - Consider building this on top of a `stopPropagation` model similar to + * `W3C` events. + * - Ensure that `onResponderTerminate` is called on touch cancels, whether or + * not `onResponderTerminationRequest` returns `true` or `false`. + * + */ + +/* Negotiation Performed + +-----------------------+ + / \ +Process low level events to + Current Responder + wantsResponderID +determine who to perform negot-| (if any exists at all) | +iation/transition | Otherwise just pass through| +-------------------------------+----------------------------+------------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchStart| | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderReject + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderStart| + | | +----------------+ +Bubble to find first ID | | +to return true:wantsResponderID| | + | | + +-------------+ | | + | onTouchMove | | | + +------+------+ none | | + | return| | ++-----------v-------------+true| +------------------------+ | +|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+ ++-----------+-------------+ | +------------------------+ | | + | | | +--------+-------+ + | returned true for| false:REJECT +-------->|onResponderRejec| + | wantsResponderID | | | +----------------+ + | (now attempt | +------------------+-----+ | + | handoff) | | onResponder | | + +------------------->| TerminationRequest| | + | +------------------+-----+ | + | | | +----------------+ + | true:GRANT +-------->|onResponderGrant| + | | +--------+-------+ + | +------------------------+ | | + | | onResponderTerminate |<-----------+ + | +------------------+-----+ | + | | | +----------------+ + | +-------->|onResponderMove | + | | +----------------+ + | | + | | + Some active touch started| | + inside current responder | +------------------------+ | + +------------------------->| onResponderEnd | | + | | +------------------------+ | + +---+---------+ | | + | onTouchEnd | | | + +---+---------+ | | + | | +------------------------+ | + +------------------------->| onResponderEnd | | + No active touches started| +-----------+------------+ | + inside current responder | | | + | v | + | +------------------------+ | + | | onResponderRelease | | + | +------------------------+ | + | | + + + */ + +/** + * A note about event ordering in the `EventPluginRegistry`. + * + * Suppose plugins are injected in the following order: + * + * `[R, S, C]` + * + * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for + * `onClick` etc) and `R` is `ResponderEventPlugin`. + * + * "Deferred-Dispatched Events": + * + * - The current event plugin system will traverse the list of injected plugins, + * in order, and extract events by collecting the plugin's return value of + * `extractEvents()`. + * - These events that are returned from `extractEvents` are "deferred + * dispatched events". + * - When returned from `extractEvents`, deferred-dispatched events contain an + * "accumulation" of deferred dispatches. + * - These deferred dispatches are accumulated/collected before they are + * returned, but processed at a later time by the `EventPluginRegistry` (hence the + * name deferred). + * + * In the process of returning their deferred-dispatched events, event plugins + * themselves can dispatch events on-demand without returning them from + * `extractEvents`. Plugins might want to do this, so that they can use event + * dispatching as a tool that helps them decide which events should be extracted + * in the first place. + * + * "On-Demand-Dispatched Events": + * + * - On-demand-dispatched events are not returned from `extractEvents`. + * - On-demand-dispatched events are dispatched during the process of returning + * the deferred-dispatched events. + * - They should not have side effects. + * - They should be avoided, and/or eventually be replaced with another + * abstraction that allows event plugins to perform multiple "rounds" of event + * extraction. + * + * Therefore, the sequence of event dispatches becomes: + * + * - `R`s on-demand events (if any) (dispatched by `R` on-demand) + * - `S`s on-demand events (if any) (dispatched by `S` on-demand) + * - `C`s on-demand events (if any) (dispatched by `C` on-demand) + * - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`) + * + * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder` + * on-demand dispatch returns `true` (and some other details are satisfied) the + * `onResponderGrant` deferred dispatched event is returned from + * `extractEvents`. The sequence of dispatch executions in this case + * will appear as follows: + * + * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand) + * - `touchStartCapture` (`EventPluginRegistry` dispatches as usual) + * - `touchStart` (`EventPluginRegistry` dispatches as usual) + * - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual) + */ + +function setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var shouldSetEventType = isStartish(topLevelType) + ? eventTypes.startShouldSetResponder + : isMoveish(topLevelType) + ? eventTypes.moveShouldSetResponder + : topLevelType === TOP_SELECTION_CHANGE + ? eventTypes.selectionChangeShouldSetResponder + : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder. + + var bubbleShouldSetFrom = !responderInst + ? targetInst + : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target + // (deepest ID) if it happens to be the current responder. The reasoning: + // It's strange to get an `onMoveShouldSetResponder` when you're *already* + // the responder. + + var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst; + var shouldSetEvent = ResponderSyntheticEvent.getPooled( + shouldSetEventType, + bubbleShouldSetFrom, + nativeEvent, + nativeEventTarget + ); + shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + + if (skipOverBubbleShouldSetFrom) { + accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent); + } else { + accumulateTwoPhaseDispatches(shouldSetEvent); + } + + var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); + + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } + + if (!wantsResponderInst || wantsResponderInst === responderInst) { + return null; + } + + var extracted; + var grantEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderGrant, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(grantEvent); + var blockHostResponder = executeDirectDispatch(grantEvent) === true; + + if (responderInst) { + var terminationRequestEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminationRequest, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminationRequestEvent.touchHistory = + ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminationRequestEvent); + var shouldSwitch = + !hasDispatches(terminationRequestEvent) || + executeDirectDispatch(terminationRequestEvent); + + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } + + if (shouldSwitch) { + var terminateEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderTerminate, + responderInst, + nativeEvent, + nativeEventTarget + ); + terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(terminateEvent); + extracted = accumulate(extracted, [grantEvent, terminateEvent]); + changeResponder(wantsResponderInst, blockHostResponder); + } else { + var rejectEvent = ResponderSyntheticEvent.getPooled( + eventTypes.responderReject, + wantsResponderInst, + nativeEvent, + nativeEventTarget + ); + rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(rejectEvent); + extracted = accumulate(extracted, rejectEvent); + } + } else { + extracted = accumulate(extracted, grantEvent); + changeResponder(wantsResponderInst, blockHostResponder); + } + + return extracted; +} +/** + * A transfer is a negotiation between a currently set responder and the next + * element to claim responder status. Any start event could trigger a transfer + * of responderInst. Any move event could trigger a transfer. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @return {boolean} True if a transfer of responder could possibly occur. + */ + +function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { + return ( + topLevelInst && // responderIgnoreScroll: We are trying to migrate away from specifically + // tracking native scroll events here and responderIgnoreScroll indicates we + // will send topTouchCancel to handle canceling touch events instead + ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || + isStartish(topLevelType) || + isMoveish(topLevelType)) + ); +} +/** + * Returns whether or not this touch end event makes it such that there are no + * longer any touches that started inside of the current `responderInst`. + * + * @param {NativeEvent} nativeEvent Native touch end event. + * @return {boolean} Whether or not this touch end event ends the responder. + */ + +function noResponderTouches(nativeEvent) { + var touches = nativeEvent.touches; + + if (!touches || touches.length === 0) { + return true; + } + + for (var i = 0; i < touches.length; i++) { + var activeTouch = touches[i]; + var target = activeTouch.target; + + if (target !== null && target !== undefined && target !== 0) { + // Is the original touch location inside of the current responder? + var targetInst = getInstanceFromNode(target); + + if (isAncestor(responderInst, targetInst)) { + return false; + } + } + } + + return true; +} + +var ResponderEventPlugin = { + /* For unit testing only */ + _getResponder: function() { + return responderInst; + }, + eventTypes: eventTypes, + + /** + * We must be resilient to `targetInst` being `null` on `touchMove` or + * `touchEnd`. On certain platforms, this means that a native scroll has + * assumed control and the original touch targets are destroyed. + */ + extractEvents: function( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget, + eventSystemFlags + ) { + if (isStartish(topLevelType)) { + trackedTouchCount += 1; + } else if (isEndish(topLevelType)) { + if (trackedTouchCount >= 0) { + trackedTouchCount -= 1; + } else { + { + warn( + "Ended a touch event which was not counted in `trackedTouchCount`." + ); + } + + return null; + } + } + + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent); + var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) + ? setResponderAndExtractTransfer( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) + : null; // Responder may or may not have transferred on a new touch start/move. + // Regardless, whoever is the responder after any potential transfer, we + // direct all touch start/move/ends to them in the form of + // `onResponderMove/Start/End`. These will be called for *every* additional + // finger that move/start/end, dispatched directly to whoever is the + // current responder at that moment, until the responder is "released". + // + // These multiple individual change touch events are are always bookended + // by `onResponderGrant`, and one of + // (`onResponderRelease/onResponderTerminate`). + + var isResponderTouchStart = responderInst && isStartish(topLevelType); + var isResponderTouchMove = responderInst && isMoveish(topLevelType); + var isResponderTouchEnd = responderInst && isEndish(topLevelType); + var incrementalTouch = isResponderTouchStart + ? eventTypes.responderStart + : isResponderTouchMove + ? eventTypes.responderMove + : isResponderTouchEnd + ? eventTypes.responderEnd + : null; + + if (incrementalTouch) { + var gesture = ResponderSyntheticEvent.getPooled( + incrementalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + gesture.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(gesture); + extracted = accumulate(extracted, gesture); + } + + var isResponderTerminate = + responderInst && topLevelType === TOP_TOUCH_CANCEL; + var isResponderRelease = + responderInst && + !isResponderTerminate && + isEndish(topLevelType) && + noResponderTouches(nativeEvent); + var finalTouch = isResponderTerminate + ? eventTypes.responderTerminate + : isResponderRelease + ? eventTypes.responderRelease + : null; + + if (finalTouch) { + var finalEvent = ResponderSyntheticEvent.getPooled( + finalTouch, + responderInst, + nativeEvent, + nativeEventTarget + ); + finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory; + accumulateDirectDispatches(finalEvent); + extracted = accumulate(extracted, finalEvent); + changeResponder(null); + } + + return extracted; + }, + GlobalResponderHandler: null, + injection: { + /** + * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler + * Object that handles any change in responder. Use this to inject + * integration with an existing touch handling system etc. + */ + injectGlobalResponderHandler: function(GlobalResponderHandler) { + ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler; + } + } +}; + +/** + * Injectable ordering of event plugins. + */ +var eventPluginOrder = null; +/** + * Injectable mapping from names to event plugin modules. + */ + +var namesToPlugins = {}; +/** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ + +function recomputePluginOrdering() { + if (!eventPluginOrder) { + // Wait until an `eventPluginOrder` is injected. + return; + } + + for (var pluginName in namesToPlugins) { + var pluginModule = namesToPlugins[pluginName]; + var pluginIndex = eventPluginOrder.indexOf(pluginName); + + if (!(pluginIndex > -1)) { + throw Error( + "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `" + + pluginName + + "`." + ); + } + + if (plugins[pluginIndex]) { + continue; + } + + if (!pluginModule.extractEvents) { + throw Error( + "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `" + + pluginName + + "` does not." + ); + } + + plugins[pluginIndex] = pluginModule; + var publishedEvents = pluginModule.eventTypes; + + for (var eventName in publishedEvents) { + if ( + !publishEventForPlugin( + publishedEvents[eventName], + pluginModule, + eventName + ) + ) { + throw Error( + "EventPluginRegistry: Failed to publish event `" + + eventName + + "` for plugin `" + + pluginName + + "`." + ); + } + } + } +} +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ + +function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { + if (!!eventNameDispatchConfigs.hasOwnProperty(eventName)) { + throw Error( + "EventPluginRegistry: More than one plugin attempted to publish the same event name, `" + + eventName + + "`." + ); + } + + eventNameDispatchConfigs[eventName] = dispatchConfig; + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName + ); + } + } + + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName + ); + return true; + } + + return false; +} +/** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ + +function publishRegistrationName(registrationName, pluginModule, eventName) { + if (!!registrationNameModules[registrationName]) { + throw Error( + "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `" + + registrationName + + "`." + ); + } + + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; + + { + var lowerCasedName = registrationName.toLowerCase(); + } +} +/** + * Registers plugins so that they can extract and dispatch events. */ /** @@ -2352,20 +2257,163 @@ function injectEventPluginsByName(injectedNamesToPlugins) { } } +function getListener$1(inst, registrationName) { + var stateNode = inst.stateNode; + + if (stateNode === null) { + // Work in progress (ex: onload events in incremental mode). + return null; + } + + var props = getFiberCurrentPropsFromNode(stateNode); + + if (props === null) { + // Work in progress. + return null; + } + + var listener = props[registrationName]; + + if (!(!listener || typeof listener === "function")) { + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof listener + + "` type." + ); + } + + return listener; +} + var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry - .customDirectEventTypes; + .customDirectEventTypes; // Start of inline: the below functions were inlined from +// EventPropagator.js, as they deviated from ReactDOM's newer +// implementations. + +function listenerAtPhase$1(inst, event, propagationPhase) { + var registrationName = + event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener$1(inst, registrationName); +} + +function accumulateDirectionalDispatches$1(inst, phase, event) { + { + if (!inst) { + error("Dispatching inst must not be null"); + } + } + + var listener = listenerAtPhase$1(inst, event, phase); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} + +function getParent$1(inst) { + do { + inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + + if (inst) { + return inst; + } + + return null; +} +/** + * Simulates the traversal of a two-phase, capture/bubble event dispatch. + */ + +function traverseTwoPhase$1(inst, fn, arg) { + var path = []; + + while (inst) { + path.push(inst); + inst = getParent$1(inst); + } + + var i; + + for (i = path.length; i-- > 0; ) { + fn(path[i], "captured", arg); + } + + for (i = 0; i < path.length; i++) { + fn(path[i], "bubbled", arg); + } +} + +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + traverseTwoPhase$1( + event._targetInst, + accumulateDirectionalDispatches$1, + event + ); + } +} + +function accumulateTwoPhaseDispatches$1(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle$1); +} +/** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ + +function accumulateDispatches$1(inst, ignoredDirection, event) { + if (inst && event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener$1(inst, registrationName); + + if (listener) { + event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + ); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } +} +/** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ + +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches$1(event._targetInst, null, event); + } +} + +function accumulateDirectDispatches$1(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle$1); +} // End of inline + var ReactNativeBridgeEventPlugin = { eventTypes: {}, extractEvents: function( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { if (targetInst == null) { // Probably a node belonging to another renderer's tree. @@ -2389,9 +2437,9 @@ var ReactNativeBridgeEventPlugin = { ); if (bubbleDispatchConfig) { - accumulateTwoPhaseDispatches(event); + accumulateTwoPhaseDispatches$1(event); } else if (directDispatchConfig) { - accumulateDirectDispatches(event); + accumulateDirectDispatches$1(event); } else { return null; } @@ -2462,23 +2510,16 @@ function updateFiberProps(tag, props) { instanceProps.set(tag, props); } -var PLUGIN_EVENT_SYSTEM = 1; - -var enableProfilerTimer = true; -var enableFundamentalAPI = false; -var warnAboutStringRefs = false; - +// Used as a way to call batchedUpdates when we don't have a reference to // the renderer. Such as when we're dispatching events or if third party // libraries need to call batchedUpdates. Eventually, this API will go away when // everything is batched by default. We'll then have a similar API to opt-out of // scheduled work and instead do synchronous work. // Defaults - var batchedUpdatesImpl = function(fn, bookkeeping) { return fn(bookkeeping); }; var isInsideEventHandler = false; - function batchedUpdates(fn, bookkeeping) { if (isInsideEventHandler) { // If we are currently inside another batch, we need to wait until it @@ -2636,13 +2677,7 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { } batchedUpdates(function() { - runExtractedPluginEventsInBatch( - topLevelType, - inst, - nativeEvent, - target, - PLUGIN_EVENT_SYSTEM - ); + runExtractedPluginEventsInBatch(topLevelType, inst, nativeEvent, target); }); // React Native doesn't use ReactControlledComponent but if it did, here's // where it would do it. } @@ -2658,22 +2693,21 @@ function extractPluginEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { var events = null; + var legacyPlugins = plugins; - for (var i = 0; i < plugins.length; i++) { + for (var i = 0; i < legacyPlugins.length; i++) { // Not every plugin in the ordering may be loaded at runtime. - var possiblePlugin = plugins[i]; + var possiblePlugin = legacyPlugins[i]; if (possiblePlugin) { var extractedEvents = possiblePlugin.extractEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ); if (extractedEvents) { @@ -2689,15 +2723,13 @@ function runExtractedPluginEventsInBatch( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ) { var events = extractPluginEvents( topLevelType, targetInst, nativeEvent, - nativeEventTarget, - eventSystemFlags + nativeEventTarget ); runEventsInBatch(events); } @@ -2810,37 +2842,58 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler( * If this becomes an actual Map, that will break. */ function get(key) { - return key._reactInternalFiber; + return key._reactInternals; } function set(key, value) { - key._reactInternalFiber = value; + key._reactInternals = value; } +// ATTENTION +// When adding new symbols to this file, +// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' // The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. -var hasSymbol = typeof Symbol === "function" && Symbol.for; -var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 0xeac7; -var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 0xeaca; -var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 0xeacb; -var REACT_STRICT_MODE_TYPE = hasSymbol - ? Symbol.for("react.strict_mode") - : 0xeacc; -var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 0xead2; -var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 0xeacd; -var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary -var REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 0xeacf; -var REACT_FORWARD_REF_TYPE = hasSymbol - ? Symbol.for("react.forward_ref") - : 0xead0; -var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 0xead1; -var REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 0xead8; -var REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 0xead3; -var REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 0xead4; -var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 0xead9; +var REACT_ELEMENT_TYPE = 0xeac7; +var REACT_PORTAL_TYPE = 0xeaca; +var REACT_FRAGMENT_TYPE = 0xeacb; +var REACT_STRICT_MODE_TYPE = 0xeacc; +var REACT_PROFILER_TYPE = 0xead2; +var REACT_PROVIDER_TYPE = 0xeacd; +var REACT_CONTEXT_TYPE = 0xeace; +var REACT_FORWARD_REF_TYPE = 0xead0; +var REACT_SUSPENSE_TYPE = 0xead1; +var REACT_SUSPENSE_LIST_TYPE = 0xead8; +var REACT_MEMO_TYPE = 0xead3; +var REACT_LAZY_TYPE = 0xead4; +var REACT_FUNDAMENTAL_TYPE = 0xead5; +var REACT_SCOPE_TYPE = 0xead7; +var REACT_OPAQUE_ID_TYPE = 0xeae0; +var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1; +var REACT_OFFSCREEN_TYPE = 0xeae2; +var REACT_LEGACY_HIDDEN_TYPE = 0xeae3; + +if (typeof Symbol === "function" && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + REACT_FUNDAMENTAL_TYPE = symbolFor("react.fundamental"); + REACT_SCOPE_TYPE = symbolFor("react.scope"); + REACT_OPAQUE_ID_TYPE = symbolFor("react.opaque.id"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} + var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; function getIteratorFn(maybeIterable) { @@ -2859,63 +2912,6 @@ function getIteratorFn(maybeIterable) { return null; } -// TODO: Move this to "react" once we can import from externals. -var Uninitialized = -1; -var Pending = 0; -var Resolved = 1; -var Rejected = 2; - -function refineResolvedLazyComponent(lazyComponent) { - return lazyComponent._status === Resolved ? lazyComponent._result : null; -} -function initializeLazyComponentType(lazyComponent) { - if (lazyComponent._status === Uninitialized) { - var ctor = lazyComponent._result; - - if (!ctor) { - // TODO: Remove this later. THis only exists in case you use an older "react" package. - ctor = lazyComponent._ctor; - } - - var thenable = ctor(); // Transition to the next state. - - var pending = lazyComponent; - pending._status = Pending; - pending._result = thenable; - thenable.then( - function(moduleObject) { - if (lazyComponent._status === Pending) { - var defaultExport = moduleObject.default; - - { - if (defaultExport === undefined) { - error( - "lazy: Expected the result of a dynamic import() call. " + - "Instead received: %s\n\nYour code should look like: \n " + // Break up imports to avoid accidentally parsing them as dependencies. - "const MyComponent = lazy(() => imp" + - "ort('./MyComponent'))", - moduleObject - ); - } - } // Transition to the next state. - - var resolved = lazyComponent; - resolved._status = Resolved; - resolved._result = defaultExport; - } - }, - function(error) { - if (lazyComponent._status === Pending) { - // Transition to the next state. - var rejected = lazyComponent; - rejected._status = Rejected; - rejected._result = error; - } - } - ); - } -} - function getWrappedName(outerType, innerType, wrapperName) { var functionName = innerType.displayName || innerType.name || ""; return ( @@ -2987,18 +2983,16 @@ function getComponentName(type) { case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); - case REACT_LAZY_TYPE: { - var thenable = type; - var resolvedThenable = refineResolvedLazyComponent(thenable); + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (resolvedThenable) { - return getComponentName(resolvedThenable); + try { + return getComponentName(init(payload)); + } catch (x) { + return null; } - - break; } } } @@ -3006,64 +3000,74 @@ function getComponentName(type) { return null; } +var enableProfilerTimer = true; +var enableFundamentalAPI = false; +var warnAboutStringRefs = false; +var enableNewReconciler = false; + // Don't change these two values. They're used by React Dev Tools. -var NoEffect = - /* */ +var NoFlags = + /* */ 0; var PerformedWork = - /* */ + /* */ 1; // You can change the rest (and add more). var Placement = - /* */ + /* */ 2; var Update = - /* */ + /* */ 4; var PlacementAndUpdate = - /* */ + /* */ 6; var Deletion = - /* */ + /* */ 8; var ContentReset = - /* */ + /* */ 16; var Callback = - /* */ + /* */ 32; var DidCapture = - /* */ + /* */ 64; var Ref = - /* */ + /* */ 128; var Snapshot = - /* */ + /* */ 256; var Passive = - /* */ + /* */ 512; var Hydrating = - /* */ + /* */ 1024; var HydratingAndUpdate = - /* */ - 1028; // Passive & Update & Callback & Ref & Snapshot - -var LifecycleEffectMask = - /* */ - 932; // Union of all host effects + /* */ + 1028; +var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = - /* */ - 2047; + /* */ + 4095; // These are not really side effects, but we still reuse this field. + var Incomplete = - /* */ - 2048; -var ShouldCapture = - /* */ + /* */ 4096; +var ShouldCapture = + /* */ + 8192; // TODO (effects) Remove this bit once the new reconciler is synced to the old. + +var PassiveUnmountPendingDev = + /* */ + 16384; +var ForceUpdateForLegacySuspense = + /* */ + 32768; // Static tags describe aspects of a fiber that are not specific to a render, var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { @@ -3078,7 +3082,7 @@ function getNearestMountedFiber(fiber) { do { node = nextNode; - if ((node.effectTag & (Placement | Hydrating)) !== NoEffect) { + if ((node.flags & (Placement | Hydrating)) !== NoFlags) { // This is an insertion or in-progress hydration. The nearest possible // mounted fiber is the parent but we need to continue to figure out // if that one is still mounted. @@ -3338,6 +3342,20 @@ function findCurrentHostFiber(parent) { return null; } +function doesFiberContain(parentFiber, childFiber) { + var node = childFiber; + var parentFiberAlternate = parentFiber.alternate; + + while (node !== null) { + if (node === parentFiber || node === parentFiberAlternate) { + return true; + } + + node = node.return; + } + + return false; +} // Modules provided by RN: var emptyObject = {}; @@ -3844,104 +3862,102 @@ function warnForStyleProps(props, validAttributes) { } } -var ReactNativeFiberHostComponent = - /*#__PURE__*/ - (function() { - function ReactNativeFiberHostComponent( - tag, - viewConfig, - internalInstanceHandleDEV - ) { - this._nativeTag = tag; - this._children = []; - this.viewConfig = viewConfig; +var ReactNativeFiberHostComponent = /*#__PURE__*/ (function() { + function ReactNativeFiberHostComponent( + tag, + viewConfig, + internalInstanceHandleDEV + ) { + this._nativeTag = tag; + this._children = []; + this.viewConfig = viewConfig; - { - this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; - } + { + this._internalFiberInstanceHandleDEV = internalInstanceHandleDEV; } + } - var _proto = ReactNativeFiberHostComponent.prototype; - - _proto.blur = function blur() { - ReactNativePrivateInterface.TextInputState.blurTextInput(this); - }; - - _proto.focus = function focus() { - ReactNativePrivateInterface.TextInputState.focusTextInput(this); - }; - - _proto.measure = function measure(callback) { - ReactNativePrivateInterface.UIManager.measure( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + var _proto = ReactNativeFiberHostComponent.prototype; - _proto.measureInWindow = function measureInWindow(callback) { - ReactNativePrivateInterface.UIManager.measureInWindow( - this._nativeTag, - mountSafeCallback_NOT_REALLY_SAFE(this, callback) - ); - }; + _proto.blur = function blur() { + ReactNativePrivateInterface.TextInputState.blurTextInput(this); + }; - _proto.measureLayout = function measureLayout( - relativeToNativeNode, - onSuccess, - onFail - ) /* currently unused */ - { - var relativeNode; + _proto.focus = function focus() { + ReactNativePrivateInterface.TextInputState.focusTextInput(this); + }; - if (typeof relativeToNativeNode === "number") { - // Already a node handle - relativeNode = relativeToNativeNode; - } else { - var nativeNode = relativeToNativeNode; + _proto.measure = function measure(callback) { + ReactNativePrivateInterface.UIManager.measure( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - if (nativeNode._nativeTag) { - relativeNode = nativeNode._nativeTag; - } - } + _proto.measureInWindow = function measureInWindow(callback) { + ReactNativePrivateInterface.UIManager.measureInWindow( + this._nativeTag, + mountSafeCallback_NOT_REALLY_SAFE(this, callback) + ); + }; - if (relativeNode == null) { - { - error( - "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." - ); - } + _proto.measureLayout = function measureLayout( + relativeToNativeNode, + onSuccess, + onFail + ) /* currently unused */ + { + var relativeNode; - return; - } + if (typeof relativeToNativeNode === "number") { + // Already a node handle + relativeNode = relativeToNativeNode; + } else { + var nativeNode = relativeToNativeNode; - ReactNativePrivateInterface.UIManager.measureLayout( - this._nativeTag, - relativeNode, - mountSafeCallback_NOT_REALLY_SAFE(this, onFail), - mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) - ); - }; + if (nativeNode._nativeTag) { + relativeNode = nativeNode._nativeTag; + } + } - _proto.setNativeProps = function setNativeProps(nativeProps) { + if (relativeNode == null) { { - warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + error( + "Warning: ref.measureLayout must be called with a node handle or a ref to a native component." + ); } - var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. - // This is an expensive no-op for Android, and causes an unnecessary - // view invalidation for certain components (eg RCTTextInput) on iOS. + return; + } - if (updatePayload != null) { - ReactNativePrivateInterface.UIManager.updateView( - this._nativeTag, - this.viewConfig.uiViewClassName, - updatePayload - ); - } - }; + ReactNativePrivateInterface.UIManager.measureLayout( + this._nativeTag, + relativeNode, + mountSafeCallback_NOT_REALLY_SAFE(this, onFail), + mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess) + ); + }; - return ReactNativeFiberHostComponent; - })(); // eslint-disable-next-line no-unused-expressions + _proto.setNativeProps = function setNativeProps(nativeProps) { + { + warnForStyleProps(nativeProps, this.viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, this.viewConfig.validAttributes); // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + + if (updatePayload != null) { + ReactNativePrivateInterface.UIManager.updateView( + this._nativeTag, + this.viewConfig.uiViewClassName, + updatePayload + ); + } + }; + + return ReactNativeFiberHostComponent; +})(); // eslint-disable-next-line no-unused-expressions // can re-export everything from this module. @@ -4104,6 +4120,7 @@ function getPublicInstance(instance) { } function prepareForCommit(containerInfo) { // Noop + return null; } function prepareUpdate( instance, @@ -4121,9 +4138,6 @@ function resetAfterCommit(containerInfo) { var scheduleTimeout = setTimeout; var cancelTimeout = clearTimeout; var noTimeout = -1; -function shouldDeprioritizeSubtree(type, props) { - return false; -} function shouldSetTextContent(type, props) { // TODO (bvaughn) Revisit this decision. // Always returning false simplifies the createInstance() implementation, @@ -4306,525 +4320,239 @@ function unhideInstance(instance, props) { updatePayload ); } +function clearContainer(container) { + // TODO Implement this for React Native + // UIManager does not expose a "remove all" type method. +} function unhideTextInstance(textInstance, text) { throw new Error("Not yet implemented."); } +function makeClientIdInDEV(warnOnAccessInDEV) { + throw new Error("Not yet implemented"); +} +function preparePortalMount(portalInstance) { + // noop +} -var loggedTypeFailures = {}; -function checkPropTypes(typeSpecs, values, location, componentName) { +var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; +function describeBuiltInComponentFrame(name, source, ownerFn) { { - // $FlowFixMe This is okay but Flow doesn't know it. - var has = Function.call.bind(Object.prototype.hasOwnProperty); - - for (var typeSpecName in typeSpecs) { - if (has(typeSpecs, typeSpecName)) { - var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - - try { - // This is intentionally an invariant that gets caught. It's the same - // behavior as without this statement except with a better message. - if (typeof typeSpecs[typeSpecName] !== "function") { - var err = Error( - (componentName || "React class") + - ": " + - location + - " type `" + - typeSpecName + - "` is invalid; " + - "it must be a function, usually from the `prop-types` package, but received `" + - typeof typeSpecs[typeSpecName] + - "`." + - "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." - ); - err.name = "Invariant Violation"; - throw err; - } - - error$1 = typeSpecs[typeSpecName]( - values, - typeSpecName, - componentName, - location, - null, - "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" - ); - } catch (ex) { - error$1 = ex; - } - - if (error$1 && !(error$1 instanceof Error)) { - error( - "%s: type specification of %s" + - " `%s` is invalid; the type checker " + - "function must return `null` or an `Error` but returned a %s. " + - "You may have forgotten to pass an argument to the type checker " + - "creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and " + - "shape all require an argument).", - componentName || "React class", - location, - typeSpecName, - typeof error$1 - ); - } - - if ( - error$1 instanceof Error && - !(error$1.message in loggedTypeFailures) - ) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error$1.message] = true; + var ownerName = null; - error("Failed %s type: %s", location, error$1.message); - } - } + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } - } -} - -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -var reactEmoji = "\u269B"; -var warningEmoji = "\u26D4"; -var supportsUserTiming = - typeof performance !== "undefined" && - typeof performance.mark === "function" && - typeof performance.clearMarks === "function" && - typeof performance.measure === "function" && - typeof performance.clearMeasures === "function"; // Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? - -var currentFiber = null; // If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). - -var currentPhase = null; -var currentPhaseFiber = null; // Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. - -var isCommitting = false; -var hasScheduledUpdateInCurrentCommit = false; -var hasScheduledUpdateInCurrentPhase = false; -var commitCountInCurrentWorkLoop = 0; -var effectCountInCurrentCommit = 0; -// to avoid stretch the commit phase with measurement overhead. - -var labelsInCurrentCommit = new Set(); - -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; - -var formatLabel = function(label, warning) { - var prefix = warning ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning ? " Warning: " + warning : ""; - return "" + prefix + label + suffix; -}; - -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; - -var clearMark = function(markName) { - performance.clearMarks(formatMarkName(markName)); -}; - -var endMark = function(label, markName, warning) { - var formattedMarkName = formatMarkName(markName); - var formattedLabel = formatLabel(label, warning); - - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. - // Clear marks immediately to avoid growing buffer. - - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; - -var getFiberMarkName = function(label, debugID) { - return label + " (#" + debugID + ")"; -}; - -var getFiberLabel = function(componentName, isMounted, phase) { - if (phase === null) { - // These are composite component total time measurements. - return componentName + " [" + (isMounted ? "update" : "mount") + "]"; - } else { - // Composite component methods. - return componentName + "." + phase; - } -}; - -var beginFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. - return false; + return describeComponentFrame(name, source, ownerName); } +} +var componentFrameCache; - labelsInCurrentCommit.add(label); - var markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; - -var clearFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; - -var endFiberMark = function(fiber, phase, warning) { - var componentName = getComponentName(fiber.type) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning); -}; - -var shouldIgnoreFiber = function(fiber) { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case Fragment: - case ContextProvider: - case ContextConsumer: - case Mode: - return true; +{ + var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); +} +var BEFORE_SLASH_RE = /^(.*)[\\\/]/; - default: - return false; - } -}; +function describeComponentFrame(name, source, ownerName) { + var sourceInfo = ""; -var clearPendingPhaseMeasurement = function() { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); - } + if (source) { + var path = source.fileName; + var fileName = path.replace(BEFORE_SLASH_RE, ""); // In DEV, include code for a common special case: + // prefer "folder/index.js" instead of just "index.js". - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; + if (/^index\./.test(fileName)) { + var match = path.match(BEFORE_SLASH_RE); -var pauseTimers = function() { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - var fiber = currentFiber; + if (match) { + var pathBeforeSlash = match[1]; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); + if (pathBeforeSlash) { + var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); + fileName = folderName + "/" + fileName; + } + } } - fiber = fiber.return; - } -}; - -var resumeTimersRecursively = function(fiber) { - if (fiber.return !== null) { - resumeTimersRecursively(fiber.return); - } - - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); + sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; + } else if (ownerName) { + sourceInfo = " (created by " + ownerName + ")"; } -}; -var resumeTimers = function() { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; + return "\n in " + (name || "Unknown") + sourceInfo; +} -function recordEffect() { +function describeClassComponentFrame(ctor, source, ownerFn) { { - effectCountInCurrentCommit++; + return describeFunctionComponentFrame(ctor, source, ownerFn); } } -function recordScheduleUpdate() { +function describeFunctionComponentFrame(fn, source, ownerFn) { { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; + if (!fn) { + return ""; } - } -} -function startWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, this is the fiber to unwind from. - currentFiber = fiber; + var name = fn.displayName || fn.name || null; + var ownerName = null; - if (!beginFiberMark(fiber, null)) { - return; + if (ownerFn) { + ownerName = ownerFn.displayName || ownerFn.name || null; } - fiber._debugIsCurrentlyTiming = true; - } -} -function cancelWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); + return describeComponentFrame(name, source, ownerName); } } -function stopWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, its parent is the fiber to unwind from. - - currentFiber = fiber.return; - - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); +function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + if (type == null) { + return ""; } -} -function stopFailedWorkTimer(fiber) { - { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber.return; - - if (!fiber._debugIsCurrentlyTiming) { - return; + if (typeof type === "function") { + { + return describeFunctionComponentFrame(type, source, ownerFn); } - - fiber._debugIsCurrentlyTiming = false; - var warning = - fiber.tag === SuspenseComponent - ? "Rendering was suspended" - : "An error was thrown inside this error boundary"; - endFiberMark(fiber, null, warning); } -} -function startPhaseTimer(fiber, phase) { - { - if (!supportsUserTiming) { - return; - } - - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - - currentPhaseFiber = fiber; - currentPhase = phase; + if (typeof type === "string") { + return describeBuiltInComponentFrame(type, source, ownerFn); } -} -function stopPhaseTimer() { - { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - var warning = hasScheduledUpdateInCurrentPhase - ? "Scheduled a cascading update" - : null; - endFiberMark(currentPhaseFiber, currentPhase, warning); - } + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame("Suspense", source, ownerFn); - currentPhase = null; - currentPhaseFiber = null; + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame("SuspenseList", source, ownerFn); } -} -function startWorkLoopTimer(nextUnitOfWork) { - { - currentFiber = nextUnitOfWork; - - if (!supportsUserTiming) { - return; - } - commitCountInCurrentWorkLoop = 0; // This is top level call. - // Any other measurements are performed within. - - beginMark("(React Tree Reconciliation)"); // Resume any measurements that were in progress during the last loop. + if (typeof type === "object") { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render, source, ownerFn); - resumeTimers(); - } -} -function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { - { - if (!supportsUserTiming) { - return; - } + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); - var warning = null; + case REACT_LAZY_TYPE: { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning = "A top-level update interrupted the previous render"; - } else { - var componentName = getComponentName(interruptedBy.type) || "Unknown"; - warning = - "An update to " + componentName + " interrupted the previous render"; + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV( + init(payload), + source, + ownerFn + ); + } catch (x) {} } - } else if (commitCountInCurrentWorkLoop > 1) { - warning = "There were cascading updates"; } - - commitCountInCurrentWorkLoop = 0; - var label = didCompleteRoot - ? "(React Tree Reconciliation: Completed Root)" - : "(React Tree Reconciliation: Yielded)"; // Pause any measurements until the next loop. - - pauseTimers(); - endMark(label, "(React Tree Reconciliation)", warning); } + + return ""; } -function startCommitTimer() { + +var loggedTypeFailures = {}; +var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + +function setCurrentlyValidatingElement(element) { { - if (!supportsUserTiming) { - return; + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV( + element.type, + element._source, + owner ? owner.type : null + ); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); } - - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark("(Committing Changes)"); } } -function stopCommitTimer() { + +function checkPropTypes(typeSpecs, values, location, componentName, element) { { - if (!supportsUserTiming) { - return; - } + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(Object.prototype.hasOwnProperty); - var warning = null; + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. - if (hasScheduledUpdateInCurrentCommit) { - warning = "Lifecycle hook scheduled a cascading update"; - } else if (commitCountInCurrentWorkLoop > 0) { - warning = "Caused by a cascading update in earlier commit"; - } + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== "function") { + var err = Error( + (componentName || "React class") + + ": " + + location + + " type `" + + typeSpecName + + "` is invalid; " + + "it must be a function, usually from the `prop-types` package, but received `" + + typeof typeSpecs[typeSpecName] + + "`." + + "This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`." + ); + err.name = "Invariant Violation"; + throw err; + } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); - endMark("(Committing Changes)", "(Committing Changes)", warning); - } -} -function startCommitSnapshotEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + error$1 = typeSpecs[typeSpecName]( + values, + typeSpecName, + componentName, + location, + null, + "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED" + ); + } catch (ex) { + error$1 = ex; + } - effectCountInCurrentCommit = 0; - beginMark("(Committing Snapshot Effects)"); - } -} -function stopCommitSnapshotEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Snapshot Effects: " + count + " Total)", - "(Committing Snapshot Effects)", - null - ); - } -} -function startCommitHostEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + error( + "%s: type specification of %s" + + " `%s` is invalid; the type checker " + + "function must return `null` or an `Error` but returned a %s. " + + "You may have forgotten to pass an argument to the type checker " + + "creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and " + + "shape all require an argument).", + componentName || "React class", + location, + typeSpecName, + typeof error$1 + ); - effectCountInCurrentCommit = 0; - beginMark("(Committing Host Effects)"); - } -} -function stopCommitHostEffectsTimer() { - { - if (!supportsUserTiming) { - return; - } + setCurrentlyValidatingElement(null); + } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Host Effects: " + count + " Total)", - "(Committing Host Effects)", - null - ); - } -} -function startCommitLifeCyclesTimer() { - { - if (!supportsUserTiming) { - return; - } + if ( + error$1 instanceof Error && + !(error$1.message in loggedTypeFailures) + ) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); - effectCountInCurrentCommit = 0; - beginMark("(Calling Lifecycle Methods)"); - } -} -function stopCommitLifeCyclesTimer() { - { - if (!supportsUserTiming) { - return; - } + error("Failed %s type: %s", location, error$1.message); - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Calling Lifecycle Methods: " + count + " Total)", - "(Calling Lifecycle Methods)", - null - ); + setCurrentlyValidatingElement(null); + } + } + } } } @@ -5031,10 +4759,7 @@ function processChildContext(fiber, type, parentContext) { return parentContext; } - var childContext; - startPhaseTimer(fiber, "getChildContext"); - childContext = instance.getChildContext(); - stopPhaseTimer(); + var childContext = instance.getChildContext(); for (var contextKey in childContext) { if (!(contextKey in childContextTypes)) { @@ -5052,7 +4777,7 @@ function processChildContext(fiber, type, parentContext) { checkPropTypes(childContextTypes, childContext, "child context", name); } - return Object.assign({}, parentContext, {}, childContext); + return Object.assign({}, parentContext, childContext); } } @@ -5155,20 +4880,112 @@ var LegacyRoot = 0; var BlockingRoot = 1; var ConcurrentRoot = 2; +var rendererID = null; +var injectedHook = null; +var hasLoggedError = false; +var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } + + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + + if (!hook.supportsFiber) { + { + error( + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://reactjs.org/link/react-devtools" + ); + } // DevTools exists, even though it doesn't support Fiber. + + return true; + } + + try { + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + + injectedHook = hook; + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + error("React instrumentation encountered an error: %s.", err); + } + } // DevTools exists + + return true; +} +function onScheduleRoot(root, children) { + { + if ( + injectedHook && + typeof injectedHook.onScheduleFiberRoot === "function" + ) { + try { + injectedHook.onScheduleFiberRoot(rendererID, root, children); + } catch (err) { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} +function onCommitRoot(root, priorityLevel) { + if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") { + try { + var didError = (root.current.flags & DidCapture) === DidCapture; + + if (enableProfilerTimer) { + injectedHook.onCommitFiberRoot( + rendererID, + root, + priorityLevel, + didError + ); + } else { + injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); + } + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} +function onCommitUnmount(fiber) { + if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") { + try { + injectedHook.onCommitFiberUnmount(rendererID, fiber); + } catch (err) { + { + if (!hasLoggedError) { + hasLoggedError = true; + + error("React instrumentation encountered an error: %s", err); + } + } + } + } +} + // Intentionally not named imports because Rollup would use dynamic dispatch for -var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, - Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, - Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, - Scheduler_shouldYield = Scheduler.unstable_shouldYield, - Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, - Scheduler_getCurrentPriorityLevel = - Scheduler.unstable_getCurrentPriorityLevel, - Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, - Scheduler_UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, - Scheduler_NormalPriority = Scheduler.unstable_NormalPriority, - Scheduler_LowPriority = Scheduler.unstable_LowPriority, - Scheduler_IdlePriority = Scheduler.unstable_IdlePriority; +var Scheduler_now = Scheduler.unstable_now; { // Provide explicit error message when production+profiling bundle of e.g. @@ -5181,12 +4998,10 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, ) ) { throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); } } - -var fakeCallbackNode = {}; // Except for NoPriority, these correspond to Scheduler priorities. We use // ascending numbers so we can compare them like numbers. They start at 90 to // avoid clashing with Scheduler's priorities. @@ -5197,1214 +5012,1434 @@ var LowPriority = 96; var IdlePriority = 95; // NoPriority is the absence of priority. Also React-only. var NoPriority = 90; -var shouldYield = Scheduler_shouldYield; -var requestPaint = // Fall back gracefully if we're running an older version of Scheduler. - Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : function() {}; -var syncQueue = null; -var immediateQueueCallbackNode = null; -var isFlushingSyncQueue = false; var initialTimeMs = Scheduler_now(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. -// This will be the case for modern browsers that support `performance.now`. In -// older browsers, Scheduler falls back to `Date.now`, which returns a Unix -// timestamp. In that case, subtract the module initialization time to simulate -// the behavior of performance.now and keep our times small enough to fit -// within 32 bits. -// TODO: Consider lifting this into Scheduler. - -var now = - initialTimeMs < 10000 - ? Scheduler_now - : function() { - return Scheduler_now() - initialTimeMs; - }; -function getCurrentPriorityLevel() { - switch (Scheduler_getCurrentPriorityLevel()) { - case Scheduler_ImmediatePriority: - return ImmediatePriority; - - case Scheduler_UserBlockingPriority: - return UserBlockingPriority; - - case Scheduler_NormalPriority: - return NormalPriority; - - case Scheduler_LowPriority: - return LowPriority; - - case Scheduler_IdlePriority: - return IdlePriority; - - default: { - throw Error("Unknown priority level."); - } - } -} - -function reactPriorityToSchedulerPriority(reactPriorityLevel) { - switch (reactPriorityLevel) { - case ImmediatePriority: - return Scheduler_ImmediatePriority; - case UserBlockingPriority: - return Scheduler_UserBlockingPriority; +var SyncLanePriority = 15; +var SyncBatchedLanePriority = 14; +var InputDiscreteHydrationLanePriority = 13; +var InputDiscreteLanePriority = 12; +var InputContinuousHydrationLanePriority = 11; +var InputContinuousLanePriority = 10; +var DefaultHydrationLanePriority = 9; +var DefaultLanePriority = 8; +var TransitionHydrationPriority = 7; +var TransitionPriority = 6; +var RetryLanePriority = 5; +var SelectiveHydrationLanePriority = 4; +var IdleHydrationLanePriority = 3; +var IdleLanePriority = 2; +var OffscreenLanePriority = 1; +var NoLanePriority = 0; +var TotalLanes = 31; +var NoLanes = + /* */ + 0; +var NoLane = + /* */ + 0; +var SyncLane = + /* */ + 1; +var SyncBatchedLane = + /* */ + 2; +var InputDiscreteHydrationLane = + /* */ + 4; +var InputDiscreteLanes = + /* */ + 24; +var InputContinuousHydrationLane = + /* */ + 32; +var InputContinuousLanes = + /* */ + 192; +var DefaultHydrationLane = + /* */ + 256; +var DefaultLanes = + /* */ + 3584; +var TransitionHydrationLane = + /* */ + 4096; +var TransitionLanes = + /* */ + 4186112; +var RetryLanes = + /* */ + 62914560; +var SomeRetryLane = + /* */ + 33554432; +var SelectiveHydrationLane = + /* */ + 67108864; +var NonIdleLanes = + /* */ + 134217727; +var IdleHydrationLane = + /* */ + 134217728; +var IdleLanes = + /* */ + 805306368; +var OffscreenLane = + /* */ + 1073741824; +var NoTimestamp = -1; +// Used by getHighestPriorityLanes and getNextLanes: - case NormalPriority: - return Scheduler_NormalPriority; +var return_highestLanePriority = DefaultLanePriority; - case LowPriority: - return Scheduler_LowPriority; +function getHighestPriorityLanes(lanes) { + if ((SyncLane & lanes) !== NoLanes) { + return_highestLanePriority = SyncLanePriority; + return SyncLane; + } - case IdlePriority: - return Scheduler_IdlePriority; + if ((SyncBatchedLane & lanes) !== NoLanes) { + return_highestLanePriority = SyncBatchedLanePriority; + return SyncBatchedLane; + } - default: { - throw Error("Unknown priority level."); - } + if ((InputDiscreteHydrationLane & lanes) !== NoLanes) { + return_highestLanePriority = InputDiscreteHydrationLanePriority; + return InputDiscreteHydrationLane; } -} -function runWithPriority(reactPriorityLevel, fn) { - var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_runWithPriority(priorityLevel, fn); -} -function scheduleCallback(reactPriorityLevel, callback, options) { - var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); - return Scheduler_scheduleCallback(priorityLevel, callback, options); -} -function scheduleSyncCallback(callback) { - // Push this callback into an internal queue. We'll flush these either in - // the next tick, or earlier if something calls `flushSyncCallbackQueue`. - if (syncQueue === null) { - syncQueue = [callback]; // Flush the queue in the next tick, at the earliest. + var inputDiscreteLanes = InputDiscreteLanes & lanes; - immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ); - } else { - // Push onto existing queue. Don't need to schedule a callback because - // we already scheduled one when we created the queue. - syncQueue.push(callback); + if (inputDiscreteLanes !== NoLanes) { + return_highestLanePriority = InputDiscreteLanePriority; + return inputDiscreteLanes; } - return fakeCallbackNode; -} -function cancelCallback(callbackNode) { - if (callbackNode !== fakeCallbackNode) { - Scheduler_cancelCallback(callbackNode); - } -} -function flushSyncCallbackQueue() { - if (immediateQueueCallbackNode !== null) { - var node = immediateQueueCallbackNode; - immediateQueueCallbackNode = null; - Scheduler_cancelCallback(node); + if ((lanes & InputContinuousHydrationLane) !== NoLanes) { + return_highestLanePriority = InputContinuousHydrationLanePriority; + return InputContinuousHydrationLane; } - flushSyncCallbackQueueImpl(); -} - -function flushSyncCallbackQueueImpl() { - if (!isFlushingSyncQueue && syncQueue !== null) { - // Prevent re-entrancy. - isFlushingSyncQueue = true; - var i = 0; - - try { - var _isSync = true; - var queue = syncQueue; - runWithPriority(ImmediatePriority, function() { - for (; i < queue.length; i++) { - var callback = queue[i]; + var inputContinuousLanes = InputContinuousLanes & lanes; - do { - callback = callback(_isSync); - } while (callback !== null); - } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); - } // Resume flushing in the next tick - - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue - ); - throw error; - } finally { - isFlushingSyncQueue = false; - } + if (inputContinuousLanes !== NoLanes) { + return_highestLanePriority = InputContinuousLanePriority; + return inputContinuousLanes; } -} -var NoMode = 0; -var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root -// tag instead + if ((lanes & DefaultHydrationLane) !== NoLanes) { + return_highestLanePriority = DefaultHydrationLanePriority; + return DefaultHydrationLane; + } -var BlockingMode = 2; -var ConcurrentMode = 4; -var ProfileMode = 8; + var defaultLanes = DefaultLanes & lanes; -// Max 31 bit integer. The max integer size in V8 for 32-bit systems. -// Math.pow(2, 30) - 1 -// 0b111111111111111111111111111111 -var MAX_SIGNED_31_BIT_INT = 1073741823; + if (defaultLanes !== NoLanes) { + return_highestLanePriority = DefaultLanePriority; + return defaultLanes; + } -var NoWork = 0; // TODO: Think of a better name for Never. The key difference with Idle is that -// Never work can be committed in an inconsistent state without tearing the UI. -// The main example is offscreen content, like a hidden subtree. So one possible -// name is Offscreen. However, it also includes dehydrated Suspense boundaries, -// which are inconsistent in the sense that they haven't finished yet, but -// aren't visibly inconsistent because the server rendered HTML matches what the -// hydrated tree would look like. + if ((lanes & TransitionHydrationLane) !== NoLanes) { + return_highestLanePriority = TransitionHydrationPriority; + return TransitionHydrationLane; + } -var Never = 1; // Idle is slightly higher priority than Never. It must completely finish in -// order to be consistent. + var transitionLanes = TransitionLanes & lanes; -var Idle = 2; // Continuous Hydration is slightly higher than Idle and is used to increase -var Sync = MAX_SIGNED_31_BIT_INT; -var Batched = Sync - 1; -var UNIT_SIZE = 10; -var MAGIC_NUMBER_OFFSET = Batched - 1; // 1 unit of expiration time represents 10ms. + if (transitionLanes !== NoLanes) { + return_highestLanePriority = TransitionPriority; + return transitionLanes; + } -function msToExpirationTime(ms) { - // Always subtract from the offset so that we don't clash with the magic number for NoWork. - return MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0); -} -function expirationTimeToMs(expirationTime) { - return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE; -} + var retryLanes = RetryLanes & lanes; -function ceiling(num, precision) { - return (((num / precision) | 0) + 1) * precision; -} + if (retryLanes !== NoLanes) { + return_highestLanePriority = RetryLanePriority; + return retryLanes; + } -function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { - return ( - MAGIC_NUMBER_OFFSET - - ceiling( - MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE, - bucketSizeMs / UNIT_SIZE - ) - ); -} // TODO: This corresponds to Scheduler's NormalPriority, not LowPriority. Update -// the names to reflect. - -var LOW_PRIORITY_EXPIRATION = 5000; -var LOW_PRIORITY_BATCH_SIZE = 250; -function computeAsyncExpiration(currentTime) { - return computeExpirationBucket( - currentTime, - LOW_PRIORITY_EXPIRATION, - LOW_PRIORITY_BATCH_SIZE - ); -} -function computeSuspenseExpiration(currentTime, timeoutMs) { - // TODO: Should we warn if timeoutMs is lower than the normal pri expiration time? - return computeExpirationBucket( - currentTime, - timeoutMs, - LOW_PRIORITY_BATCH_SIZE - ); -} // We intentionally set a higher expiration time for interactive updates in -// dev than in production. -// -// If the main thread is being blocked so long that you hit the expiration, -// it's a problem that could be solved with better scheduling. -// -// People will be more likely to notice this and fix it with the long -// expiration time in development. -// -// In production we opt for better UX at the risk of masking scheduling -// problems, by expiring fast. - -var HIGH_PRIORITY_EXPIRATION = 500; -var HIGH_PRIORITY_BATCH_SIZE = 100; -function computeInteractiveExpiration(currentTime) { - return computeExpirationBucket( - currentTime, - HIGH_PRIORITY_EXPIRATION, - HIGH_PRIORITY_BATCH_SIZE - ); -} -function inferPriorityFromExpirationTime(currentTime, expirationTime) { - if (expirationTime === Sync) { - return ImmediatePriority; + if (lanes & SelectiveHydrationLane) { + return_highestLanePriority = SelectiveHydrationLanePriority; + return SelectiveHydrationLane; } - if (expirationTime === Never || expirationTime === Idle) { - return IdlePriority; + if ((lanes & IdleHydrationLane) !== NoLanes) { + return_highestLanePriority = IdleHydrationLanePriority; + return IdleHydrationLane; } - var msUntil = - expirationTimeToMs(expirationTime) - expirationTimeToMs(currentTime); + var idleLanes = IdleLanes & lanes; - if (msUntil <= 0) { - return ImmediatePriority; + if (idleLanes !== NoLanes) { + return_highestLanePriority = IdleLanePriority; + return idleLanes; } - if (msUntil <= HIGH_PRIORITY_EXPIRATION + HIGH_PRIORITY_BATCH_SIZE) { - return UserBlockingPriority; + if ((OffscreenLane & lanes) !== NoLanes) { + return_highestLanePriority = OffscreenLanePriority; + return OffscreenLane; } - if (msUntil <= LOW_PRIORITY_EXPIRATION + LOW_PRIORITY_BATCH_SIZE) { - return NormalPriority; - } // TODO: Handle LowPriority - // Assume anything lower has idle priority + { + error("Should have found matching lanes. This is a bug in React."); + } // This shouldn't be reachable, but as a fallback, return the entire bitmask. - return IdlePriority; + return_highestLanePriority = DefaultLanePriority; + return lanes; } -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - return ( - (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare - ); -} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case ImmediatePriority: + return SyncLanePriority; -var objectIs = typeof Object.is === "function" ? Object.is : is; + case UserBlockingPriority: + return InputContinuousLanePriority; -var hasOwnProperty = Object.prototype.hasOwnProperty; -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ + case NormalPriority: + case LowPriority: + // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration. + return DefaultLanePriority; -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) { - return true; - } + case IdlePriority: + return IdleLanePriority; - if ( - typeof objA !== "object" || - objA === null || - typeof objB !== "object" || - objB === null - ) { - return false; + default: + return NoLanePriority; } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case SyncLanePriority: + case SyncBatchedLanePriority: + return ImmediatePriority; - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); + case InputDiscreteHydrationLanePriority: + case InputDiscreteLanePriority: + case InputContinuousHydrationLanePriority: + case InputContinuousLanePriority: + return UserBlockingPriority; - if (keysA.length !== keysB.length) { - return false; - } // Test for A's keys different from B. + case DefaultHydrationLanePriority: + case DefaultLanePriority: + case TransitionHydrationPriority: + case TransitionPriority: + case SelectiveHydrationLanePriority: + case RetryLanePriority: + return NormalPriority; - for (var i = 0; i < keysA.length; i++) { - if ( - !hasOwnProperty.call(objB, keysA[i]) || - !objectIs(objA[keysA[i]], objB[keysA[i]]) - ) { - return false; + case IdleHydrationLanePriority: + case IdleLanePriority: + case OffscreenLanePriority: + return IdlePriority; + + case NoLanePriority: + return NoPriority; + + default: { + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); } } - - return true; } +function getNextLanes(root, wipLanes) { + // Early bailout if there's no pending work left. + var pendingLanes = root.pendingLanes; -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; -function describeComponentFrame(name, source, ownerName) { - var sourceInfo = ""; + if (pendingLanes === NoLanes) { + return_highestLanePriority = NoLanePriority; + return NoLanes; + } - if (source) { - var path = source.fileName; - var fileName = path.replace(BEFORE_SLASH_RE, ""); + var nextLanes = NoLanes; + var nextLanePriority = NoLanePriority; + var expiredLanes = root.expiredLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; // Check if any work has expired. - { - // In DEV, include code for a common special case: - // prefer "folder/index.js" instead of just "index.js". - if (/^index\./.test(fileName)) { - var match = path.match(BEFORE_SLASH_RE); + if (expiredLanes !== NoLanes) { + nextLanes = expiredLanes; + nextLanePriority = return_highestLanePriority = SyncLanePriority; + } else { + // Do not work on any idle work until all the non-idle work has finished, + // even if the work is suspended. + var nonIdlePendingLanes = pendingLanes & NonIdleLanes; - if (match) { - var pathBeforeSlash = match[1]; + if (nonIdlePendingLanes !== NoLanes) { + var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; - if (pathBeforeSlash) { - var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ""); - fileName = folderName + "/" + fileName; - } + if (nonIdleUnblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); + nextLanePriority = return_highestLanePriority; + } else { + var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; + + if (nonIdlePingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); + nextLanePriority = return_highestLanePriority; } } - } + } else { + // The only remaining work is Idle. + var unblockedLanes = pendingLanes & ~suspendedLanes; - sourceInfo = " (at " + fileName + ":" + source.lineNumber + ")"; - } else if (ownerName) { - sourceInfo = " (created by " + ownerName + ")"; + if (unblockedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(unblockedLanes); + nextLanePriority = return_highestLanePriority; + } else { + if (pingedLanes !== NoLanes) { + nextLanes = getHighestPriorityLanes(pingedLanes); + nextLanePriority = return_highestLanePriority; + } + } + } } - return "\n in " + (name || "Unknown") + sourceInfo; -} + if (nextLanes === NoLanes) { + // This should only be reachable if we're suspended + // TODO: Consider warning in this path if a fallback timer is not scheduled. + return NoLanes; + } // If there are higher priority lanes, we'll include them even if they + // are suspended. -var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + nextLanes = pendingLanes & getEqualOrHigherPriorityLanes(nextLanes); // If we're already in the middle of a render, switching lanes will interrupt + // it and we'll lose our progress. We should only do this if the new lanes are + // higher priority. -function describeFiber(fiber) { - switch (fiber.tag) { - case HostRoot: - case HostPortal: - case HostText: - case Fragment: - case ContextProvider: - case ContextConsumer: - return ""; + if ( + wipLanes !== NoLanes && + wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't + // bother waiting until the root is complete. + (wipLanes & suspendedLanes) === NoLanes + ) { + getHighestPriorityLanes(wipLanes); + var wipLanePriority = return_highestLanePriority; - default: - var owner = fiber._debugOwner; - var source = fiber._debugSource; - var name = getComponentName(fiber.type); - var ownerName = null; + if (nextLanePriority <= wipLanePriority) { + return wipLanes; + } else { + return_highestLanePriority = nextLanePriority; + } + } // Check for entangled lanes and add them to the batch. + // + // A lane is said to be entangled with another when it's not allowed to render + // in a batch that does not also include the other lane. Typically we do this + // when multiple updates have the same source, and we only want to respond to + // the most recent event from that source. + // + // Note that we apply entanglements *after* checking for partial work above. + // This means that if a lane is entangled during an interleaved event while + // it's already rendering, we won't interrupt it. This is intentional, since + // entanglement is usually "best effort": we'll try our best to render the + // lanes in the same batch, but it's not worth throwing out partially + // completed work in order to do it. + // + // For those exceptions where entanglement is semantically important, like + // useMutableSource, we should ensure that there is no partial work at the + // time we apply the entanglement. - if (owner) { - ownerName = getComponentName(owner.type); - } + var entangledLanes = root.entangledLanes; - return describeComponentFrame(name, source, ownerName); + if (entangledLanes !== NoLanes) { + var entanglements = root.entanglements; + var lanes = nextLanes & entangledLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + nextLanes |= entanglements[index]; + lanes &= ~lane; + } } + + return nextLanes; } +function getMostRecentEventTime(root, lanes) { + var eventTimes = root.eventTimes; + var mostRecentEventTime = NoTimestamp; -function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - var node = workInProgress; + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var eventTime = eventTimes[index]; - do { - info += describeFiber(node); - node = node.return; - } while (node); + if (eventTime > mostRecentEventTime) { + mostRecentEventTime = eventTime; + } + + lanes &= ~lane; + } - return info; + return mostRecentEventTime; } -var current = null; -var isRendering = false; -function getCurrentFiberOwnerNameInDevOrNull() { - { - if (current === null) { - return null; - } - var owner = current._debugOwner; +function computeExpirationTime(lane, currentTime) { + // TODO: Expiration heuristic is constant per lane, so could use a map. + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; - if (owner !== null && typeof owner !== "undefined") { - return getComponentName(owner.type); + if (priority >= InputContinuousLanePriority) { + // User interactions should expire slightly more quickly. + // + // NOTE: This is set to the corresponding constant as in Scheduler.js. When + // we made it larger, a product metric in www regressed, suggesting there's + // a user interaction that's being starved by a series of synchronous + // updates. If that theory is correct, the proper solution is to fix the + // starvation. However, this scenario supports the idea that expiration + // times are an important safeguard when starvation does happen. + // + // Also note that, in the case of user input specifically, this will soon no + // longer be an issue because we plan to make user input synchronous by + // default (until you enter `startTransition`, of course.) + // + // If weren't planning to make these updates synchronous soon anyway, I + // would probably make this number a configurable parameter. + return currentTime + 250; + } else if (priority >= TransitionPriority) { + return currentTime + 5000; + } else { + // Anything idle priority or lower should never expire. + return NoTimestamp; + } +} + +function markStarvedLanesAsExpired(root, currentTime) { + // TODO: This gets called every time we yield. We can optimize by storing + // the earliest expiration time on the root. Then use that to quickly bail out + // of this function. + var pendingLanes = root.pendingLanes; + var suspendedLanes = root.suspendedLanes; + var pingedLanes = root.pingedLanes; + var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their + // expiration time. If so, we'll assume the update is being starved and mark + // it as expired to force it to finish. + + var lanes = pendingLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + var expirationTime = expirationTimes[index]; + + if (expirationTime === NoTimestamp) { + // Found a pending lane with no expiration time. If it's not suspended, or + // if it's pinged, assume it's CPU-bound. Compute a new expiration time + // using the current time. + if ( + (lane & suspendedLanes) === NoLanes || + (lane & pingedLanes) !== NoLanes + ) { + // Assumes timestamps are monotonically increasing. + expirationTimes[index] = computeExpirationTime(lane, currentTime); + } + } else if (expirationTime <= currentTime) { + // This lane expired + root.expiredLanes |= lane; } + + lanes &= ~lane; } +} // This returns the highest priority pending lanes regardless of whether they +function getLanesToRetrySynchronouslyOnError(root) { + var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; - return null; -} -function getCurrentFiberStackInDev() { - { - if (current === null) { - return ""; - } // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. + if (everythingButOffscreen !== NoLanes) { + return everythingButOffscreen; + } - return getStackByFiberInDevAndProd(current); + if (everythingButOffscreen & OffscreenLane) { + return OffscreenLane; } + + return NoLanes; } -function resetCurrentFiber() { - { - ReactDebugCurrentFrame.getCurrentStack = null; - current = null; - isRendering = false; - } +function returnNextLanesPriority() { + return return_highestLanePriority; } -function setCurrentFiber(fiber) { - { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev; - current = fiber; - isRendering = false; - } +function includesNonIdleWork(lanes) { + return (lanes & NonIdleLanes) !== NoLanes; } -function setIsRendering(rendering) { - { - isRendering = rendering; - } +function includesOnlyRetries(lanes) { + return (lanes & RetryLanes) === lanes; } +function includesOnlyTransitions(lanes) { + return (lanes & TransitionLanes) === lanes; +} // To ensure consistency across multiple updates in the same event, this should +// be a pure function, so that it always returns the same lane for given inputs. + +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case NoLanePriority: + break; -var ReactStrictModeWarnings = { - recordUnsafeLifecycleWarnings: function(fiber, instance) {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordLegacyContextWarning: function(fiber, instance) {}, - flushLegacyContextWarning: function() {}, - discardPendingWarnings: function() {} -}; + case SyncLanePriority: + return SyncLane; -{ - var findStrictRoot = function(fiber) { - var maybeStrictRoot = null; - var node = fiber; + case SyncBatchedLanePriority: + return SyncBatchedLane; - while (node !== null) { - if (node.mode & StrictMode) { - maybeStrictRoot = node; + case InputDiscreteLanePriority: { + var _lane = pickArbitraryLane(InputDiscreteLanes & ~wipLanes); + + if (_lane === NoLane) { + // Shift to the next priority level + return findUpdateLane(InputContinuousLanePriority, wipLanes); } - node = node.return; + return _lane; } - return maybeStrictRoot; - }; + case InputContinuousLanePriority: { + var _lane2 = pickArbitraryLane(InputContinuousLanes & ~wipLanes); - var setToSortedString = function(set) { - var array = []; - set.forEach(function(value) { - array.push(value); - }); - return array.sort().join(", "); - }; + if (_lane2 === NoLane) { + // Shift to the next priority level + return findUpdateLane(DefaultLanePriority, wipLanes); + } - var pendingComponentWillMountWarnings = []; - var pendingUNSAFE_ComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + return _lane2; + } - var didWarnAboutUnsafeLifecycles = new Set(); + case DefaultLanePriority: { + var _lane3 = pickArbitraryLane(DefaultLanes & ~wipLanes); - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - // Dedup strategy: Warn once per component. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + if (_lane3 === NoLane) { + // If all the default lanes are already being worked on, look for a + // lane in the transition range. + _lane3 = pickArbitraryLane(TransitionLanes & ~wipLanes); - if ( - typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } + if (_lane3 === NoLane) { + // All the transition lanes are taken, too. This should be very + // rare, but as a last resort, pick a default lane. This will have + // the effect of interrupting the current work-in-progress render. + _lane3 = pickArbitraryLane(DefaultLanes); + } + } - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillMount === "function" - ) { - pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + return _lane3; } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } + case TransitionPriority: // Should be handled by findTransitionLane instead - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); - } + case RetryLanePriority: + // Should be handled by findRetryLane instead + break; - if ( - typeof instance.componentWillUpdate === "function" && - instance.componentWillUpdate.__suppressDeprecationWarning !== true - ) { - pendingComponentWillUpdateWarnings.push(fiber); - } + case IdleLanePriority: + var lane = pickArbitraryLane(IdleLanes & ~wipLanes); - if ( - fiber.mode & StrictMode && - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); - } - }; + if (lane === NoLane) { + lane = pickArbitraryLane(IdleLanes); + } - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - // We do an initial pass to gather component names - var componentWillMountUniqueNames = new Set(); + return lane; + } - if (pendingComponentWillMountWarnings.length > 0) { - pendingComponentWillMountWarnings.forEach(function(fiber) { - componentWillMountUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillMountWarnings = []; - } + { + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} // To ensure consistency across multiple updates in the same event, this should +// be pure function, so that it always returns the same lane for given inputs. - var UNSAFE_componentWillMountUniqueNames = new Set(); +function findTransitionLane(wipLanes, pendingLanes) { + // First look for lanes that are completely unclaimed, i.e. have no + // pending work. + var lane = pickArbitraryLane(TransitionLanes & ~pendingLanes); - if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { - pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { - UNSAFE_componentWillMountUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillMountWarnings = []; + if (lane === NoLane) { + // If all lanes have pending work, look for a lane that isn't currently + // being worked on. + lane = pickArbitraryLane(TransitionLanes & ~wipLanes); + + if (lane === NoLane) { + // If everything is being worked on, pick any lane. This has the + // effect of interrupting the current work-in-progress. + lane = pickArbitraryLane(TransitionLanes); } + } - var componentWillReceivePropsUniqueNames = new Set(); + return lane; +} // To ensure consistency across multiple updates in the same event, this should +// be pure function, so that it always returns the same lane for given inputs. - if (pendingComponentWillReceivePropsWarnings.length > 0) { - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - componentWillReceivePropsUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillReceivePropsWarnings = []; - } +function findRetryLane(wipLanes) { + // This is a fork of `findUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + var lane = pickArbitraryLane(RetryLanes & ~wipLanes); - var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + if (lane === NoLane) { + lane = pickArbitraryLane(RetryLanes); + } - if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { - pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { - UNSAFE_componentWillReceivePropsUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - } + return lane; +} - var componentWillUpdateUniqueNames = new Set(); +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} - if (pendingComponentWillUpdateWarnings.length > 0) { - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - componentWillUpdateUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingComponentWillUpdateWarnings = []; - } +function getLowestPriorityLane(lanes) { + // This finds the most significant non-zero bit. + var index = 31 - clz32(lanes); + return index < 0 ? NoLanes : 1 << index; +} - var UNSAFE_componentWillUpdateUniqueNames = new Set(); +function getEqualOrHigherPriorityLanes(lanes) { + return (getLowestPriorityLane(lanes) << 1) - 1; +} - if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { - pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function(fiber) { - UNSAFE_componentWillUpdateUniqueNames.add( - getComponentName(fiber.type) || "Component" - ); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - pendingUNSAFE_ComponentWillUpdateWarnings = []; - } // Finally, we flush all the warnings - // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' +function pickArbitraryLane(lanes) { + // This wrapper function gets inlined. Only exists so to communicate that it + // doesn't matter which bit is selected; you can pick any bit without + // affecting the algorithms where its used. Here I'm using + // getHighestPriorityLane because it requires the fewest operations. + return getHighestPriorityLane(lanes); +} - if (UNSAFE_componentWillMountUniqueNames.size > 0) { - var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); +function pickArbitraryLaneIndex(lanes) { + return 31 - clz32(lanes); +} - error( - "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "\nPlease update the following components: %s", - sortedNames - ); - } +function laneToIndex(lane) { + return pickArbitraryLaneIndex(lane); +} - if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames = setToSortedString( - UNSAFE_componentWillReceivePropsUniqueNames - ); +function includesSomeLane(a, b) { + return (a & b) !== NoLanes; +} +function isSubsetOfLanes(set, subset) { + return (set & subset) === subset; +} +function mergeLanes(a, b) { + return a | b; +} +function removeLanes(set, subset) { + return set & ~subset; +} // Seems redundant, but it changes the type from a single lane (used for +// updates) to a group of lanes (used for flushing work). - error( - "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, " + - "refactor your code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + - "\nPlease update the following components: %s", - _sortedNames - ); - } +function laneToLanes(lane) { + return lane; +} +function createLaneMap(initial) { + // Intentionally pushing one by one. + // https://v8.dev/blog/elements-kinds#avoid-creating-holes + var laneMap = []; - if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { - var _sortedNames2 = setToSortedString( - UNSAFE_componentWillUpdateUniqueNames - ); + for (var i = 0; i < TotalLanes; i++) { + laneMap.push(initial); + } - error( - "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + - "and may indicate bugs in your code. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "\nPlease update the following components: %s", - _sortedNames2 - ); - } + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But + // it's not practical to try every single possible combination. We need a + // heuristic to decide which lanes to attempt to render, and in which batches. + // For now, we use the same heuristic as in the old ExpirationTimes model: + // retry any lane at equal or lower priority, but don't try updates at higher + // priority without also including the lower priority updates. This works well + // when considering updates across different priority levels, but isn't + // sufficient for updates within the same priority, since we want to treat + // those updates as parallel. + // Unsuspend any update at equal or lower priority. - if (componentWillMountUniqueNames.size > 0) { - var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); + var higherPriorityLanes = updateLane - 1; // Turns 0b1000 into 0b0111 + + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + var eventTimes = root.eventTimes; + var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most + // recent event, and we assume time is monotonically increasing. + + eventTimes[index] = eventTime; +} +function markRootSuspended(root, suspendedLanes) { + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. + + var expirationTimes = root.expirationTimes; + var lanes = suspendedLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } +} +function markRootPinged(root, pingedLanes, eventTime) { + root.pingedLanes |= root.suspendedLanes & pingedLanes; +} +function hasDiscreteLanes(lanes) { + return (lanes & InputDiscreteLanes) !== NoLanes; +} +function markRootMutableRead(root, updateLane) { + root.mutableReadLanes |= updateLane & root.pendingLanes; +} +function markRootFinished(root, remainingLanes) { + var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; + root.pendingLanes = remainingLanes; // Let's try everything again + + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes; + root.mutableReadLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + var entanglements = root.entanglements; + var eventTimes = root.eventTimes; + var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work + + var lanes = noLongerPendingLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] = NoLanes; + eventTimes[index] = NoTimestamp; + expirationTimes[index] = NoTimestamp; + lanes &= ~lane; + } +} +function markRootEntangled(root, entangledLanes) { + root.entangledLanes |= entangledLanes; + var entanglements = root.entanglements; + var lanes = entangledLanes; + + while (lanes > 0) { + var index = pickArbitraryLaneIndex(lanes); + var lane = 1 << index; + entanglements[index] |= entangledLanes; + lanes &= ~lane; + } +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. Only used on lanes, so assume input is an integer. +// Based on: +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +var log = Math.log; +var LN2 = Math.LN2; + +function clz32Fallback(lanes) { + if (lanes === 0) { + return 32; + } + + return (31 - ((log(lanes) / LN2) | 0)) | 0; +} + +// Intentionally not named imports because Rollup would use dynamic dispatch for +var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, + Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, + Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, + Scheduler_shouldYield = Scheduler.unstable_shouldYield, + Scheduler_requestPaint = Scheduler.unstable_requestPaint, + Scheduler_now$1 = Scheduler.unstable_now, + Scheduler_getCurrentPriorityLevel = + Scheduler.unstable_getCurrentPriorityLevel, + Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, + Scheduler_UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, + Scheduler_NormalPriority = Scheduler.unstable_NormalPriority, + Scheduler_LowPriority = Scheduler.unstable_LowPriority, + Scheduler_IdlePriority = Scheduler.unstable_IdlePriority; + +{ + // Provide explicit error message when production+profiling bundle of e.g. + // react-dom is used with production (non-profiling) bundle of + // scheduler/tracing + if ( + !( + tracing.__interactionsRef != null && + tracing.__interactionsRef.current != null + ) + ) { + throw Error( + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" + ); + } +} + +var fakeCallbackNode = {}; // Except for NoPriority, these correspond to Scheduler priorities. We use +// ascending numbers so we can compare them like numbers. They start at 90 to +// avoid clashing with Scheduler's priorities. - warn( - "componentWillMount has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + - "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames3 - ); - } +var ImmediatePriority$1 = 99; +var UserBlockingPriority$1 = 98; +var NormalPriority$1 = 97; +var LowPriority$1 = 96; +var IdlePriority$1 = 95; // NoPriority is the absence of priority. Also React-only. - if (componentWillReceivePropsUniqueNames.size > 0) { - var _sortedNames4 = setToSortedString( - componentWillReceivePropsUniqueNames - ); +var NoPriority$1 = 90; +var shouldYield = Scheduler_shouldYield; +var requestPaint = // Fall back gracefully if we're running an older version of Scheduler. + Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : function() {}; +var syncQueue = null; +var immediateQueueCallbackNode = null; +var isFlushingSyncQueue = false; +var initialTimeMs$1 = Scheduler_now$1(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly. +// This will be the case for modern browsers that support `performance.now`. In +// older browsers, Scheduler falls back to `Date.now`, which returns a Unix +// timestamp. In that case, subtract the module initialization time to simulate +// the behavior of performance.now and keep our times small enough to fit +// within 32 bits. +// TODO: Consider lifting this into Scheduler. - warn( - "componentWillReceiveProps has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* If you're updating state whenever props change, refactor your " + - "code to use memoization techniques or move it to " + - "static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state\n" + - "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames4 - ); - } +var now = + initialTimeMs$1 < 10000 + ? Scheduler_now$1 + : function() { + return Scheduler_now$1() - initialTimeMs$1; + }; +function getCurrentPriorityLevel() { + switch (Scheduler_getCurrentPriorityLevel()) { + case Scheduler_ImmediatePriority: + return ImmediatePriority$1; - if (componentWillUpdateUniqueNames.size > 0) { - var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + case Scheduler_UserBlockingPriority: + return UserBlockingPriority$1; - warn( - "componentWillUpdate has been renamed, and is not recommended for use. " + - "See https://fb.me/react-unsafe-component-lifecycles for details.\n\n" + - "* Move data fetching code or side effects to componentDidUpdate.\n" + - "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + - "this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. " + - "To rename all deprecated lifecycles to their new names, you can run " + - "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + - "\nPlease update the following components: %s", - _sortedNames5 - ); - } - }; + case Scheduler_NormalPriority: + return NormalPriority$1; - var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. + case Scheduler_LowPriority: + return LowPriority$1; - var didWarnAboutLegacyContext = new Set(); + case Scheduler_IdlePriority: + return IdlePriority$1; - ReactStrictModeWarnings.recordLegacyContextWarning = function( - fiber, - instance - ) { - var strictRoot = findStrictRoot(fiber); + default: { + throw Error("Unknown priority level."); + } + } +} - if (strictRoot === null) { - error( - "Expected to find a StrictMode component in a strict mode tree. " + - "This error is likely caused by a bug in React. Please file an issue." - ); +function reactPriorityToSchedulerPriority(reactPriorityLevel) { + switch (reactPriorityLevel) { + case ImmediatePriority$1: + return Scheduler_ImmediatePriority; - return; - } // Dedup strategy: Warn once per component. + case UserBlockingPriority$1: + return Scheduler_UserBlockingPriority; - if (didWarnAboutLegacyContext.has(fiber.type)) { - return; - } + case NormalPriority$1: + return Scheduler_NormalPriority; - var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + case LowPriority$1: + return Scheduler_LowPriority; - if ( - fiber.type.contextTypes != null || - fiber.type.childContextTypes != null || - (instance !== null && typeof instance.getChildContext === "function") - ) { - if (warningsForRoot === undefined) { - warningsForRoot = []; - pendingLegacyContextWarning.set(strictRoot, warningsForRoot); - } + case IdlePriority$1: + return Scheduler_IdlePriority; - warningsForRoot.push(fiber); + default: { + throw Error("Unknown priority level."); } - }; + } +} - ReactStrictModeWarnings.flushLegacyContextWarning = function() { - pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { - if (fiberArray.length === 0) { - return; - } +function runWithPriority(reactPriorityLevel, fn) { + var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); + return Scheduler_runWithPriority(priorityLevel, fn); +} +function scheduleCallback(reactPriorityLevel, callback, options) { + var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); + return Scheduler_scheduleCallback(priorityLevel, callback, options); +} +function scheduleSyncCallback(callback) { + // Push this callback into an internal queue. We'll flush these either in + // the next tick, or earlier if something calls `flushSyncCallbackQueue`. + if (syncQueue === null) { + syncQueue = [callback]; // Flush the queue in the next tick, at the earliest. - var firstFiber = fiberArray[0]; - var uniqueNames = new Set(); - fiberArray.forEach(function(fiber) { - uniqueNames.add(getComponentName(fiber.type) || "Component"); - didWarnAboutLegacyContext.add(fiber.type); - }); - var sortedNames = setToSortedString(uniqueNames); - var firstComponentStack = getStackByFiberInDevAndProd(firstFiber); + immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ); + } else { + // Push onto existing queue. Don't need to schedule a callback because + // we already scheduled one when we created the queue. + syncQueue.push(callback); + } - error( - "Legacy context API has been detected within a strict-mode tree." + - "\n\nThe old API will be supported in all 16.x releases, but applications " + - "using it should migrate to the new version." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here: https://fb.me/react-legacy-context" + - "%s", - sortedNames, - firstComponentStack - ); - }); - }; + return fakeCallbackNode; +} +function cancelCallback(callbackNode) { + if (callbackNode !== fakeCallbackNode) { + Scheduler_cancelCallback(callbackNode); + } +} +function flushSyncCallbackQueue() { + if (immediateQueueCallbackNode !== null) { + var node = immediateQueueCallbackNode; + immediateQueueCallbackNode = null; + Scheduler_cancelCallback(node); + } - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingUNSAFE_ComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingUNSAFE_ComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUNSAFE_ComponentWillUpdateWarnings = []; - pendingLegacyContextWarning = new Map(); - }; + flushSyncCallbackQueueImpl(); } -var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. +function flushSyncCallbackQueueImpl() { + if (!isFlushingSyncQueue && syncQueue !== null) { + // Prevent re-entrancy. + isFlushingSyncQueue = true; + var i = 0; -var failedBoundaries = null; -var setRefreshHandler = function(handler) { - { - resolveFamily = handler; - } -}; -function resolveFunctionForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; + { + try { + var _isSync2 = true; + var _queue = syncQueue; + runWithPriority(ImmediatePriority$1, function() { + for (; i < _queue.length; i++) { + var callback = _queue[i]; + + do { + callback = callback(_isSync2); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } // Resume flushing in the next tick + + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue + ); + throw error; + } finally { + isFlushingSyncQueue = false; + } } + } +} - var family = resolveFamily(type); +// TODO: this is special because it gets imported during build. +var ReactVersion = "17.0.1-454c2211c"; - if (family === undefined) { - return type; - } // Use the latest known implementation. +var NoMode = 0; +var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root +// tag instead - return family.current; - } +var BlockingMode = 2; +var ConcurrentMode = 4; +var ProfileMode = 8; +var DebugTracingMode = 16; + +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +var NoTransition = 0; +function requestCurrentTransition() { + return ReactCurrentBatchConfig.transition; } -function resolveClassForHotReloading(type) { - // No implementation differences. - return resolveFunctionForHotReloading(type); + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + return ( + (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare + ); } -function resolveForwardRefForHotReloading(type) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. - return type; - } - var family = resolveFamily(type); +var objectIs = typeof Object.is === "function" ? Object.is : is; - if (family === undefined) { - // Check if we're dealing with a real forwardRef. Don't want to crash early. - if ( - type !== null && - type !== undefined && - typeof type.render === "function" - ) { - // ForwardRef is special because its resolved .type is an object, - // but it's possible that we only have its inner render function in the map. - // If that inner render function is different, we'll build a new forwardRef type. - var currentRender = resolveFunctionForHotReloading(type.render); +var hasOwnProperty = Object.prototype.hasOwnProperty; +/** + * Performs equality by iterating through keys on an object and returning false + * when any key has values which are not strictly equal between the arguments. + * Returns true when the values of all keys are strictly equal. + */ - if (type.render !== currentRender) { - var syntheticType = { - $$typeof: REACT_FORWARD_REF_TYPE, - render: currentRender - }; +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) { + return true; + } - if (type.displayName !== undefined) { - syntheticType.displayName = type.displayName; - } + if ( + typeof objA !== "object" || + objA === null || + typeof objB !== "object" || + objB === null + ) { + return false; + } - return syntheticType; - } - } + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); - return type; - } // Use the latest known implementation. + if (keysA.length !== keysB.length) { + return false; + } // Test for A's keys different from B. - return family.current; - } -} -function isCompatibleFamilyForHotReloading(fiber, element) { - { - if (resolveFamily === null) { - // Hot reloading is disabled. + for (var i = 0; i < keysA.length; i++) { + if ( + !hasOwnProperty.call(objB, keysA[i]) || + !objectIs(objA[keysA[i]], objB[keysA[i]]) + ) { return false; } + } - var prevType = fiber.elementType; - var nextType = element.type; // If we got here, we know types aren't === equal. - - var needsCompareFamilies = false; - var $$typeofNextType = - typeof nextType === "object" && nextType !== null - ? nextType.$$typeof - : null; + return true; +} - switch (fiber.tag) { - case ClassComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } +function describeFiber(fiber) { + var owner = fiber._debugOwner ? fiber._debugOwner.type : null; + var source = fiber._debugSource; - break; - } + switch (fiber.tag) { + case HostComponent: + return describeBuiltInComponentFrame(fiber.type, source, owner); - case FunctionComponent: { - if (typeof nextType === "function") { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - // We don't know the inner type yet. - // We're going to assume that the lazy inner type is stable, - // and so it is sufficient to avoid reconciling it away. - // We're not going to unwrap or actually use the new lazy type. - needsCompareFamilies = true; - } + case LazyComponent: + return describeBuiltInComponentFrame("Lazy", source, owner); - break; - } + case SuspenseComponent: + return describeBuiltInComponentFrame("Suspense", source, owner); - case ForwardRef: { - if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + case SuspenseListComponent: + return describeBuiltInComponentFrame("SuspenseList", source, owner); - break; - } + case FunctionComponent: + case IndeterminateComponent: + case SimpleMemoComponent: + return describeFunctionComponentFrame(fiber.type, source, owner); - case MemoComponent: - case SimpleMemoComponent: { - if ($$typeofNextType === REACT_MEMO_TYPE) { - // TODO: if it was but can no longer be simple, - // we shouldn't set this. - needsCompareFamilies = true; - } else if ($$typeofNextType === REACT_LAZY_TYPE) { - needsCompareFamilies = true; - } + case ForwardRef: + return describeFunctionComponentFrame(fiber.type.render, source, owner); - break; - } + case ClassComponent: + return describeClassComponentFrame(fiber.type, source, owner); - default: - return false; - } // Check if both types have a family and it's the same one. + default: + return ""; + } +} - if (needsCompareFamilies) { - // Note: memo() and forwardRef() we'll compare outer rather than inner type. - // This means both of them need to be registered to preserve state. - // If we unwrapped and compared the inner types for wrappers instead, - // then we would risk falsely saying two separate memo(Foo) - // calls are equivalent because they wrap the same Foo function. - var prevFamily = resolveFamily(prevType); +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = ""; + var node = workInProgress; - if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { - return true; - } - } + do { + info += describeFiber(node); + node = node.return; + } while (node); - return false; + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; } } -function markFailedErrorBoundaryForHotReloading(fiber) { + +var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; +var current = null; +var isRendering = false; +function getCurrentFiberOwnerNameInDevOrNull() { { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; + if (current === null) { + return null; } - if (typeof WeakSet !== "function") { - return; - } + var owner = current._debugOwner; - if (failedBoundaries === null) { - failedBoundaries = new WeakSet(); + if (owner !== null && typeof owner !== "undefined") { + return getComponentName(owner.type); } + } - failedBoundaries.add(fiber); + return null; +} + +function getCurrentFiberStackInDev() { + { + if (current === null) { + return ""; + } // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + + return getStackByFiberInDevAndProd(current); } } -var scheduleRefresh = function(root, update) { + +function resetCurrentFiber() { { - if (resolveFamily === null) { - // Hot reloading is disabled. - return; + ReactDebugCurrentFrame$1.getCurrentStack = null; + current = null; + isRendering = false; + } +} +function setCurrentFiber(fiber) { + { + ReactDebugCurrentFrame$1.getCurrentStack = getCurrentFiberStackInDev; + current = fiber; + isRendering = false; + } +} +function setIsRendering(rendering) { + { + isRendering = rendering; + } +} +function getIsRendering() { + { + return isRendering; + } +} + +var ReactStrictModeWarnings = { + recordUnsafeLifecycleWarnings: function(fiber, instance) {}, + flushPendingUnsafeLifecycleWarnings: function() {}, + recordLegacyContextWarning: function(fiber, instance) {}, + flushLegacyContextWarning: function() {}, + discardPendingWarnings: function() {} +}; + +{ + var findStrictRoot = function(fiber) { + var maybeStrictRoot = null; + var node = fiber; + + while (node !== null) { + if (node.mode & StrictMode) { + maybeStrictRoot = node; + } + + node = node.return; } - var staleFamilies = update.staleFamilies, - updatedFamilies = update.updatedFamilies; - flushPassiveEffects(); - flushSync(function() { - scheduleFibersWithFamiliesRecursively( - root.current, - updatedFamilies, - staleFamilies - ); + return maybeStrictRoot; + }; + + var setToSortedString = function(set) { + var array = []; + set.forEach(function(value) { + array.push(value); }); - } -}; -var scheduleRoot = function(root, element) { - { - if (root.context !== emptyContextObject) { - // Super edge case: root has a legacy _renderSubtree context - // but we don't know the parentComponent so we can't pass it. - // Just ignore. We'll delete this with _renderSubtree code path later. + return array.sort().join(", "); + }; + + var pendingComponentWillMountWarnings = []; + var pendingUNSAFE_ComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. + + var didWarnAboutUnsafeLifecycles = new Set(); + + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( + fiber, + instance + ) { + // Dedup strategy: Warn once per component. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { return; } - flushPassiveEffects(); - syncUpdates(function() { - updateContainer(element, root, null, null); - }); - } -}; + if ( + typeof instance.componentWillMount === "function" && // Don't warn about react-lifecycles-compat polyfilled components. + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } -function scheduleFibersWithFamiliesRecursively( - fiber, - updatedFamilies, - staleFamilies -) { - { - var alternate = fiber.alternate, - child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillMount === "function" + ) { + pendingUNSAFE_ComponentWillMountWarnings.push(fiber); + } - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } - case ForwardRef: - candidateType = type.render; - break; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); } - if (resolveFamily === null) { - throw new Error("Expected resolveFamily to be set during hot reload."); + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); } - var needsRender = false; - var needsRemount = false; + if ( + fiber.mode & StrictMode && + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); + } + }; - if (candidateType !== null) { - var family = resolveFamily(candidateType); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { + // We do an initial pass to gather component names + var componentWillMountUniqueNames = new Set(); - if (family !== undefined) { - if (staleFamilies.has(family)) { - needsRemount = true; - } else if (updatedFamilies.has(family)) { - if (tag === ClassComponent) { - needsRemount = true; - } else { - needsRender = true; - } - } - } + if (pendingComponentWillMountWarnings.length > 0) { + pendingComponentWillMountWarnings.forEach(function(fiber) { + componentWillMountUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillMountWarnings = []; } - if (failedBoundaries !== null) { - if ( - failedBoundaries.has(fiber) || - (alternate !== null && failedBoundaries.has(alternate)) - ) { - needsRemount = true; - } + var UNSAFE_componentWillMountUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { + pendingUNSAFE_ComponentWillMountWarnings.forEach(function(fiber) { + UNSAFE_componentWillMountUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillMountWarnings = []; } - if (needsRemount) { - fiber._debugNeedsRemount = true; + var componentWillReceivePropsUniqueNames = new Set(); + + if (pendingComponentWillReceivePropsWarnings.length > 0) { + pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { + componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillReceivePropsWarnings = []; } - if (needsRemount || needsRender) { - scheduleWork(fiber, Sync); + var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { + pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function(fiber) { + UNSAFE_componentWillReceivePropsUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; } - if (child !== null && !needsRemount) { - scheduleFibersWithFamiliesRecursively( - child, - updatedFamilies, - staleFamilies - ); + var componentWillUpdateUniqueNames = new Set(); + + if (pendingComponentWillUpdateWarnings.length > 0) { + pendingComponentWillUpdateWarnings.forEach(function(fiber) { + componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingComponentWillUpdateWarnings = []; } - if (sibling !== null) { - scheduleFibersWithFamiliesRecursively( - sibling, - updatedFamilies, - staleFamilies + var UNSAFE_componentWillUpdateUniqueNames = new Set(); + + if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { + pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function(fiber) { + UNSAFE_componentWillUpdateUniqueNames.add( + getComponentName(fiber.type) || "Component" + ); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); + pendingUNSAFE_ComponentWillUpdateWarnings = []; + } // Finally, we flush all the warnings + // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' + + if (UNSAFE_componentWillMountUniqueNames.size > 0) { + var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); + + error( + "Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "\nPlease update the following components: %s", + sortedNames ); } - } -} -var findHostInstancesForRefresh = function(root, families) { - { - var hostInstances = new Set(); - var types = new Set( - families.map(function(family) { - return family.current; - }) - ); - findHostInstancesForMatchingFibersRecursively( - root.current, - types, - hostInstances - ); - return hostInstances; - } -}; + if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames = setToSortedString( + UNSAFE_componentWillReceivePropsUniqueNames + ); -function findHostInstancesForMatchingFibersRecursively( - fiber, - types, - hostInstances -) { - { - var child = fiber.child, - sibling = fiber.sibling, - tag = fiber.tag, - type = fiber.type; - var candidateType = null; + error( + "Using UNSAFE_componentWillReceiveProps in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, " + + "refactor your code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "\nPlease update the following components: %s", + _sortedNames + ); + } - switch (tag) { - case FunctionComponent: - case SimpleMemoComponent: - case ClassComponent: - candidateType = type; - break; + if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { + var _sortedNames2 = setToSortedString( + UNSAFE_componentWillUpdateUniqueNames + ); - case ForwardRef: - candidateType = type.render; - break; + error( + "Using UNSAFE_componentWillUpdate in strict mode is not recommended " + + "and may indicate bugs in your code. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "\nPlease update the following components: %s", + _sortedNames2 + ); } - var didMatch = false; + if (componentWillMountUniqueNames.size > 0) { + var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); - if (candidateType !== null) { - if (types.has(candidateType)) { - didMatch = true; - } + warn( + "componentWillMount has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move code with side effects to componentDidMount, and set initial state in the constructor.\n" + + "* Rename componentWillMount to UNSAFE_componentWillMount to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames3 + ); } - if (didMatch) { - // We have a match. This only drills down to the closest host components. - // There's no need to search deeper because for the purpose of giving - // visual feedback, "flashing" outermost parent rectangles is sufficient. - findHostInstancesForFiberShallowly(fiber, hostInstances); - } else { - // If there's no match, maybe there will be one further down in the child tree. - if (child !== null) { - findHostInstancesForMatchingFibersRecursively( - child, - types, - hostInstances - ); - } + if (componentWillReceivePropsUniqueNames.size > 0) { + var _sortedNames4 = setToSortedString( + componentWillReceivePropsUniqueNames + ); + + warn( + "componentWillReceiveProps has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* If you're updating state whenever props change, refactor your " + + "code to use memoization techniques or move it to " + + "static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n" + + "* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames4 + ); } - if (sibling !== null) { - findHostInstancesForMatchingFibersRecursively( - sibling, - types, - hostInstances + if (componentWillUpdateUniqueNames.size > 0) { + var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); + + warn( + "componentWillUpdate has been renamed, and is not recommended for use. " + + "See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n" + + "* Move data fetching code or side effects to componentDidUpdate.\n" + + "* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress " + + "this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. " + + "To rename all deprecated lifecycles to their new names, you can run " + + "`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n" + + "\nPlease update the following components: %s", + _sortedNames5 ); } - } -} + }; -function findHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var foundHostInstances = findChildHostInstancesForFiberShallowly( - fiber, - hostInstances - ); + var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. - if (foundHostInstances) { - return; - } // If we didn't find any host children, fallback to closest host parent. + var didWarnAboutLegacyContext = new Set(); - var node = fiber; + ReactStrictModeWarnings.recordLegacyContextWarning = function( + fiber, + instance + ) { + var strictRoot = findStrictRoot(fiber); - while (true) { - switch (node.tag) { - case HostComponent: - hostInstances.add(node.stateNode); - return; + if (strictRoot === null) { + error( + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - case HostPortal: - hostInstances.add(node.stateNode.containerInfo); - return; + return; + } // Dedup strategy: Warn once per component. - case HostRoot: - hostInstances.add(node.stateNode.containerInfo); - return; - } + if (didWarnAboutLegacyContext.has(fiber.type)) { + return; + } - if (node.return === null) { - throw new Error("Expected to reach root first."); + var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); + + if ( + fiber.type.contextTypes != null || + fiber.type.childContextTypes != null || + (instance !== null && typeof instance.getChildContext === "function") + ) { + if (warningsForRoot === undefined) { + warningsForRoot = []; + pendingLegacyContextWarning.set(strictRoot, warningsForRoot); } - node = node.return; + warningsForRoot.push(fiber); } - } -} - -function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { - { - var node = fiber; - var foundHostInstances = false; + }; - while (true) { - if (node.tag === HostComponent) { - // We got a match. - foundHostInstances = true; - hostInstances.add(node.stateNode); // There may still be more, so keep searching. - } else if (node.child !== null) { - node.child.return = node; - node = node.child; - continue; + ReactStrictModeWarnings.flushLegacyContextWarning = function() { + pendingLegacyContextWarning.forEach(function(fiberArray, strictRoot) { + if (fiberArray.length === 0) { + return; } - if (node === fiber) { - return foundHostInstances; - } + var firstFiber = fiberArray[0]; + var uniqueNames = new Set(); + fiberArray.forEach(function(fiber) { + uniqueNames.add(getComponentName(fiber.type) || "Component"); + didWarnAboutLegacyContext.add(fiber.type); + }); + var sortedNames = setToSortedString(uniqueNames); - while (node.sibling === null) { - if (node.return === null || node.return === fiber) { - return foundHostInstances; - } + try { + setCurrentFiber(firstFiber); - node = node.return; + error( + "Legacy context API has been detected within a strict-mode tree." + + "\n\nThe old API will be supported in all 16.x releases, but applications " + + "using it should migrate to the new version." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context", + sortedNames + ); + } finally { + resetCurrentFiber(); } + }); + }; - node.sibling.return = node.return; - node = node.sibling; - } - } - - return false; + ReactStrictModeWarnings.discardPendingWarnings = function() { + pendingComponentWillMountWarnings = []; + pendingUNSAFE_ComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingUNSAFE_ComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUNSAFE_ComponentWillUpdateWarnings = []; + pendingLegacyContextWarning = new Map(); + }; } function resolveDefaultProps(Component, baseProps) { @@ -6424,15 +6459,11 @@ function resolveDefaultProps(Component, baseProps) { return baseProps; } -function readLazyComponentType(lazyComponent) { - initializeLazyComponentType(lazyComponent); - - if (lazyComponent._status !== Resolved) { - throw lazyComponent._result; - } - return lazyComponent._result; -} +// Max 31 bit integer. The max integer size in V8 for 32-bit systems. +// Math.pow(2, 30) - 1 +// 0b111111111111111111111111111111 +var MAX_SIGNED_31_BIT_INT = 1073741823; var valueCursor = createCursor(null); var rendererSigil; @@ -6522,28 +6553,24 @@ function calculateChangedBits(context, newValue, oldValue) { return changedBits | 0; } } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { - // Update the child expiration time of all the ancestors, including - // the alternates. +function scheduleWorkOnParentPath(parent, renderLanes) { + // Update the child lanes of all the ancestors, including the alternates. var node = parent; while (node !== null) { var alternate = node.alternate; - if (node.childExpirationTime < renderExpirationTime) { - node.childExpirationTime = renderExpirationTime; + if (!isSubsetOfLanes(node.childLanes, renderLanes)) { + node.childLanes = mergeLanes(node.childLanes, renderLanes); - if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } } else if ( alternate !== null && - alternate.childExpirationTime < renderExpirationTime + !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { - alternate.childExpirationTime = renderExpirationTime; + alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); } else { // Neither alternate was updated, which means the rest of the // ancestor path already has sufficient priority. @@ -6557,7 +6584,7 @@ function propagateContextChange( workInProgress, context, changedBits, - renderExpirationTime + renderLanes ) { var fiber = workInProgress.child; @@ -6584,7 +6611,10 @@ function propagateContextChange( // Match! Schedule an update on this fiber. if (fiber.tag === ClassComponent) { // Schedule a force update on the work-in-progress. - var update = createUpdate(renderExpirationTime, null); + var update = createUpdate( + NoTimestamp, + pickArbitraryLane(renderLanes) + ); update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the // update to the current fiber, too, which means it will persist even if // this render is thrown away. Since it's a race condition, not sure it's @@ -6593,24 +6623,16 @@ function propagateContextChange( enqueueUpdate(fiber, update); } - if (fiber.expirationTime < renderExpirationTime) { - fiber.expirationTime = renderExpirationTime; - } - + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; - if ( - alternate !== null && - alternate.expirationTime < renderExpirationTime - ) { - alternate.expirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); // Mark the expiration time on the list, too. + scheduleWorkOnParentPath(fiber.return, renderLanes); // Mark the updated lanes on the list, too. - if (list.expirationTime < renderExpirationTime) { - list.expirationTime = renderExpirationTime; - } // Since we already found a match, we can stop traversing the + list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the // dependency list. break; @@ -6656,7 +6678,7 @@ function propagateContextChange( fiber = nextFiber; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextDependency = null; lastContextWithAllBitsObserved = null; @@ -6666,7 +6688,7 @@ function prepareToReadContext(workInProgress, renderExpirationTime) { var firstContext = dependencies.firstContext; if (firstContext !== null) { - if (dependencies.expirationTime >= renderExpirationTime) { + if (includesSomeLane(dependencies.lanes, renderLanes)) { // Context list has a pending update. Mark that this fiber performed work. markWorkInProgressReceivedUpdate(); } // Reset the work-in-progress list @@ -6720,7 +6742,7 @@ function readContext(context, observedBits) { lastContextDependency = contextItem; currentlyRenderingFiber.dependencies = { - expirationTime: NoWork, + lanes: NoLanes, firstContext: contextItem, responders: null }; @@ -6752,7 +6774,8 @@ var currentlyProcessingQueue; function initializeUpdateQueue(fiber) { var queue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, @@ -6768,28 +6791,23 @@ function cloneUpdateQueue(current, workInProgress) { if (queue === currentQueue) { var clone = { baseState: currentQueue.baseState, - baseQueue: currentQueue.baseQueue, + firstBaseUpdate: currentQueue.firstBaseUpdate, + lastBaseUpdate: currentQueue.lastBaseUpdate, shared: currentQueue.shared, effects: currentQueue.effects }; workInProgress.updateQueue = clone; } } -function createUpdate(expirationTime, suspenseConfig) { +function createUpdate(eventTime, lane) { var update = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, + eventTime: eventTime, + lane: lane, tag: UpdateState, payload: null, callback: null, next: null }; - update.next = update; - - { - update.priority = getCurrentPriorityLevel(); - } - return update; } function enqueueUpdate(fiber, update) { @@ -6829,25 +6847,84 @@ function enqueueUpdate(fiber, update) { } } } -function enqueueCapturedUpdate(workInProgress, update) { +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + // Captured updates are updates that are thrown by a child during the render + // phase. They should be discarded if the render is aborted. Therefore, + // we should only put them on the work-in-progress queue, not the current one. + var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. + var current = workInProgress.alternate; if (current !== null) { - // Ensure the work-in-progress queue is a clone - cloneUpdateQueue(current, workInProgress); - } // Captured updates go only on the work-in-progress queue. + var currentQueue = current.updateQueue; + + if (queue === currentQueue) { + // The work-in-progress queue is the same as current. This happens when + // we bail out on a parent fiber that then captures an error thrown by + // a child. Since we want to append the update only to the work-in + // -progress queue, we need to clone the updates. We usually clone during + // processUpdateQueue, but that didn't happen in this case because we + // skipped over the parent when we bailed out. + var newFirst = null; + var newLast = null; + var firstBaseUpdate = queue.firstBaseUpdate; + + if (firstBaseUpdate !== null) { + // Loop through the updates and clone them. + var update = firstBaseUpdate; + + do { + var clone = { + eventTime: update.eventTime, + lane: update.lane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - var queue = workInProgress.updateQueue; // Append the update to the end of the list. + if (newLast === null) { + newFirst = newLast = clone; + } else { + newLast.next = clone; + newLast = clone; + } - var last = queue.baseQueue; + update = update.next; + } while (update !== null); // Append the captured update the end of the cloned list. - if (last === null) { - queue.baseQueue = update.next = update; - update.next = update; + if (newLast === null) { + newFirst = newLast = capturedUpdate; + } else { + newLast.next = capturedUpdate; + newLast = capturedUpdate; + } + } else { + // There are no base updates. + newFirst = newLast = capturedUpdate; + } + + queue = { + baseState: currentQueue.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: currentQueue.shared, + effects: currentQueue.effects + }; + workInProgress.updateQueue = queue; + return; + } + } // Append the update to the end of the list. + + var lastBaseUpdate = queue.lastBaseUpdate; + + if (lastBaseUpdate === null) { + queue.firstBaseUpdate = capturedUpdate; } else { - update.next = last.next; - last.next = update; + lastBaseUpdate.next = capturedUpdate; } + + queue.lastBaseUpdate = capturedUpdate; } function getStateFromUpdate( @@ -6881,8 +6958,8 @@ function getStateFromUpdate( } case CaptureUpdate: { - workInProgress.effectTag = - (workInProgress.effectTag & ~ShouldCapture) | DidCapture; + workInProgress.flags = + (workInProgress.flags & ~ShouldCapture) | DidCapture; } // Intentional fallthrough @@ -6923,161 +7000,163 @@ function getStateFromUpdate( return prevState; } -function processUpdateQueue( - workInProgress, - props, - instance, - renderExpirationTime -) { +function processUpdateQueue(workInProgress, props, instance, renderLanes) { // This is always non-null on a ClassComponent or HostRoot var queue = workInProgress.updateQueue; hasForceUpdate = false; { currentlyProcessingQueue = queue.shared; - } // The last rebase update that is NOT part of the base state. + } - var baseQueue = queue.baseQueue; // The last pending update that hasn't been processed yet. + var firstBaseUpdate = queue.firstBaseUpdate; + var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. var pendingQueue = queue.shared.pending; if (pendingQueue !== null) { - // We have new updates that haven't been processed yet. - // We'll add them to the base queue. - if (baseQueue !== null) { - // Merge the pending queue and the base queue. - var baseFirst = baseQueue.next; - var pendingFirst = pendingQueue.next; - baseQueue.next = pendingFirst; - pendingQueue.next = baseFirst; + queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first + // and last so that it's non-circular. + + var lastPendingUpdate = pendingQueue; + var firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; // Append pending updates to base queue + + if (lastBaseUpdate === null) { + firstBaseUpdate = firstPendingUpdate; + } else { + lastBaseUpdate.next = firstPendingUpdate; } - baseQueue = pendingQueue; - queue.shared.pending = null; // TODO: Pass `current` as argument + lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then + // we need to transfer the updates to that queue, too. Because the base + // queue is a singly-linked list with no cycles, we can append to both + // lists and take advantage of structural sharing. + // TODO: Pass `current` as argument var current = workInProgress.alternate; if (current !== null) { + // This is always non-null on a ClassComponent or HostRoot var currentQueue = current.updateQueue; + var currentLastBaseUpdate = currentQueue.lastBaseUpdate; - if (currentQueue !== null) { - currentQueue.baseQueue = pendingQueue; + if (currentLastBaseUpdate !== lastBaseUpdate) { + if (currentLastBaseUpdate === null) { + currentQueue.firstBaseUpdate = firstPendingUpdate; + } else { + currentLastBaseUpdate.next = firstPendingUpdate; + } + + currentQueue.lastBaseUpdate = lastPendingUpdate; } } } // These values may change as we process the queue. - if (baseQueue !== null) { - var first = baseQueue.next; // Iterate through the list of updates to compute the result. + if (firstBaseUpdate !== null) { + // Iterate through the list of updates to compute the result. + var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes + // from the original lanes. - var newState = queue.baseState; - var newExpirationTime = NoWork; + var newLanes = NoLanes; var newBaseState = null; - var newBaseQueueFirst = null; - var newBaseQueueLast = null; + var newFirstBaseUpdate = null; + var newLastBaseUpdate = null; + var update = firstBaseUpdate; + + do { + var updateLane = update.lane; + var updateEventTime = update.eventTime; - if (first !== null) { - var update = first; + if (!isSubsetOfLanes(renderLanes, updateLane)) { + // Priority is insufficient. Skip this update. If this is the first + // skipped update, the previous update/state is the new base + // update/state. + var clone = { + eventTime: updateEventTime, + lane: updateLane, + tag: update.tag, + payload: update.payload, + callback: update.callback, + next: null + }; - do { - var updateExpirationTime = update.expirationTime; + if (newLastBaseUpdate === null) { + newFirstBaseUpdate = newLastBaseUpdate = clone; + newBaseState = newState; + } else { + newLastBaseUpdate = newLastBaseUpdate.next = clone; + } // Update the remaining priority in the queue. - if (updateExpirationTime < renderExpirationTime) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, + newLanes = mergeLanes(newLanes, updateLane); + } else { + // This update does have sufficient priority. + if (newLastBaseUpdate !== null) { + var _clone = { + eventTime: updateEventTime, + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, tag: update.tag, payload: update.payload, callback: update.callback, next: null }; + newLastBaseUpdate = newLastBaseUpdate.next = _clone; + } // Process this update. - if (newBaseQueueLast === null) { - newBaseQueueFirst = newBaseQueueLast = clone; - newBaseState = newState; - } else { - newBaseQueueLast = newBaseQueueLast.next = clone; - } // Update the remaining priority in the queue. - - if (updateExpirationTime > newExpirationTime) { - newExpirationTime = updateExpirationTime; - } - } else { - // This update does have sufficient priority. - if (newBaseQueueLast !== null) { - var _clone = { - expirationTime: Sync, - // This update is going to be committed so we never want uncommit it. - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }; - newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reverseable value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ); // Process this update. - - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance - ); - var callback = update.callback; + newState = getStateFromUpdate( + workInProgress, + queue, + update, + newState, + props, + instance + ); + var callback = update.callback; - if (callback !== null) { - workInProgress.effectTag |= Callback; - var effects = queue.effects; + if (callback !== null) { + workInProgress.flags |= Callback; + var effects = queue.effects; - if (effects === null) { - queue.effects = [update]; - } else { - effects.push(update); - } + if (effects === null) { + queue.effects = [update]; + } else { + effects.push(update); } } + } - update = update.next; + update = update.next; - if (update === null || update === first) { - pendingQueue = queue.shared.pending; + if (update === null) { + pendingQueue = queue.shared.pending; - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - update = baseQueue.next = pendingQueue.next; - pendingQueue.next = first; - queue.baseQueue = baseQueue = pendingQueue; - queue.shared.pending = null; - } + if (pendingQueue === null) { + break; + } else { + // An update was scheduled from inside a reducer. Add the new + // pending updates to the end of the list and keep processing. + var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we + // unravel them when transferring them to the base queue. + + var _firstPendingUpdate = _lastPendingUpdate.next; + _lastPendingUpdate.next = null; + update = _firstPendingUpdate; + queue.lastBaseUpdate = _lastPendingUpdate; + queue.shared.pending = null; } - } while (true); - } + } + } while (true); - if (newBaseQueueLast === null) { + if (newLastBaseUpdate === null) { newBaseState = newState; - } else { - newBaseQueueLast.next = newBaseQueueFirst; } queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; // Set the remaining expiration time to be whatever is remaining in the queue. + queue.firstBaseUpdate = newFirstBaseUpdate; + queue.lastBaseUpdate = newLastBaseUpdate; // Set the remaining expiration time to be whatever is remaining in the queue. // This should be fine because the only two other things that contribute to // expiration time are props and context. We're already in the middle of the // begin phase by the time we start processing the queue, so we've already @@ -7085,8 +7164,8 @@ function processUpdateQueue( // shouldComponentUpdate is tricky; but we'll have to account for // that regardless. - markUnprocessedUpdateTime(newExpirationTime); - workInProgress.expirationTime = newExpirationTime; + markSkippedUpdateLanes(newLanes); + workInProgress.lanes = newLanes; workInProgress.memoizedState = newState; } @@ -7130,11 +7209,6 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; -function requestCurrentSuspenseConfig() { - return ReactCurrentBatchConfig.suspense; -} - var fakeInternalInstance = {}; var isArray = Array.isArray; // React.Component uses a shared frozen object by default. // We'll use it to determine whether we need to initialize legacy refs. @@ -7235,7 +7309,7 @@ function applyDerivedStateFromProps( workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the // base state. - if (workInProgress.expirationTime === NoWork) { + if (workInProgress.lanes === NoLanes) { // Queue is always non-null for classes var updateQueue = workInProgress.updateQueue; updateQueue.baseState = memoizedState; @@ -7245,14 +7319,9 @@ var classComponentUpdater = { isMounted: isMounted, enqueueSetState: function(inst, payload, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.payload = payload; if (callback !== undefined && callback !== null) { @@ -7264,18 +7333,13 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ReplaceState; update.payload = payload; @@ -7288,18 +7352,13 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { var fiber = get(inst); - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); - var update = createUpdate(expirationTime, suspenseConfig); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); + var update = createUpdate(eventTime, lane); update.tag = ForceUpdate; if (callback !== undefined && callback !== null) { @@ -7311,7 +7370,7 @@ var classComponentUpdater = { } enqueueUpdate(fiber, update); - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } }; @@ -7327,13 +7386,11 @@ function checkShouldComponentUpdate( var instance = workInProgress.stateNode; if (typeof instance.shouldComponentUpdate === "function") { - startPhaseTimer(workInProgress, "shouldComponentUpdate"); var shouldUpdate = instance.shouldComponentUpdate( newProps, newState, nextContext ); - stopPhaseTimer(); { if (shouldUpdate === undefined) { @@ -7736,7 +7793,7 @@ function constructClassInstance(workInProgress, ctor, props) { "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + "The above lifecycles should be removed. Learn more about this warning here:\n" + - "https://fb.me/react-unsafe-component-lifecycles", + "https://reactjs.org/link/unsafe-component-lifecycles", _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : "", @@ -7759,7 +7816,6 @@ function constructClassInstance(workInProgress, ctor, props) { } function callComponentWillMount(workInProgress, instance) { - startPhaseTimer(workInProgress, "componentWillMount"); var oldState = instance.state; if (typeof instance.componentWillMount === "function") { @@ -7770,8 +7826,6 @@ function callComponentWillMount(workInProgress, instance) { instance.UNSAFE_componentWillMount(); } - stopPhaseTimer(); - if (oldState !== instance.state) { { error( @@ -7793,7 +7847,6 @@ function callComponentWillReceiveProps( nextContext ) { var oldState = instance.state; - startPhaseTimer(workInProgress, "componentWillReceiveProps"); if (typeof instance.componentWillReceiveProps === "function") { instance.componentWillReceiveProps(newProps, nextContext); @@ -7803,8 +7856,6 @@ function callComponentWillReceiveProps( instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); } - stopPhaseTimer(); - if (instance.state !== oldState) { { var componentName = getComponentName(workInProgress.type) || "Component"; @@ -7825,12 +7876,7 @@ function callComponentWillReceiveProps( } } // Invokes the mount life-cycles on a previously never rendered instance. -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { { checkClassInstance(workInProgress, ctor, newProps); } @@ -7880,7 +7926,7 @@ function mountClassInstance( } } - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; var getDerivedStateFromProps = ctor.getDerivedStateFromProps; @@ -7904,26 +7950,16 @@ function mountClassInstance( callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's // process them now. - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } - -function resumeMountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { + +function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; var oldProps = workInProgress.memoizedProps; instance.props = oldProps; @@ -7969,7 +8005,7 @@ function resumeMountClassInstance( resetHasForceUpdateBeforeProcessing(); var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); newState = workInProgress.memoizedState; if ( @@ -7981,7 +8017,7 @@ function resumeMountClassInstance( // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } return false; @@ -8017,8 +8053,6 @@ function resumeMountClassInstance( (typeof instance.UNSAFE_componentWillMount === "function" || typeof instance.componentWillMount === "function") ) { - startPhaseTimer(workInProgress, "componentWillMount"); - if (typeof instance.componentWillMount === "function") { instance.componentWillMount(); } @@ -8026,18 +8060,16 @@ function resumeMountClassInstance( if (typeof instance.UNSAFE_componentWillMount === "function") { instance.UNSAFE_componentWillMount(); } - - stopPhaseTimer(); } if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidMount === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // If shouldComponentUpdate returned false, we should still update the // memoized state to indicate that this work can be reused. @@ -8057,15 +8089,17 @@ function updateClassInstance( workInProgress, ctor, newProps, - renderExpirationTime + renderLanes ) { var instance = workInProgress.stateNode; cloneUpdateQueue(current, workInProgress); - var oldProps = workInProgress.memoizedProps; - instance.props = + var unresolvedOldProps = workInProgress.memoizedProps; + var oldProps = workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps); + ? unresolvedOldProps + : resolveDefaultProps(workInProgress.type, unresolvedOldProps); + instance.props = oldProps; + var unresolvedNewProps = workInProgress.pendingProps; var oldContext = instance.context; var contextType = ctor.contextType; var nextContext = emptyContextObject; @@ -8091,7 +8125,10 @@ function updateClassInstance( (typeof instance.UNSAFE_componentWillReceiveProps === "function" || typeof instance.componentWillReceiveProps === "function") ) { - if (oldProps !== newProps || oldContext !== nextContext) { + if ( + unresolvedOldProps !== unresolvedNewProps || + oldContext !== nextContext + ) { callComponentWillReceiveProps( workInProgress, instance, @@ -8104,11 +8141,11 @@ function updateClassInstance( resetHasForceUpdateBeforeProcessing(); var oldState = workInProgress.memoizedState; var newState = (instance.state = oldState); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); newState = workInProgress.memoizedState; if ( - oldProps === newProps && + unresolvedOldProps === unresolvedNewProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing() @@ -8117,19 +8154,19 @@ function updateClassInstance( // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } if (typeof instance.getSnapshotBeforeUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } @@ -8166,8 +8203,6 @@ function updateClassInstance( (typeof instance.UNSAFE_componentWillUpdate === "function" || typeof instance.componentWillUpdate === "function") ) { - startPhaseTimer(workInProgress, "componentWillUpdate"); - if (typeof instance.componentWillUpdate === "function") { instance.componentWillUpdate(newProps, newState, nextContext); } @@ -8175,35 +8210,33 @@ function updateClassInstance( if (typeof instance.UNSAFE_componentWillUpdate === "function") { instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); } - - stopPhaseTimer(); } if (typeof instance.componentDidUpdate === "function") { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } if (typeof instance.getSnapshotBeforeUpdate === "function") { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. if (typeof instance.componentDidUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } if (typeof instance.getSnapshotBeforeUpdate === "function") { if ( - oldProps !== current.memoizedProps || + unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState ) { - workInProgress.effectTag |= Snapshot; + workInProgress.flags |= Snapshot; } } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -8225,7 +8258,7 @@ var didWarnAboutStringRefs; var ownerHasKeyUseWarning; var ownerHasFunctionTypeWarning; -var warnForMissingKey = function(child) {}; +var warnForMissingKey = function(child, returnFiber) {}; { didWarnAboutMaps = false; @@ -8240,7 +8273,7 @@ var warnForMissingKey = function(child) {}; ownerHasKeyUseWarning = {}; ownerHasFunctionTypeWarning = {}; - warnForMissingKey = function(child) { + warnForMissingKey = function(child, returnFiber) { if (child === null || typeof child !== "object") { return; } @@ -8256,21 +8289,17 @@ var warnForMissingKey = function(child) {}; } child._store.validated = true; - var currentComponentErrorInfo = - "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + - "more information." + - getCurrentFiberStackInDev(); + var componentName = getComponentName(returnFiber.type) || "Component"; - if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + if (ownerHasKeyUseWarning[componentName]) { return; } - ownerHasKeyUseWarning[currentComponentErrorInfo] = true; + ownerHasKeyUseWarning[componentName] = true; error( "Each child in a list should have a unique " + - '"key" prop. See https://fb.me/react-warning-keys for ' + + '"key" prop. See https://reactjs.org/link/warning-keys for ' + "more information." ); }; @@ -8308,9 +8337,8 @@ function coerceRef(returnFiber, current, element) { "String refs are a source of potential bugs and should be avoided. " + "We recommend using useRef() or createRef() instead. " + "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-string-ref%s", - mixedRef, - getStackByFiberInDevAndProd(returnFiber) + "https://reactjs.org/link/strict-mode-string-ref", + mixedRef ); } @@ -8328,7 +8356,7 @@ function coerceRef(returnFiber, current, element) { if (!(ownerFiber.tag === ClassComponent)) { throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); } @@ -8382,7 +8410,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + mixedRef + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } } @@ -8393,41 +8421,27 @@ function coerceRef(returnFiber, current, element) { function throwOnInvalidObjectType(returnFiber, newChild) { if (returnFiber.type !== "textarea") { - var addendum = ""; - - { - addendum = - " If you meant to render a collection of children, use an array " + - "instead." + - getCurrentFiberStackInDev(); - } - { throw Error( "Objects are not valid as a React child (found: " + (Object.prototype.toString.call(newChild) === "[object Object]" ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + - addendum + "). If you meant to render a collection of children, use an array instead." ); } } } -function warnOnFunctionType() { +function warnOnFunctionType(returnFiber) { { - var currentComponentErrorInfo = - "Functions are not valid as a React child. This may happen if " + - "you return a Component instead of from render. " + - "Or maybe you meant to call this function rather than return it." + - getCurrentFiberStackInDev(); + var componentName = getComponentName(returnFiber.type) || "Component"; - if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) { + if (ownerHasFunctionTypeWarning[componentName]) { return; } - ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true; + ownerHasFunctionTypeWarning[componentName] = true; error( "Functions are not valid as a React child. This may happen if " + @@ -8461,7 +8475,7 @@ function ChildReconciler(shouldTrackSideEffects) { } childToDelete.nextEffect = null; - childToDelete.effectTag = Deletion; + childToDelete.flags = Deletion; } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -8525,7 +8539,7 @@ function ChildReconciler(shouldTrackSideEffects) { if (oldIndex < lastPlacedIndex) { // This is a move. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } else { // This item can stay in place. @@ -8533,7 +8547,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } else { // This is an insertion. - newFiber.effectTag = Placement; + newFiber.flags = Placement; return lastPlacedIndex; } } @@ -8542,20 +8556,16 @@ function ChildReconciler(shouldTrackSideEffects) { // This is simpler for the single child case. We only need to do a // placement for inserting new children. if (shouldTrackSideEffects && newFiber.alternate === null) { - newFiber.effectTag = Placement; + newFiber.flags = Placement; } return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (current === null || current.tag !== HostText) { // Insert - var created = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); created.return = returnFiber; return created; } else { @@ -8566,7 +8576,7 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (current !== null) { if ( current.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -8586,17 +8596,13 @@ function ChildReconciler(shouldTrackSideEffects) { } } // Insert - var created = createFiberFromElement( - element, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromElement(element, returnFiber.mode, lanes); created.ref = coerceRef(returnFiber, current, element); created.return = returnFiber; return created; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( current === null || current.tag !== HostPortal || @@ -8604,11 +8610,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) { // Insert - var created = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); created.return = returnFiber; return created; } else { @@ -8619,13 +8621,13 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (current === null || current.tag !== Fragment) { // Insert var created = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key ); created.return = returnFiber; @@ -8638,16 +8640,12 @@ function ChildReconciler(shouldTrackSideEffects) { } } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if (typeof newChild === "string" || typeof newChild === "number") { // Text nodes don't have keys. If the previous node is implicitly keyed // we can continue to replace it without aborting even if it is not a text // node. - var created = createFiberFromText( - "" + newChild, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText("" + newChild, returnFiber.mode, lanes); created.return = returnFiber; return created; } @@ -8658,7 +8656,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created = createFiberFromElement( newChild, returnFiber.mode, - expirationTime + lanes ); _created.ref = coerceRef(returnFiber, null, newChild); @@ -8670,7 +8668,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created2 = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); _created2.return = returnFiber; @@ -8682,7 +8680,7 @@ function ChildReconciler(shouldTrackSideEffects) { var _created3 = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null ); @@ -8695,14 +8693,14 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { // Update the fiber if the keys match, otherwise return null. var key = oldFiber !== null ? oldFiber.key : null; @@ -8714,12 +8712,7 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } - return updateTextNode( - returnFiber, - oldFiber, - "" + newChild, - expirationTime - ); + return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); } if (typeof newChild === "object" && newChild !== null) { @@ -8731,17 +8724,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ); } - return updateElement( - returnFiber, - oldFiber, - newChild, - expirationTime - ); + return updateElement(returnFiber, oldFiber, newChild, lanes); } else { return null; } @@ -8749,12 +8737,7 @@ function ChildReconciler(shouldTrackSideEffects) { case REACT_PORTAL_TYPE: { if (newChild.key === key) { - return updatePortal( - returnFiber, - oldFiber, - newChild, - expirationTime - ); + return updatePortal(returnFiber, oldFiber, newChild, lanes); } else { return null; } @@ -8766,13 +8749,7 @@ function ChildReconciler(shouldTrackSideEffects) { return null; } - return updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + return updateFragment(returnFiber, oldFiber, newChild, lanes, null); } throwOnInvalidObjectType(returnFiber, newChild); @@ -8780,7 +8757,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -8792,18 +8769,13 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if (typeof newChild === "string" || typeof newChild === "number") { // Text nodes don't have keys, so we neither have to check the old nor // new node for the key. If both are text nodes, they match. var matchedFiber = existingChildren.get(newIdx) || null; - return updateTextNode( - returnFiber, - matchedFiber, - "" + newChild, - expirationTime - ); + return updateTextNode(returnFiber, matchedFiber, "" + newChild, lanes); } if (typeof newChild === "object" && newChild !== null) { @@ -8819,17 +8791,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, _matchedFiber, newChild.props.children, - expirationTime, + lanes, newChild.key ); } - return updateElement( - returnFiber, - _matchedFiber, - newChild, - expirationTime - ); + return updateElement(returnFiber, _matchedFiber, newChild, lanes); } case REACT_PORTAL_TYPE: { @@ -8838,12 +8805,7 @@ function ChildReconciler(shouldTrackSideEffects) { newChild.key === null ? newIdx : newChild.key ) || null; - return updatePortal( - returnFiber, - _matchedFiber2, - newChild, - expirationTime - ); + return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); } } @@ -8854,7 +8816,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, _matchedFiber3, newChild, - expirationTime, + lanes, null ); } @@ -8864,7 +8826,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -8874,7 +8836,7 @@ function ChildReconciler(shouldTrackSideEffects) { * Warns if there is a duplicate or missing key */ - function warnOnInvalidKey(child, knownKeys) { + function warnOnInvalidKey(child, knownKeys, returnFiber) { { if (typeof child !== "object" || child === null) { return knownKeys; @@ -8883,7 +8845,7 @@ function ChildReconciler(shouldTrackSideEffects) { switch (child.$$typeof) { case REACT_ELEMENT_TYPE: case REACT_PORTAL_TYPE: - warnForMissingKey(child); + warnForMissingKey(child, returnFiber); var key = child.key; if (typeof key !== "string") { @@ -8921,7 +8883,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { // This algorithm can't optimize by searching from both ends since we // don't have backpointers on fibers. I'm trying to see how far we can get @@ -8944,7 +8906,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (var i = 0; i < newChildren.length; i++) { var child = newChildren[i]; - knownKeys = warnOnInvalidKey(child, knownKeys); + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } } @@ -8967,7 +8929,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (newFiber === null) { @@ -9017,11 +8979,7 @@ function ChildReconciler(shouldTrackSideEffects) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. for (; newIdx < newChildren.length; newIdx++) { - var _newFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - ); + var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); if (_newFiber === null) { continue; @@ -9050,7 +9008,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes ); if (_newFiber2 !== null) { @@ -9093,7 +9051,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { // This is the same implementation as reconcileChildrenArray(), // but using the iterator instead. @@ -9128,9 +9086,8 @@ function ChildReconciler(shouldTrackSideEffects) { if (newChildrenIterable.entries === iteratorFn) { if (!didWarnAboutMaps) { error( - "Using Maps as children is unsupported and will likely yield " + - "unexpected results. Convert it to a sequence/iterable of keyed " + - "ReactElements instead." + "Using Maps as children is not supported. " + + "Use an array of keyed ReactElements instead." ); } @@ -9147,7 +9104,7 @@ function ChildReconciler(shouldTrackSideEffects) { for (; !_step.done; _step = _newChildren.next()) { var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys); + knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); } } } @@ -9178,12 +9135,7 @@ function ChildReconciler(shouldTrackSideEffects) { nextOldFiber = oldFiber.sibling; } - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (newFiber === null) { // TODO: This breaks on empty slots like null children. That's @@ -9232,7 +9184,7 @@ function ChildReconciler(shouldTrackSideEffects) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. for (; !step.done; newIdx++, step = newChildren.next()) { - var _newFiber3 = createChild(returnFiber, step.value, expirationTime); + var _newFiber3 = createChild(returnFiber, step.value, lanes); if (_newFiber3 === null) { continue; @@ -9261,7 +9213,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, step.value, - expirationTime + lanes ); if (_newFiber4 !== null) { @@ -9304,7 +9256,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, textContent, - expirationTime + lanes ) { // There's no need to check for keys on text nodes since we don't have a // way to define them. @@ -9319,11 +9271,7 @@ function ChildReconciler(shouldTrackSideEffects) { // and delete the existing ones. deleteRemainingChildren(returnFiber, currentFirstChild); - var created = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromText(textContent, returnFiber.mode, lanes); created.return = returnFiber; return created; } @@ -9332,7 +9280,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, element, - expirationTime + lanes ) { var key = element.key; var child = currentFirstChild; @@ -9359,11 +9307,6 @@ function ChildReconciler(shouldTrackSideEffects) { break; } - case Block: - - // We intentionally fallthrough here if enableBlocksAPI is not on. - // eslint-disable-next-lined no-fallthrough - default: { if ( child.elementType === element.type || // Keep this check inline so it only runs on the false path: @@ -9371,17 +9314,17 @@ function ChildReconciler(shouldTrackSideEffects) { ) { deleteRemainingChildren(returnFiber, child.sibling); - var _existing3 = useFiber(child, element.props); + var _existing = useFiber(child, element.props); - _existing3.ref = coerceRef(returnFiber, child, element); - _existing3.return = returnFiber; + _existing.ref = coerceRef(returnFiber, child, element); + _existing.return = returnFiber; { - _existing3._debugSource = element._source; - _existing3._debugOwner = element._owner; + _existing._debugSource = element._source; + _existing._debugOwner = element._owner; } - return _existing3; + return _existing; } break; @@ -9401,17 +9344,13 @@ function ChildReconciler(shouldTrackSideEffects) { var created = createFiberFromFragment( element.props.children, returnFiber.mode, - expirationTime, + lanes, element.key ); created.return = returnFiber; return created; } else { - var _created4 = createFiberFromElement( - element, - returnFiber.mode, - expirationTime - ); + var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); _created4.ref = coerceRef(returnFiber, currentFirstChild, element); _created4.return = returnFiber; @@ -9423,7 +9362,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, portal, - expirationTime + lanes ) { var key = portal.key; var child = currentFirstChild; @@ -9452,11 +9391,7 @@ function ChildReconciler(shouldTrackSideEffects) { child = child.sibling; } - var created = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - ); + var created = createFiberFromPortal(portal, returnFiber.mode, lanes); created.return = returnFiber; return created; } // This API will tag the children with the side-effect of the reconciliation @@ -9467,7 +9402,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) { // This function is not recursive. // If the top level item is an array, we treat it as a set of children, @@ -9496,7 +9431,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) ); @@ -9506,7 +9441,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ) ); } @@ -9518,7 +9453,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, "" + newChild, - expirationTime + lanes ) ); } @@ -9528,7 +9463,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); } @@ -9537,7 +9472,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); } @@ -9547,7 +9482,7 @@ function ChildReconciler(shouldTrackSideEffects) { { if (typeof newChild === "function") { - warnOnFunctionType(); + warnOnFunctionType(returnFiber); } } @@ -9570,12 +9505,12 @@ function ChildReconciler(shouldTrackSideEffects) { // functions and classes // eslint-disable-next-lined no-fallthrough - case FunctionComponent: { - var Component = returnFiber.type; - + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { { throw Error( - (Component.displayName || Component.name || "Component") + + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." ); } @@ -9617,11 +9552,11 @@ function cloneChildFibers(current, workInProgress) { newChild.sibling = null; } // Reset a workInProgress child set to prepare it for a second pass. -function resetChildFibers(workInProgress, renderExpirationTime) { +function resetChildFibers(workInProgress, lanes) { var child = workInProgress.child; while (child !== null) { - resetWorkInProgress(child, renderExpirationTime); + resetWorkInProgress(child, lanes); child = child.sibling; } } @@ -9793,7 +9728,7 @@ function findFirstSuspended(row) { // keep track of whether it suspended or not. node.memoizedProps.revealOrder !== undefined ) { - var didSuspend = (node.effectTag & DidCapture) !== NoEffect; + var didSuspend = (node.flags & DidCapture) !== NoFlags; if (didSuspend) { return node; @@ -9823,18 +9758,9 @@ function findFirstSuspended(row) { return null; } -function createDeprecatedResponderListener(responder, props) { - var eventResponderListener = { - responder: responder, - props: props - }; - - { - Object.freeze(eventResponderListener); - } - - return eventResponderListener; -} +var NoFlags$1 = + /* */ + 0; // Represents whether effect should fire. var HasEffect = /* */ @@ -9847,16 +9773,113 @@ var Passive$1 = /* */ 4; -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var isHydrating = false; + +function enterHydrationState(fiber) { + { + return false; + } +} + +function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext +) { + { + { + throw Error( + "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + } +} + +function prepareToHydrateHostTextInstance(fiber) { + { + { + throw Error( + "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." + ); + } + } + var shouldUpdate = hydrateTextInstance(); +} + +function popHydrationState(fiber) { + { + return false; + } +} + +function getIsHydrating() { + return isHydrating; +} + +// and should be reset before starting a new render. +// This tracks which mutable sources need to be reset after a render. + +var workInProgressSources = []; +var rendererSigil$1; + +{ + // Used to detect multiple renderers using the same mutable source. + rendererSigil$1 = {}; +} + +function markSourceAsDirty(mutableSource) { + workInProgressSources.push(mutableSource); +} +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) { + var mutableSource = workInProgressSources[i]; + + { + mutableSource._workInProgressVersionPrimary = null; + } + } + + workInProgressSources.length = 0; +} +function getWorkInProgressVersion(mutableSource) { + { + return mutableSource._workInProgressVersionPrimary; + } +} +function setWorkInProgressVersion(mutableSource, version) { + { + mutableSource._workInProgressVersionPrimary = version; + } + + workInProgressSources.push(mutableSource); +} +function warnAboutMultipleRenderersDEV(mutableSource) { + { + { + if (mutableSource._currentPrimaryRenderer == null) { + mutableSource._currentPrimaryRenderer = rendererSigil$1; + } else if (mutableSource._currentPrimaryRenderer !== rendererSigil$1) { + error( + "Detected multiple renderers concurrently rendering the " + + "same mutable source. This is currently unsupported." + ); + } + } + } +} // Eager reads the version of a mutable source and stores it on the root. + +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; var didWarnAboutMismatchedHooksForComponent; +var didWarnAboutUseOpaqueIdentifier; { + didWarnAboutUseOpaqueIdentifier = {}; didWarnAboutMismatchedHooksForComponent = new Set(); } // These are set right before calling the component. -var renderExpirationTime = NoWork; // The work-in-progress fiber. I've named it differently to distinguish it from +var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from // the work-in-progress hook. var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The @@ -9870,7 +9893,12 @@ var workInProgressHook = null; // Whether an update was scheduled at any point d // finished evaluating this component. This is an optimization so we know // whether we need to clear render phase updates after a throw. -var didScheduleRenderPhaseUpdate = false; +var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This +// gets reset after each attempt. +// TODO: Maybe there's some way to consolidate this with +// `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. + +var didScheduleRenderPhaseUpdateDuringThisPass = false; var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. @@ -9954,7 +9982,7 @@ function warnOnHookMismatchInDev(currentHookName) { error( "React has detected a change in the order of Hooks called by %s. " + "This will lead to bugs and errors if not fixed. " + - "For more information, read the Rules of Hooks: https://fb.me/rules-of-hooks\n\n" + + "For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n" + " Previous render Next render\n" + " ------------------------------------------------------\n" + "%s" + @@ -9970,7 +9998,7 @@ function warnOnHookMismatchInDev(currentHookName) { function throwInvalidHookError() { { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } } @@ -10029,9 +10057,9 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; { @@ -10044,7 +10072,7 @@ function renderWithHooks( workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = NoWork; // The following should have already been reset + workInProgress.lanes = NoLanes; // The following should have already been reset // currentHook = null; // workInProgressHook = null; // didScheduleRenderPhaseUpdate = false; @@ -10057,28 +10085,28 @@ function renderWithHooks( { if (current !== null && current.memoizedState !== null) { - ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; } else if (hookTypesDev !== null) { // This dispatcher handles an edge case where a component is updating, // but no stateful hooks have been used. // We want to match the production code behavior (which will use HooksDispatcherOnMount), // but with the extra DEV validation to ensure hooks ordering hasn't changed. // This dispatcher does that. - ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountWithHookTypesInDEV; } else { - ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; } } var children = Component(props, secondArg); // Check if there was a render phase update - if (workInProgress.expirationTime === renderExpirationTime) { + if (didScheduleRenderPhaseUpdateDuringThisPass) { // Keep rendering in a loop for as long as render phase updates continue to // be scheduled. Use a counter to prevent infinite loops. var numberOfReRenders = 0; do { - workInProgress.expirationTime = NoWork; + didScheduleRenderPhaseUpdateDuringThisPass = false; if (!(numberOfReRenders < RE_RENDER_LIMIT)) { throw Error( @@ -10103,13 +10131,13 @@ function renderWithHooks( hookTypesUpdateIndexDev = -1; } - ReactCurrentDispatcher.current = HooksDispatcherOnRerenderInDEV; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV; children = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrancy. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; { workInProgress._debugHookTypes = hookTypesDev; @@ -10117,7 +10145,7 @@ function renderWithHooks( // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; - renderExpirationTime = NoWork; + renderLanes = NoLanes; currentlyRenderingFiber$1 = null; currentHook = null; workInProgressHook = null; @@ -10138,18 +10166,15 @@ function renderWithHooks( return children; } -function bailoutHooks(current, workInProgress, expirationTime) { +function bailoutHooks(current, workInProgress, lanes) { workInProgress.updateQueue = current.updateQueue; - workInProgress.effectTag &= ~(Passive | Update); - - if (current.expirationTime <= expirationTime) { - current.expirationTime = NoWork; - } + workInProgress.flags &= ~(Passive | Update); + current.lanes = removeLanes(current.lanes, lanes); } function resetHooksAfterThrow() { // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrancy. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; if (didScheduleRenderPhaseUpdate) { // There were render phase updates. These are only valid for this render @@ -10171,9 +10196,11 @@ function resetHooksAfterThrow() { hook = hook.next; } + + didScheduleRenderPhaseUpdate = false; } - renderExpirationTime = NoWork; + renderLanes = NoLanes; currentlyRenderingFiber$1 = null; currentHook = null; workInProgressHook = null; @@ -10182,9 +10209,10 @@ function resetHooksAfterThrow() { hookTypesDev = null; hookTypesUpdateIndexDev = -1; currentHookNameInDev = null; + isUpdatingOpaqueValueInRenderPhase = false; } - didScheduleRenderPhaseUpdate = false; + didScheduleRenderPhaseUpdateDuringThisPass = false; } function mountWorkInProgressHook() { @@ -10331,6 +10359,17 @@ function updateReducer(reducer, initialArg, init) { pendingQueue.next = baseFirst; } + { + if (current.baseQueue !== baseQueue) { + // Internal invariant that should never happen, but feasibly could in + // the future if we implement resuming, or some form of that. + error( + "Internal error: Expected work-in-progress queue to be a clone. " + + "This is a bug in React." + ); + } + } + current.baseQueue = baseQueue = pendingQueue; queue.pending = null; } @@ -10345,15 +10384,14 @@ function updateReducer(reducer, initialArg, init) { var update = first; do { - var updateExpirationTime = update.expirationTime; + var updateLane = update.lane; - if (updateExpirationTime < renderExpirationTime) { + if (!isSubsetOfLanes(renderLanes, updateLane)) { // Priority is insufficient. Skip this update. If this is the first // skipped update, the previous update/state is the new base // update/state. var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, + lane: updateLane, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, @@ -10366,35 +10404,29 @@ function updateReducer(reducer, initialArg, init) { } else { newBaseQueueLast = newBaseQueueLast.next = clone; } // Update the remaining priority in the queue. + // TODO: Don't need to accumulate this. Instead, we can remove + // renderLanes from the original lanes. - if (updateExpirationTime > currentlyRenderingFiber$1.expirationTime) { - currentlyRenderingFiber$1.expirationTime = updateExpirationTime; - markUnprocessedUpdateTime(updateExpirationTime); - } + currentlyRenderingFiber$1.lanes = mergeLanes( + currentlyRenderingFiber$1.lanes, + updateLane + ); + markSkippedUpdateLanes(updateLane); } else { // This update does have sufficient priority. if (newBaseQueueLast !== null) { var _clone = { - expirationTime: Sync, - // This update is going to be committed so we never want uncommit it. - suspenseConfig: update.suspenseConfig, + // This update is going to be committed so we never want uncommit + // it. Using NoLane works because 0 is a subset of all bitmasks, so + // this will never be skipped by the check above. + lane: NoLane, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }; newBaseQueueLast = newBaseQueueLast.next = _clone; - } // Mark the event time of this update as relevant to this render pass. - // TODO: This should ideally use the true event time of this update rather than - // its priority which is a derived and not reverseable value. - // TODO: We should skip this update if it was already committed but currently - // we have no way of detecting the difference between a committed and suspended - // update here. - - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ); // Process this update. + } // Process this update. if (update.eagerReducer === reducer) { // If this update was processed eagerly, and its reducer matches the @@ -10482,6 +10514,251 @@ function rerenderReducer(reducer, initialArg, init) { return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + { + warnAboutMultipleRenderersDEV(source); + } + + var getVersion = source._getVersion; + var version = getVersion(source._source); // Is it safe for this component to read from this source during the current render? + + var isSafeToReadFromSource = false; // Check the version first. + // If this render has already been started with a specific version, + // we can use it alone to determine if we can safely read from the source. + + var currentRenderVersion = getWorkInProgressVersion(source); + + if (currentRenderVersion !== null) { + // It's safe to read if the store hasn't been mutated since the last time + // we read something. + isSafeToReadFromSource = currentRenderVersion === version; + } else { + // If there's no version, then this is the first time we've read from the + // source during the current render pass, so we need to do a bit more work. + // What we need to determine is if there are any hooks that already + // subscribed to the source, and if so, whether there are any pending + // mutations that haven't been synchronized yet. + // + // If there are no pending mutations, then `root.mutableReadLanes` will be + // empty, and we know we can safely read. + // + // If there *are* pending mutations, we may still be able to safely read + // if the currently rendering lanes are inclusive of the pending mutation + // lanes, since that guarantees that the value we're about to read from + // the source is consistent with the values that we read during the most + // recent mutation. + isSafeToReadFromSource = isSubsetOfLanes( + renderLanes, + root.mutableReadLanes + ); + + if (isSafeToReadFromSource) { + // If it's safe to read from this source during the current render, + // store the version in case other components read from it. + // A changed version number will let those components know to throw and restart the render. + setWorkInProgressVersion(source, version); + } + } + + if (isSafeToReadFromSource) { + var snapshot = getSnapshot(source._source); + + { + if (typeof snapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } + } + + return snapshot; + } else { + // This handles the special case of a mutable source being shared between renderers. + // In that case, if the source is mutated between the first and second renderer, + // The second renderer don't know that it needs to reset the WIP version during unwind, + // (because the hook only marks sources as dirty if it's written to their WIP version). + // That would cause this tear check to throw again and eventually be visible to the user. + // We can avoid this infinite loop by explicitly marking the source as dirty. + // + // This can lead to tearing in the first renderer when it resumes, + // but there's nothing we can do about that (short of throwing here and refusing to continue the render). + markSourceAsDirty(source); + + { + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); + } + } +} + +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = getWorkInProgressRoot(); + + if (!(root !== null)) { + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + } + + var getVersion = source._getVersion; + var version = getVersion(source._source); + var dispatcher = ReactCurrentDispatcher$1.current; // eslint-disable-next-line prefer-const + + var _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + currentSnapshot = _dispatcher$useState[0], + setSnapshot = _dispatcher$useState[1]; + + var snapshot = currentSnapshot; // Grab a handle to the state hook as well. + // We use it to clear the pending update queue if we have a new source. + + var stateHook = workInProgressHook; + var memoizedState = hook.memoizedState; + var refs = memoizedState.refs; + var prevGetSnapshot = refs.getSnapshot; + var prevSource = memoizedState.source; + var prevSubscribe = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { + refs: refs, + source: source, + subscribe: subscribe + }; // Sync the values needed by our subscription handler after each commit. + + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; // Normally the dispatch function for a state hook never changes, + // but this hook recreates the queue in certain cases to avoid updates from stale sources. + // handleChange() below needs to reference the dispatch function without re-subscribing, + // so we use a ref to ensure that it always has the latest version. + + refs.setSnapshot = setSnapshot; // Check for a possible change between when we last rendered now. + + var maybeNewVersion = getVersion(source._source); + + if (!objectIs(version, maybeNewVersion)) { + var maybeNewSnapshot = getSnapshot(source._source); + + { + if (typeof maybeNewSnapshot === "function") { + error( + "Mutable source should not return a function as the snapshot value. " + + "Functions may close over mutable values and cause tearing." + ); + } + } + + if (!objectIs(snapshot, maybeNewSnapshot)) { + setSnapshot(maybeNewSnapshot); + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } // If the source mutated between render and now, + // there may be state updates already scheduled from the old source. + // Entangle the updates so that they render in the same batch. + + markRootEntangled(root, root.mutableReadLanes); + } + }, + [getSnapshot, source, subscribe] + ); // If we got a new source or subscribe function, re-subscribe in a passive effect. + + dispatcher.useEffect( + function() { + var handleChange = function() { + var latestGetSnapshot = refs.getSnapshot; + var latestSetSnapshot = refs.setSnapshot; + + try { + latestSetSnapshot(latestGetSnapshot(source._source)); // Record a pending mutable source update with the same expiration time. + + var lane = requestUpdateLane(fiber); + markRootMutableRead(root, lane); + } catch (error) { + // A selector might throw after a source mutation. + // e.g. it might try to read from a part of the store that no longer exists. + // In this case we should still schedule an update with React. + // Worst case the selector will throw again and then an error boundary will handle it. + latestSetSnapshot(function() { + throw error; + }); + } + }; + + var unsubscribe = subscribe(source._source, handleChange); + + { + if (typeof unsubscribe !== "function") { + error( + "Mutable source subscribe function must return an unsubscribe function." + ); + } + } + + return unsubscribe; + }, + [source, subscribe] + ); // If any of the inputs to useMutableSource change, reading is potentially unsafe. + // + // If either the source or the subscription have changed we can't can't trust the update queue. + // Maybe the source changed in a way that the old subscription ignored but the new one depends on. + // + // If the getSnapshot function changed, we also shouldn't rely on the update queue. + // It's possible that the underlying source was mutated between the when the last "change" event fired, + // and when the current render (with the new getSnapshot function) is processed. + // + // In both cases, we need to throw away pending updates (since they are no longer relevant) + // and treat reading from the source as we do in the mount case. + + if ( + !objectIs(prevGetSnapshot, getSnapshot) || + !objectIs(prevSource, source) || + !objectIs(prevSubscribe, subscribe) + ) { + // Create a new queue and setState method, + // So if there are interleaved updates, they get pushed to the older queue. + // When this becomes current, the previous queue and dispatch method will be discarded, + // including any interleaving updates that occur. + var newQueue = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }; + newQueue.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + newQueue + ); + stateHook.queue = newQueue; + stateHook.baseQueue = null; + snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot); + stateHook.memoizedState = stateHook.baseState = snapshot; + } + + return snapshot; +} + +function mountMutableSource(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { + getSnapshot: getSnapshot, + setSnapshot: null + }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); +} + +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} + function mountState(initialState) { var hook = mountWorkInProgressHook(); @@ -10546,16 +10823,14 @@ function pushEffect(tag, create, destroy, deps) { function mountRef(initialValue) { var hook = mountWorkInProgressHook(); - var ref = { - current: initialValue - }; { - Object.seal(ref); + var _ref2 = { + current: initialValue + }; + hook.memoizedState = _ref2; + return _ref2; } - - hook.memoizedState = ref; - return ref; } function updateRef(initialValue) { @@ -10563,19 +10838,19 @@ function updateRef(initialValue) { return hook.memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, undefined, nextDeps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); var nextDeps = deps === undefined ? null : deps; var destroy = undefined; @@ -10588,15 +10863,15 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { - pushEffect(hookEffectTag, create, destroy, nextDeps); + pushEffect(hookFlags, create, destroy, nextDeps); return; } } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - HasEffect | hookEffectTag, + HasEffect | hookFlags, create, destroy, nextDeps @@ -10770,129 +11045,175 @@ function updateMemo(nextCreate, deps) { return nextValue; } -function mountDeferredValue(value, config) { +function mountDeferredValue(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function updateDeferredValue(value, config) { +function updateDeferredValue(value) { var _updateState = updateState(), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function rerenderDeferredValue(value, config) { +function rerenderDeferredValue(value) { var _rerenderState = rerenderState(), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); - runWithPriority( - priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel, - function() { - setPending(true); - } - ); - runWithPriority( - priorityLevel > NormalPriority ? NormalPriority : priorityLevel, - function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + { + runWithPriority( + priorityLevel < UserBlockingPriority$1 + ? UserBlockingPriority$1 + : priorityLevel, + function() { + setPending(true); + } + ); + runWithPriority( + priorityLevel > NormalPriority$1 ? NormalPriority$1 : priorityLevel, + function() { + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; + + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig$1.transition = prevTransition; + } } - } - ); + ); + } } -function mountTransition(config) { +function mountTransition() { var _mountState2 = mountState(false), isPending = _mountState2[0], - setPending = _mountState2[1]; + setPending = _mountState2[1]; // The `start` method never changes. - var start = mountCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var start = startTransition.bind(null, setPending); + var hook = mountWorkInProgressHook(); + hook.memoizedState = start; return [start, isPending]; } -function updateTransition(config) { +function updateTransition() { var _updateState2 = updateState(), - isPending = _updateState2[0], - setPending = _updateState2[1]; + isPending = _updateState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } -function rerenderTransition(config) { +function rerenderTransition() { var _rerenderState2 = rerenderState(), - isPending = _rerenderState2[0], - setPending = _rerenderState2[1]; + isPending = _rerenderState2[0]; - var start = updateCallback(startTransition.bind(null, setPending, config), [ - setPending, - config - ]); + var hook = updateWorkInProgressHook(); + var start = hook.memoizedState; return [start, isPending]; } +var isUpdatingOpaqueValueInRenderPhase = false; +function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { + { + return isUpdatingOpaqueValueInRenderPhase; + } +} + +function warnOnOpaqueIdentifierAccessInDEV(fiber) { + { + // TODO: Should warn in effects and callbacks, too + var name = getComponentName(fiber.type) || "Unknown"; + + if (getIsRendering() && !didWarnAboutUseOpaqueIdentifier[name]) { + error( + "The object passed back from useOpaqueIdentifier is meant to be " + + "passed through to attributes only. Do not read the " + + "value directly." + ); + + didWarnAboutUseOpaqueIdentifier[name] = true; + } + } +} + +function mountOpaqueIdentifier() { + var makeId = makeClientIdInDEV.bind( + null, + warnOnOpaqueIdentifierAccessInDEV.bind(null, currentlyRenderingFiber$1) + ); + + { + var _id = makeId(); + + mountState(_id); + return _id; + } +} + +function updateOpaqueIdentifier() { + var id = updateState()[0]; + return id; +} + +function rerenderOpaqueIdentifier() { + var id = rerenderState()[0]; + return id; +} + function dispatchAction(fiber, queue, action) { { if (typeof arguments[3] === "function") { @@ -10904,25 +11225,15 @@ function dispatchAction(fiber, queue, action) { } } - var currentTime = requestCurrentTimeForUpdate(); - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - fiber, - suspenseConfig - ); + var eventTime = requestEventTime(); + var lane = requestUpdateLane(fiber); var update = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, + lane: lane, action: action, eagerReducer: null, eagerState: null, next: null - }; - - { - update.priority = getCurrentPriorityLevel(); - } // Append the update to the end of the list. + }; // Append the update to the end of the list. var pending = queue.pending; @@ -10944,13 +11255,11 @@ function dispatchAction(fiber, queue, action) { // This is a render phase update. Stash it in a lazily-created map of // queue -> linked list of updates. After this render pass, we'll restart // and apply the stashed updates on top of the work-in-progress hook. - didScheduleRenderPhaseUpdate = true; - update.expirationTime = renderExpirationTime; - currentlyRenderingFiber$1.expirationTime = renderExpirationTime; + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; } else { if ( - fiber.expirationTime === NoWork && - (alternate === null || alternate.expirationTime === NoWork) + fiber.lanes === NoLanes && + (alternate === null || alternate.lanes === NoLanes) ) { // The queue is currently empty, which means we can eagerly compute the // next state before entering the render phase. If the new state is the @@ -10961,8 +11270,8 @@ function dispatchAction(fiber, queue, action) { var prevDispatcher; { - prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; } try { @@ -10986,7 +11295,7 @@ function dispatchAction(fiber, queue, action) { // Suppress the error. It will throw again in the render phase. } finally { { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } } } @@ -11000,18 +11309,10 @@ function dispatchAction(fiber, queue, action) { } } - scheduleWork(fiber, expirationTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function mountEventListener(event) { - return undefined; -} - -function updateEventListener(event) { - return undefined; -} - var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -11024,10 +11325,11 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: enableNewReconciler }; var HooksDispatcherOnMountInDEV = null; var HooksDispatcherOnMountWithHookTypesInDEV = null; @@ -11052,7 +11354,7 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; "Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. " + "You can only call Hooks at the top level of your React function. " + "For more information, see " + - "https://fb.me/rules-of-hooks" + "https://reactjs.org/link/rules-of-hooks" ); }; @@ -11093,25 +11395,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; mountHookTypesDev(); checkDepsAreArrayDev(deps); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11122,13 +11424,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11136,26 +11438,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - mountHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; mountHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; mountHookTypesDev(); - return mountEventListener(); - } + return mountMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + mountHookTypesDev(); + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnMountWithHookTypesInDEV = { readContext: function(context, observedBits) { @@ -11189,25 +11492,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11218,13 +11521,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11232,26 +11535,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return mountDeferredValue(value, config); + return mountDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return mountTransition(config); + return mountTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return mountEventListener(); - } + return mountMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnUpdateInDEV = { readContext: function(context, observedBits) { @@ -11285,25 +11589,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11314,13 +11618,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11328,26 +11632,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return updateTransition(config); + return updateTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return updateEventListener(); - } + return updateMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return updateOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; HooksDispatcherOnRerenderInDEV = { readContext: function(context, observedBits) { @@ -11381,25 +11686,25 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useMemo: function(create, deps) { currentHookNameInDev = "useMemo"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11410,13 +11715,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; useState: function(initialState) { currentHookNameInDev = "useState"; updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnRerenderInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11424,26 +11729,27 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; - updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); - }, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { currentHookNameInDev = "useDeferredValue"; updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderDeferredValue(value); }, - useTransition: function(config) { + useTransition: function() { currentHookNameInDev = "useTransition"; updateHookTypesDev(); - return rerenderTransition(config); + return rerenderTransition(); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; updateHookTypesDev(); - return updateEventListener(); - } + return updateMutableSource(source, getSnapshot, subscribe); + }, + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; + updateHookTypesDev(); + return rerenderOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnMountInDEV = { readContext: function(context, observedBits) { @@ -11484,26 +11790,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11516,13 +11822,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); mountHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11531,30 +11837,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; mountHookTypesDev(); return mountDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); mountHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return mountDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountDeferredValue(value, config); + return mountTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountTransition(config); + return mountMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); mountHookTypesDev(); - return mountEventListener(); - } + return mountOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnUpdateInDEV = { readContext: function(context, observedBits) { @@ -11595,26 +11902,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11627,13 +11934,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11642,30 +11949,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return updateDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateDeferredValue(value, config); + return updateTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateTransition(config); + return updateMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateEventListener(); - } + return updateOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; InvalidNestedHooksDispatcherOnRerenderInDEV = { readContext: function(context, observedBits) { @@ -11706,26 +12014,26 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useMemo"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useReducer: function(reducer, initialArg, init) { currentHookNameInDev = "useReducer"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useRef: function(initialValue) { @@ -11738,13 +12046,13 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; currentHookNameInDev = "useState"; warnInvalidHookAccess(); updateHookTypesDev(); - var prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV; + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactCurrentDispatcher$1.current = prevDispatcher; } }, useDebugValue: function(value, formatterFn) { @@ -11753,30 +12061,31 @@ var InvalidNestedHooksDispatcherOnRerenderInDEV = null; updateHookTypesDev(); return updateDebugValue(); }, - useResponder: function(responder, props) { - currentHookNameInDev = "useResponder"; + useDeferredValue: function(value) { + currentHookNameInDev = "useDeferredValue"; warnInvalidHookAccess(); updateHookTypesDev(); - return createDeprecatedResponderListener(responder, props); + return rerenderDeferredValue(value); }, - useDeferredValue: function(value, config) { - currentHookNameInDev = "useDeferredValue"; + useTransition: function() { + currentHookNameInDev = "useTransition"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderDeferredValue(value, config); + return rerenderTransition(); }, - useTransition: function(config) { - currentHookNameInDev = "useTransition"; + useMutableSource: function(source, getSnapshot, subscribe) { + currentHookNameInDev = "useMutableSource"; warnInvalidHookAccess(); updateHookTypesDev(); - return rerenderTransition(config); + return updateMutableSource(source, getSnapshot, subscribe); }, - useEvent: function(event) { - currentHookNameInDev = "useEvent"; + useOpaqueIdentifier: function() { + currentHookNameInDev = "useOpaqueIdentifier"; warnInvalidHookAccess(); updateHookTypesDev(); - return updateEventListener(); - } + return rerenderOpaqueIdentifier(); + }, + unstable_isNewReconciler: enableNewReconciler }; } @@ -11817,40 +12126,15 @@ function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { } } -function enterHydrationState(fiber) { - { - return false; - } -} - -function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext -) { - { - { - throw Error( - "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." - ); - } - } -} - -function prepareToHydrateHostTextInstance(fiber) { - { - { - throw Error( - "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue." - ); - } - } - var shouldUpdate = hydrateTextInstance(); -} +function transferActualDuration(fiber) { + // Transfer time spent rendering these children so we don't lose it + // after we rerender. This is used as a helper in special cases + // where we should count the work of multiple passes. + var child = fiber.child; -function popHydrationState(fiber) { - { - return false; + while (child) { + fiber.actualDuration += child.actualDuration; + child = child.sibling; } } @@ -11876,12 +12160,7 @@ var didWarnAboutTailOptions; didWarnAboutTailOptions = {}; } -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { if (current === null) { // If this is a fresh new component that hasn't been rendered yet, we // won't update its child set by applying minimal side-effects. Instead, @@ -11891,7 +12170,7 @@ function reconcileChildren( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } else { // If the current child is the same as the work in progress, it means that @@ -11903,7 +12182,7 @@ function reconcileChildren( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } } @@ -11912,7 +12191,7 @@ function forceUnmountCurrentAndReconcile( current, workInProgress, nextChildren, - renderExpirationTime + renderLanes ) { // This function is fork of reconcileChildren. It's used in cases where we // want to reconcile without matching against the existing set. This has the @@ -11926,7 +12205,7 @@ function forceUnmountCurrentAndReconcile( workInProgress, current.child, null, - renderExpirationTime + renderLanes ); // In the second pass, we mount the new children. The trick here is that we // pass null in place of where we usually pass the current child set. This has // the effect of remounting all children regardless of whether their @@ -11936,7 +12215,7 @@ function forceUnmountCurrentAndReconcile( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } @@ -11945,7 +12224,7 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { // TODO: current can be non-null here even if the component // hasn't yet mounted. This happens after the first render suspends. @@ -11971,7 +12250,7 @@ function updateForwardRef( var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent var nextChildren; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); { ReactCurrentOwner$1.current = workInProgress; @@ -11982,28 +12261,19 @@ function updateForwardRef( render, nextProps, ref, - renderExpirationTime + renderLanes ); setIsRendering(false); } if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderExpirationTime); - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12012,8 +12282,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (current === null) { var type = Component.type; @@ -12043,8 +12313,8 @@ function updateMemoComponent( workInProgress, resolvedType, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -12067,9 +12337,9 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); child.ref = workInProgress.ref; child.return = workInProgress; @@ -12095,7 +12365,7 @@ function updateMemoComponent( var currentChild = current.child; // This is always exactly one child - if (updateExpirationTime < renderExpirationTime) { + if (!includesSomeLane(updateLanes, renderLanes)) { // This will be the props with resolved defaultProps, // unlike current.memoizedProps which will be the unresolved ones. var prevProps = currentChild.memoizedProps; // Default to shallow comparison @@ -12104,15 +12374,11 @@ function updateMemoComponent( compare = compare !== null ? compare : shallowEqual; if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; var newChild = createWorkInProgress(currentChild, nextProps); newChild.ref = workInProgress.ref; newChild.return = workInProgress; @@ -12125,8 +12391,8 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { // TODO: current can be non-null here even if the component // hasn't yet mounted. This happens when the inner render suspends. @@ -12141,19 +12407,27 @@ function updateSimpleMemoComponent( // We warn when you define propTypes on lazy() // so let's just skip over it to find memo() outer wrapper. // Inner props for memo are validated later. - outerMemoType = refineResolvedLazyComponent(outerMemoType); - } + var lazyComponent = outerMemoType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; - var outerPropTypes = outerMemoType && outerMemoType.propTypes; - - if (outerPropTypes) { - checkPropTypes( - outerPropTypes, - nextProps, // Resolved (SimpleMemoComponent has no defaultProps) - "prop", - getComponentName(outerMemoType) - ); - } // Inner propTypes will be validated in the function component path. + try { + outerMemoType = init(payload); + } catch (x) { + outerMemoType = null; + } // Inner propTypes will be validated in the function component path. + + var outerPropTypes = outerMemoType && outerMemoType.propTypes; + + if (outerPropTypes) { + checkPropTypes( + outerPropTypes, + nextProps, // Resolved (SimpleMemoComponent has no defaultProps) + "prop", + getComponentName(outerMemoType) + ); + } + } } } @@ -12167,10 +12441,10 @@ function updateSimpleMemoComponent( ) { didReceiveUpdate = false; - if (updateExpirationTime < renderExpirationTime) { - // The pending update priority was cleared at the beginning of - // beginWork. We're about to bail out, but there might be additional - // updates at a lower priority. Usually, the priority level of the + if (!includesSomeLane(renderLanes, updateLanes)) { + // The pending lanes were cleared at the beginning of beginWork. We're + // about to bail out, but there might be other lanes that weren't + // included in the current render. Usually, the priority level of the // remaining updates is accumlated during the evaluation of the // component (i.e. when processing the update queue). But since since // we're bailing out early *without* evaluating the component, we need @@ -12181,12 +12455,16 @@ function updateSimpleMemoComponent( // contains hooks. // TODO: Move the reset at in beginWork out of the common path so that // this is no longer necessary. - workInProgress.expirationTime = current.expirationTime; + workInProgress.lanes = current.lanes; return bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); + } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; } } } @@ -12196,35 +12474,103 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } -function updateFragment(current, workInProgress, renderExpirationTime) { +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + var prevState = current !== null ? current.memoizedState : null; + + if ( + nextProps.mode === "hidden" || + nextProps.mode === "unstable-defer-without-hiding" + ) { + if ((workInProgress.mode & ConcurrentMode) === NoMode) { + // In legacy sync mode, don't defer the subtree. Render it now. + // TODO: Figure out what we should do in Blocking mode. + var nextState = { + baseLanes: NoLanes + }; + workInProgress.memoizedState = nextState; + pushRenderLanes(workInProgress, renderLanes); + } else if (!includesSomeLane(renderLanes, OffscreenLane)) { + var nextBaseLanes; + + if (prevState !== null) { + var prevBaseLanes = prevState.baseLanes; + nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); + } else { + nextBaseLanes = renderLanes; + } // Schedule this fiber to re-render at offscreen priority. Then bailout. + + { + markSpawnedWork(OffscreenLane); + } + + workInProgress.lanes = workInProgress.childLanes = laneToLanes( + OffscreenLane + ); + var _nextState = { + baseLanes: nextBaseLanes + }; + workInProgress.memoizedState = _nextState; // We're about to bail out, but we need to push this to the stack anyway + // to avoid a push/pop misalignment. + + pushRenderLanes(workInProgress, nextBaseLanes); + return null; + } else { + // Rendering at offscreen, so we can clear the base lanes. + var _nextState2 = { + baseLanes: NoLanes + }; + workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. + + var subtreeRenderLanes = + prevState !== null ? prevState.baseLanes : renderLanes; + pushRenderLanes(workInProgress, subtreeRenderLanes); + } + } else { + var _subtreeRenderLanes; + + if (prevState !== null) { + _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); // Since we're not hidden anymore, reset the state + + workInProgress.memoizedState = null; + } else { + // We weren't previously hidden, and we still aren't, so there's nothing + // special to do. Need to push to the stack regardless, though, to avoid + // a push/pop misalignment. + _subtreeRenderLanes = renderLanes; + } + + pushRenderLanes(workInProgress, _subtreeRenderLanes); + } + + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; +} // Note: These happen to have identical begin phases, for now. We shouldn't hold +// ourselves to this constraint, though. If the behavior diverges, we should +// fork the function. + +var updateLegacyHiddenComponent = updateOffscreenComponent; + +function updateFragment(current, workInProgress, renderLanes) { var nextChildren = workInProgress.pendingProps; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function updateMode(current, workInProgress, renderExpirationTime) { +function updateMode(current, workInProgress, renderLanes) { var nextChildren = workInProgress.pendingProps.children; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } -function updateProfiler(current, workInProgress, renderExpirationTime) { +function updateProfiler(current, workInProgress, renderLanes) { { - workInProgress.effectTag |= Update; // Reset effect durations for the next eventual effect phase. + workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, var stateNode = workInProgress.stateNode; @@ -12234,12 +12580,7 @@ function updateProfiler(current, workInProgress, renderExpirationTime) { var nextProps = workInProgress.pendingProps; var nextChildren = nextProps.children; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12251,7 +12592,7 @@ function markRef(current, workInProgress) { (current !== null && current.ref !== ref) ) { // Schedule a Ref effect - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } } @@ -12260,7 +12601,7 @@ function updateFunctionComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { { if (workInProgress.type !== workInProgress.elementType) { @@ -12287,7 +12628,7 @@ function updateFunctionComponent( } var nextChildren; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); { ReactCurrentOwner$1.current = workInProgress; @@ -12298,28 +12639,19 @@ function updateFunctionComponent( Component, nextProps, context, - renderExpirationTime + renderLanes ); setIsRendering(false); } if (current !== null && !didReceiveUpdate) { - bailoutHooks(current, workInProgress, renderExpirationTime); - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + bailoutHooks(current, workInProgress, renderLanes); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12328,7 +12660,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { { if (workInProgress.type !== workInProgress.elementType) { @@ -12358,7 +12690,7 @@ function updateClassComponent( hasContext = false; } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var instance = workInProgress.stateNode; var shouldUpdate; @@ -12371,16 +12703,11 @@ function updateClassComponent( current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // In the initial pass we might need to construct the instance. constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); shouldUpdate = true; } else if (current === null) { // In a resume, we'll already have an instance we can reuse. @@ -12388,7 +12715,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } else { shouldUpdate = updateClassInstance( @@ -12396,7 +12723,7 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ); } @@ -12406,13 +12733,13 @@ function updateClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ); { var inst = workInProgress.stateNode; - if (inst.props !== nextProps) { + if (shouldUpdate && inst.props !== nextProps) { if (!didWarnAboutReassigningProps) { error( "It looks like %s is reassigning its own `this.props` while rendering. " + @@ -12434,11 +12761,11 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { // Refs should update even if shouldComponentUpdate returns false markRef(current, workInProgress); - var didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect; + var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; if (!shouldUpdate && !didCaptureError) { // Context providers should defer to sCU for rendering @@ -12446,11 +12773,7 @@ function finishClassComponent( invalidateContextProvider(workInProgress, Component, false); } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } var instance = workInProgress.stateNode; // Rerender @@ -12481,7 +12804,7 @@ function finishClassComponent( } } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; if (current !== null && didCaptureError) { // If we're recovering from an error, reconcile without reusing any of @@ -12492,15 +12815,10 @@ function finishClassComponent( current, workInProgress, nextChildren, - renderExpirationTime + renderLanes ); } else { - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } // Memoize state using the values we just used to render. // TODO: Restructure so we never read values from the instance. @@ -12530,7 +12848,7 @@ function pushHostRootContext(workInProgress) { pushHostContainer(workInProgress, root.containerInfo); } -function updateHostRoot(current, workInProgress, renderExpirationTime) { +function updateHostRoot(current, workInProgress, renderLanes) { pushHostRootContext(workInProgress); var updateQueue = workInProgress.updateQueue; @@ -12544,32 +12862,24 @@ function updateHostRoot(current, workInProgress, renderExpirationTime) { var prevState = workInProgress.memoizedState; var prevChildren = prevState !== null ? prevState.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue(workInProgress, nextProps, null, renderExpirationTime); + processUpdateQueue(workInProgress, nextProps, null, renderLanes); var nextState = workInProgress.memoizedState; // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; if (nextChildren === prevChildren) { - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } var root = workInProgress.stateNode; if (root.hydrate && enterHydrationState()) { - // If we don't have any current children this might be the first pass. - // We always try to hydrate. If this isn't a hydration pass there won't - // be any children to hydrate which is effectively the same thing as - // not hydrating. var child = mountChildFibers( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); workInProgress.child = child; var node = child; @@ -12581,24 +12891,19 @@ function updateHostRoot(current, workInProgress, renderExpirationTime) { // Conceptually this is similar to Placement in that a new subtree is // inserted into the React tree here. It just happens to not need DOM // mutations because it already exists. - node.effectTag = (node.effectTag & ~Placement) | Hydrating; + node.flags = (node.flags & ~Placement) | Hydrating; node = node.sibling; } } else { // Otherwise reset hydration state in case we aborted and resumed another // root. - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } return workInProgress.child; } -function updateHostComponent(current, workInProgress, renderExpirationTime) { +function updateHostComponent(current, workInProgress, renderLanes) { pushHostContext(workInProgress); var type = workInProgress.type; @@ -12609,30 +12914,11 @@ function updateHostComponent(current, workInProgress, renderExpirationTime) { if (prevProps !== null && shouldSetTextContent()) { // If we're switching from a direct text child to a normal child, or to // empty, we need to schedule the text content to be reset. - workInProgress.effectTag |= ContentReset; - } - - markRef(current, workInProgress); // Check the host config to see if the children are offscreen/hidden. - - if ( - workInProgress.mode & ConcurrentMode && - renderExpirationTime !== Never && - shouldDeprioritizeSubtree() - ) { - { - markSpawnedWork(Never); - } // Schedule this fiber to re-render at offscreen priority. Then bailout. - - workInProgress.expirationTime = workInProgress.childExpirationTime = Never; - return null; + workInProgress.flags |= ContentReset; } - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); return workInProgress.child; } @@ -12646,8 +12932,8 @@ function mountLazyComponent( _current, workInProgress, elementType, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (_current !== null) { // A lazy component only mounts if it suspended inside a non- @@ -12657,18 +12943,17 @@ function mountLazyComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } - var props = workInProgress.pendingProps; // We can't start a User Timing measurement with correct label yet. - // Cancel and resume right after we know the tag. - - cancelWorkTimer(workInProgress); - var Component = readLazyComponentType(elementType); // Store the unwrapped component in the type. + var props = workInProgress.pendingProps; + var lazyComponent = elementType; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); // Store the unwrapped component in the type. workInProgress.type = Component; var resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - startWorkTimer(workInProgress); var resolvedProps = resolveDefaultProps(Component, props); var child; @@ -12686,7 +12971,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12703,7 +12988,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12720,7 +13005,7 @@ function mountLazyComponent( workInProgress, Component, resolvedProps, - renderExpirationTime + renderLanes ); return child; } @@ -12746,8 +13031,8 @@ function mountLazyComponent( workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); return child; } @@ -12782,7 +13067,7 @@ function mountIncompleteClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (_current !== null) { // An incomplete component only mounts if it suspended inside a non- @@ -12792,7 +13077,7 @@ function mountIncompleteClassComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } // Promote the fiber to a class and try rendering again. workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` @@ -12809,21 +13094,16 @@ function mountIncompleteClassComponent( hasContext = false; } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); constructClassInstance(workInProgress, Component, nextProps); - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ); + mountClassInstance(workInProgress, Component, nextProps, renderLanes); return finishClassComponent( null, workInProgress, Component, true, hasContext, - renderExpirationTime + renderLanes ); } @@ -12831,7 +13111,7 @@ function mountIndeterminateComponent( _current, workInProgress, Component, - renderExpirationTime + renderLanes ) { if (_current !== null) { // An indeterminate component only mounts if it suspended inside a non- @@ -12841,7 +13121,7 @@ function mountIndeterminateComponent( _current.alternate = null; workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect - workInProgress.effectTag |= Placement; + workInProgress.flags |= Placement; } var props = workInProgress.pendingProps; @@ -12852,7 +13132,7 @@ function mountIndeterminateComponent( context = getMaskedContext(workInProgress, unmaskedContext); } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var value; { @@ -12878,6 +13158,7 @@ function mountIndeterminateComponent( ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); } + setIsRendering(true); ReactCurrentOwner$1.current = workInProgress; value = renderWithHooks( null, @@ -12885,34 +13166,65 @@ function mountIndeterminateComponent( Component, props, context, - renderExpirationTime + renderLanes ); + setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; + workInProgress.flags |= PerformedWork; + + { + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if ( + typeof value === "object" && + value !== null && + typeof value.render === "function" && + value.$$typeof === undefined + ) { + var _componentName = getComponentName(Component) || "Unknown"; + + if (!didWarnAboutModulePatternComponent[_componentName]) { + error( + "The <%s /> component appears to be a function component that returns a class instance. " + + "Change %s to a class that extends React.Component instead. " + + "If you can't use a class try assigning the prototype on the function as a workaround. " + + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + + "cannot be called with `new` by React.", + _componentName, + _componentName, + _componentName + ); + + didWarnAboutModulePatternComponent[_componentName] = true; + } + } + } if ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. typeof value === "object" && value !== null && typeof value.render === "function" && value.$$typeof === undefined ) { { - var _componentName = getComponentName(Component) || "Unknown"; + var _componentName2 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutModulePatternComponent[_componentName]) { + if (!didWarnAboutModulePatternComponent[_componentName2]) { error( "The <%s /> component appears to be a function component that returns a class instance. " + "Change %s to a class that extends React.Component instead. " + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + "cannot be called with `new` by React.", - _componentName, - _componentName, - _componentName + _componentName2, + _componentName2, + _componentName2 ); - didWarnAboutModulePatternComponent[_componentName] = true; + didWarnAboutModulePatternComponent[_componentName2] = true; } } // Proceed under the assumption that this is a class instance @@ -12947,20 +13259,20 @@ function mountIndeterminateComponent( } adoptClassInstance(workInProgress, value); - mountClassInstance(workInProgress, Component, props, renderExpirationTime); + mountClassInstance(workInProgress, Component, props, renderLanes); return finishClassComponent( null, workInProgress, Component, true, hasContext, - renderExpirationTime + renderLanes ); } else { // Proceed under the assumption that this is a function component workInProgress.tag = FunctionComponent; - reconcileChildren(null, workInProgress, value, renderExpirationTime); + reconcileChildren(null, workInProgress, value, renderLanes); { validateFunctionComponentInDev(workInProgress, Component); @@ -13009,15 +13321,15 @@ function validateFunctionComponentInDev(workInProgress, Component) { } if (typeof Component.getDerivedStateFromProps === "function") { - var _componentName2 = getComponentName(Component) || "Unknown"; + var _componentName3 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName2]) { + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { error( "%s: Function components do not support getDerivedStateFromProps.", - _componentName2 + _componentName3 ); - didWarnAboutGetDerivedStateOnFunctionComponent[_componentName2] = true; + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; } } @@ -13025,15 +13337,15 @@ function validateFunctionComponentInDev(workInProgress, Component) { typeof Component.contextType === "object" && Component.contextType !== null ) { - var _componentName3 = getComponentName(Component) || "Unknown"; + var _componentName4 = getComponentName(Component) || "Unknown"; - if (!didWarnAboutContextTypeOnFunctionComponent[_componentName3]) { + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { error( "%s: Function components do not support contextType.", - _componentName3 + _componentName4 ); - didWarnAboutContextTypeOnFunctionComponent[_componentName3] = true; + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; } } } @@ -13041,41 +13353,68 @@ function validateFunctionComponentInDev(workInProgress, Component) { var SUSPENDED_MARKER = { dehydrated: null, - retryTime: NoWork + retryLane: NoLane }; -function shouldRemainOnFallback(suspenseContext, current, workInProgress) { - // If the context is telling us that we should show a fallback, and we're not - // already showing content, then we should show the fallback instead. - return ( - hasSuspenseContext(suspenseContext, ForceSuspenseFallback) && - (current === null || current.memoizedState !== null) - ); +function mountSuspenseOffscreenState(renderLanes) { + return { + baseLanes: renderLanes + }; } -function updateSuspenseComponent( +function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { + return { + baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes) + }; +} // TODO: Probably should inline this back + +function shouldRemainOnFallback( + suspenseContext, current, workInProgress, - renderExpirationTime + renderLanes ) { - var mode = workInProgress.mode; + // If we're already showing a fallback, there are cases where we need to + // remain on that fallback regardless of whether the content has resolved. + // For example, SuspenseList coordinates when nested content appears. + if (current !== null) { + var suspenseState = current.memoizedState; + + if (suspenseState === null) { + // Currently showing content. Don't hide it, even if ForceSuspenseFallack + // is true. More precise name might be "ForceRemainSuspenseFallback". + // Note: This is a factoring smell. Can't remain on a fallback if there's + // no fallback to remain on. + return false; + } + } // Not currently showing content. Consult the Suspense context. + + return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); +} + +function getRemainingWorkInPrimaryTree(current, renderLanes) { + // TODO: Should not remove render lanes that were pinged during this render + return removeLanes(current.childLanes, renderLanes); +} + +function updateSuspenseComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. { if (shouldSuspend(workInProgress)) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } } var suspenseContext = suspenseStackCursor.current; - var nextDidTimeout = false; - var didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect; + var showFallback = false; + var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { // Something in this boundary's subtree already suspended. Switch to // rendering the fallback children. - nextDidTimeout = true; - workInProgress.effectTag &= ~DidCapture; + showFallback = true; + workInProgress.flags &= ~DidCapture; } else { // Attempting the main content if (current === null || current.memoizedState !== null) { @@ -13097,290 +13436,411 @@ function updateSuspenseComponent( } suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); - pushSuspenseContext(workInProgress, suspenseContext); // This next part is a bit confusing. If the children timeout, we switch to - // showing the fallback children in place of the "primary" children. - // However, we don't want to delete the primary children because then their - // state will be lost (both the React state and the host state, e.g. - // uncontrolled form inputs). Instead we keep them mounted and hide them. - // Both the fallback children AND the primary children are rendered at the - // same time. Once the primary children are un-suspended, we can delete - // the fallback children — don't need to preserve their state. + pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense + // boundary's children. This involves some custom reconcilation logic. Two + // main reasons this is so complicated. // - // The two sets of children are siblings in the host environment, but - // semantically, for purposes of reconciliation, they are two separate sets. - // So we store them using two fragment fibers. + // First, Legacy Mode has different semantics for backwards compatibility. The + // primary tree will commit in an inconsistent state, so when we do the + // second pass to render the fallback, we do some exceedingly, uh, clever + // hacks to make that not totally break. Like transferring effects and + // deletions from hidden tree. In Concurrent Mode, it's much simpler, + // because we bailout on the primary tree completely and leave it in its old + // state, no effects. Same as what we do for Offscreen (except that + // Offscreen doesn't have the first render pass). // - // However, we want to avoid allocating extra fibers for every placeholder. - // They're only necessary when the children time out, because that's the - // only time when both sets are mounted. + // Second is hydration. During hydration, the Suspense fiber has a slightly + // different layout, where the child points to a dehydrated fragment, which + // contains the DOM rendered by the server. // - // So, the extra fragment fibers are only used if the children time out. - // Otherwise, we render the primary children directly. This requires some - // custom reconciliation logic to preserve the state of the primary - // children. It's essentially a very basic form of re-parenting. + // Third, even if you set all that aside, Suspense is like error boundaries in + // that we first we try to render one tree, and if that fails, we render again + // and switch to a different tree. Like a try/catch block. So we have to track + // which branch we're currently rendering. Ideally we would model this using + // a stack. if (current === null) { + // Initial mount // If we're currently hydrating, try to hydrate this boundary. // But only if this has a fallback. - if (nextProps.fallback !== undefined); // This is the initial mount. This branch is pretty simple because there's - // no previous state that needs to be preserved. + if (nextProps.fallback !== undefined); - if (nextDidTimeout) { - // Mount separate fragments for primary and fallback children. - var nextFallbackChildren = nextProps.fallback; - var primaryChildFragment = createFiberFromFragment( - null, - mode, - NoWork, - null - ); - primaryChildFragment.return = workInProgress; - - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var progressedState = workInProgress.memoizedState; - var progressedPrimaryChild = - progressedState !== null - ? workInProgress.child.child - : workInProgress.child; - primaryChildFragment.child = progressedPrimaryChild; - var progressedChild = progressedPrimaryChild; - - while (progressedChild !== null) { - progressedChild.return = primaryChildFragment; - progressedChild = progressedChild.sibling; - } - } + var nextPrimaryChildren = nextProps.children; + var nextFallbackChildren = nextProps.fallback; - var fallbackChildFragment = createFiberFromFragment( + if (showFallback) { + var fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, nextFallbackChildren, - mode, - renderExpirationTime, - null + renderLanes + ); + var primaryChildFragment = workInProgress.child; + primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes ); - fallbackChildFragment.return = workInProgress; - primaryChildFragment.sibling = fallbackChildFragment; // Skip the primary children, and continue working on the - // fallback children. - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = primaryChildFragment; - return fallbackChildFragment; + return fallbackFragment; + } else if (typeof nextProps.unstable_expectedLoadTime === "number") { + // This is a CPU-bound tree. Skip this tree and show a placeholder to + // unblock the surrounding content. Then immediately retry after the + // initial commit. + var _fallbackFragment = mountSuspenseFallbackChildren( + workInProgress, + nextPrimaryChildren, + nextFallbackChildren, + renderLanes + ); + + var _primaryChildFragment = workInProgress.child; + _primaryChildFragment.memoizedState = mountSuspenseOffscreenState( + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to + // get it started back up to attempt the next item. While in terms of + // priority this work has the same priority as this current render, it's + // not part of the same transition once the transition has committed. If + // it's sync, we still want to yield so that it can be painted. + // Conceptually, this is really the same as pinging. We can use any + // RetryLane even if it's the one currently rendering since we're leaving + // it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); + } + + return _fallbackFragment; } else { - // Mount the primary children without an intermediate fragment fiber. - var nextPrimaryChildren = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( + return mountSuspensePrimaryChildren( workInProgress, - null, nextPrimaryChildren, - renderExpirationTime - )); + renderLanes + ); } } else { - // This is an update. This branch is more complicated because we need to - // ensure the state of the primary children is preserved. + // This is an update. + // If the current fiber has a SuspenseState, that means it's already showing + // a fallback. var prevState = current.memoizedState; if (prevState !== null) { - // wrapped in a fragment fiber. - - var currentPrimaryChildFragment = current.child; - var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; - - if (nextDidTimeout) { - // Still timed out. Reuse the current primary children by cloning - // its fragment. We're going to skip over these entirely. + if (showFallback) { var _nextFallbackChildren2 = nextProps.fallback; + var _nextPrimaryChildren2 = nextProps.children; - var _primaryChildFragment2 = createWorkInProgress( - currentPrimaryChildFragment, - currentPrimaryChildFragment.pendingProps + var _fallbackChildFragment = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren2, + _nextFallbackChildren2, + renderLanes ); - _primaryChildFragment2.return = workInProgress; - - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var _progressedState = workInProgress.memoizedState; - - var _progressedPrimaryChild = - _progressedState !== null - ? workInProgress.child.child - : workInProgress.child; - - if (_progressedPrimaryChild !== currentPrimaryChildFragment.child) { - _primaryChildFragment2.child = _progressedPrimaryChild; - var _progressedChild2 = _progressedPrimaryChild; - - while (_progressedChild2 !== null) { - _progressedChild2.return = _primaryChildFragment2; - _progressedChild2 = _progressedChild2.sibling; - } - } - } // Because primaryChildFragment is a new fiber that we're inserting as the - // parent of a new tree, we need to set its treeBaseDuration. - - if (workInProgress.mode & ProfileMode) { - // treeBaseDuration is the sum of all the child tree base durations. - var _treeBaseDuration = 0; - var _hiddenChild = _primaryChildFragment2.child; + var _primaryChildFragment3 = workInProgress.child; + var prevOffscreenState = current.child.memoizedState; + _primaryChildFragment3.memoizedState = + prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); + _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); + workInProgress.memoizedState = SUSPENDED_MARKER; + return _fallbackChildFragment; + } else { + var _nextPrimaryChildren3 = nextProps.children; - while (_hiddenChild !== null) { - _treeBaseDuration += _hiddenChild.treeBaseDuration; - _hiddenChild = _hiddenChild.sibling; - } + var _primaryChildFragment4 = updateSuspensePrimaryChildren( + current, + workInProgress, + _nextPrimaryChildren3, + renderLanes + ); - _primaryChildFragment2.treeBaseDuration = _treeBaseDuration; - } // Clone the fallback child fragment, too. These we'll continue - // working on. + workInProgress.memoizedState = null; + return _primaryChildFragment4; + } + } else { + // The current tree is not already showing a fallback. + if (showFallback) { + // Timed out. + var _nextFallbackChildren3 = nextProps.fallback; + var _nextPrimaryChildren4 = nextProps.children; - var _fallbackChildFragment2 = createWorkInProgress( - currentFallbackChildFragment, - _nextFallbackChildren2 + var _fallbackChildFragment2 = updateSuspenseFallbackChildren( + current, + workInProgress, + _nextPrimaryChildren4, + _nextFallbackChildren3, + renderLanes ); - _fallbackChildFragment2.return = workInProgress; - _primaryChildFragment2.sibling = _fallbackChildFragment2; - _primaryChildFragment2.childExpirationTime = NoWork; // Skip the primary children, and continue working on the + var _primaryChildFragment5 = workInProgress.child; + var _prevOffscreenState = current.child.memoizedState; + _primaryChildFragment5.memoizedState = + _prevOffscreenState === null + ? mountSuspenseOffscreenState(renderLanes) + : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes); + _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree( + current, + renderLanes + ); // Skip the primary children, and continue working on the // fallback children. workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = _primaryChildFragment2; return _fallbackChildFragment2; } else { - // No longer suspended. Switch back to showing the primary children, - // and remove the intermediate fragment fiber. - var _nextPrimaryChildren = nextProps.children; - var currentPrimaryChild = currentPrimaryChildFragment.child; - var primaryChild = reconcileChildFibers( + // Still haven't timed out. Continue rendering the children, like we + // normally do. + var _nextPrimaryChildren5 = nextProps.children; + + var _primaryChildFragment6 = updateSuspensePrimaryChildren( + current, workInProgress, - currentPrimaryChild, - _nextPrimaryChildren, - renderExpirationTime - ); // If this render doesn't suspend, we need to delete the fallback - // children. Wait until the complete phase, after we've confirmed the - // fallback is no longer needed. - // TODO: Would it be better to store the fallback fragment on - // the stateNode? - // Continue rendering the children, like we normally do. + _nextPrimaryChildren5, + renderLanes + ); workInProgress.memoizedState = null; - return (workInProgress.child = primaryChild); + return _primaryChildFragment6; } - } else { - // The current tree has not already timed out. That means the primary - // children are not wrapped in a fragment fiber. - var _currentPrimaryChild = current.child; + } + } +} - if (nextDidTimeout) { - // Timed out. Wrap the children in a fragment fiber to keep them - // separate from the fallback children. - var _nextFallbackChildren3 = nextProps.fallback; +function mountSuspensePrimaryChildren( + workInProgress, + primaryChildren, + renderLanes +) { + var mode = workInProgress.mode; + var primaryChildProps = { + mode: "visible", + children: primaryChildren + }; + var primaryChildFragment = createFiberFromOffscreen( + primaryChildProps, + mode, + renderLanes, + null + ); + primaryChildFragment.return = workInProgress; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - var _primaryChildFragment3 = createFiberFromFragment( - // It shouldn't matter what the pending props are because we aren't - // going to render this fragment. - null, - mode, - NoWork, - null - ); +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var progressedPrimaryFragment = workInProgress.child; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; + var fallbackChildFragment; + + if ((mode & BlockingMode) === NoMode && progressedPrimaryFragment !== null) { + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = 0; + primaryChildFragment.treeBaseDuration = 0; + } + + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } else { + primaryChildFragment = createFiberFromOffscreen( + primaryChildProps, + mode, + NoLanes, + null + ); + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + } - _primaryChildFragment3.return = workInProgress; - _primaryChildFragment3.child = _currentPrimaryChild; + primaryChildFragment.return = workInProgress; + fallbackChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} - if (_currentPrimaryChild !== null) { - _currentPrimaryChild.return = _primaryChildFragment3; - } // Even though we're creating a new fiber, there are no new children, - // because we're reusing an already mounted tree. So we don't need to - // schedule a placement. - // primaryChildFragment.effectTag |= Placement; +function createWorkInProgressOffscreenFiber(current, offscreenProps) { + // The props argument to `createWorkInProgress` is `any` typed, so we use this + // wrapper function to constrain it. + return createWorkInProgress(current, offscreenProps); +} - if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, we commit the effects from the - // partially completed, timed-out tree, too. - var _progressedState2 = workInProgress.memoizedState; +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildFragment = createWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + { + mode: "visible", + children: primaryChildren + } + ); - var _progressedPrimaryChild2 = - _progressedState2 !== null - ? workInProgress.child.child - : workInProgress.child; + if ((workInProgress.mode & BlockingMode) === NoMode) { + primaryChildFragment.lanes = renderLanes; + } - _primaryChildFragment3.child = _progressedPrimaryChild2; - var _progressedChild3 = _progressedPrimaryChild2; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = null; - while (_progressedChild3 !== null) { - _progressedChild3.return = _primaryChildFragment3; - _progressedChild3 = _progressedChild3.sibling; - } - } // Because primaryChildFragment is a new fiber that we're inserting as the - // parent of a new tree, we need to set its treeBaseDuration. + if (currentFallbackChildFragment !== null) { + // Delete the fallback child fragment + currentFallbackChildFragment.nextEffect = null; + currentFallbackChildFragment.flags = Deletion; + workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment; + } - if (workInProgress.mode & ProfileMode) { - // treeBaseDuration is the sum of all the child tree base durations. - var _treeBaseDuration2 = 0; - var _hiddenChild2 = _primaryChildFragment3.child; + workInProgress.child = primaryChildFragment; + return primaryChildFragment; +} - while (_hiddenChild2 !== null) { - _treeBaseDuration2 += _hiddenChild2.treeBaseDuration; - _hiddenChild2 = _hiddenChild2.sibling; - } +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode; + var currentPrimaryChildFragment = current.child; + var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; + var primaryChildProps = { + mode: "hidden", + children: primaryChildren + }; + var primaryChildFragment; - _primaryChildFragment3.treeBaseDuration = _treeBaseDuration2; - } // Create a fragment from the fallback children, too. + if ( + // In legacy mode, we commit the primary tree as if it successfully + // completed, even though it's in an inconsistent state. + (mode & BlockingMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was + // already cloned. In legacy mode, the only case where this isn't true is + // when DevTools forces us to display a fallback; we skip the first render + // pass entirely and go straight to rendering the fallback. (In Concurrent + // Mode, SuspenseList can also trigger this scenario, but this is a legacy- + // only codepath.) + workInProgress.child !== currentPrimaryChildFragment + ) { + var progressedPrimaryFragment = workInProgress.child; + primaryChildFragment = progressedPrimaryFragment; + primaryChildFragment.childLanes = NoLanes; + primaryChildFragment.pendingProps = primaryChildProps; + + if (workInProgress.mode & ProfileMode) { + // Reset the durations from the first pass so they aren't included in the + // final amounts. This seems counterintuitive, since we're intentionally + // not measuring part of the render phase, but this makes it match what we + // do in Concurrent Mode. + primaryChildFragment.actualDuration = 0; + primaryChildFragment.actualStartTime = -1; + primaryChildFragment.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration; + primaryChildFragment.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration; + } // The fallback fiber was added as a deletion effect during the first pass. + // However, since we're going to remain on the fallback, we no longer want + // to delete it. So we need to remove it from the list. Deletions are stored + // on the same list as effects. We want to keep the effects from the primary + // tree. So we copy the primary child fragment's effect list, which does not + // include the fallback deletion effect. + + var progressedLastEffect = primaryChildFragment.lastEffect; + + if (progressedLastEffect !== null) { + workInProgress.firstEffect = primaryChildFragment.firstEffect; + workInProgress.lastEffect = progressedLastEffect; + progressedLastEffect.nextEffect = null; + } else { + // TODO: Reset this somewhere else? Lol legacy mode is so weird. + workInProgress.firstEffect = workInProgress.lastEffect = null; + } + } else { + primaryChildFragment = createWorkInProgressOffscreenFiber( + currentPrimaryChildFragment, + primaryChildProps + ); + } - var _fallbackChildFragment3 = createFiberFromFragment( - _nextFallbackChildren3, - mode, - renderExpirationTime, - null - ); + var fallbackChildFragment; - _fallbackChildFragment3.return = workInProgress; - _primaryChildFragment3.sibling = _fallbackChildFragment3; - _fallbackChildFragment3.effectTag |= Placement; - _primaryChildFragment3.childExpirationTime = NoWork; // Skip the primary children, and continue working on the - // fallback children. + if (currentFallbackChildFragment !== null) { + fallbackChildFragment = createWorkInProgress( + currentFallbackChildFragment, + fallbackChildren + ); + } else { + fallbackChildFragment = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); // Needs a placement effect because the parent (the Suspense boundary) already + // mounted but this is a new fiber. - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = _primaryChildFragment3; - return _fallbackChildFragment3; - } else { - // Still haven't timed out. Continue rendering the children, like we - // normally do. - workInProgress.memoizedState = null; - var _nextPrimaryChildren2 = nextProps.children; - return (workInProgress.child = reconcileChildFibers( - workInProgress, - _currentPrimaryChild, - _nextPrimaryChildren2, - renderExpirationTime - )); - } - } + fallbackChildFragment.flags |= Placement; } -} -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - if (fiber.expirationTime < renderExpirationTime) { - fiber.expirationTime = renderExpirationTime; - } + fallbackChildFragment.return = workInProgress; + primaryChildFragment.return = workInProgress; + primaryChildFragment.sibling = fallbackChildFragment; + workInProgress.child = primaryChildFragment; + return fallbackChildFragment; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; - if (alternate !== null && alternate.expirationTime < renderExpirationTime) { - alternate.expirationTime = renderExpirationTime; + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function propagateSuspenseContextChange( workInProgress, firstChild, - renderExpirationTime + renderLanes ) { // Mark any Suspense boundaries with fallbacks as having work to do. // If they were previously forced into fallbacks, they may now be able @@ -13392,7 +13852,7 @@ function propagateSuspenseContextChange( var state = node.memoizedState; if (state !== null) { - scheduleWorkOnFiber(node, renderExpirationTime); + scheduleWorkOnFiber(node, renderLanes); } } else if (node.tag === SuspenseListComponent) { // If the tail is hidden there might not be an Suspense boundaries @@ -13400,7 +13860,7 @@ function propagateSuspenseContextChange( // list itself. // We don't have to traverse to the children of the list since // the list will propagate the change when it rerenders. - scheduleWorkOnFiber(node, renderExpirationTime); + scheduleWorkOnFiber(node, renderLanes); } else if (node.child !== null) { node.child.return = node; node = node.child; @@ -13619,7 +14079,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }; @@ -13630,7 +14089,6 @@ function initSuspenseListRenderState( renderState.renderingStartTime = 0; renderState.last = lastContentRow; renderState.tail = tail; - renderState.tailExpiration = 0; renderState.tailMode = tailMode; renderState.lastEffect = lastEffectBeforeRendering; } @@ -13642,11 +14100,7 @@ function initSuspenseListRenderState( // in fallback state. Then we render each row in the tail one-by-one. // That happens in the completeWork phase without going back to beginWork. -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps; var revealOrder = nextProps.revealOrder; var tailMode = nextProps.tail; @@ -13654,7 +14108,7 @@ function updateSuspenseListComponent( validateRevealOrder(revealOrder); validateTailOptions(tailMode, revealOrder); validateSuspenseListChildren(newChildren, revealOrder); - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + reconcileChildren(current, workInProgress, newChildren, renderLanes); var suspenseContext = suspenseStackCursor.current; var shouldForceFallback = hasSuspenseContext( suspenseContext, @@ -13666,10 +14120,10 @@ function updateSuspenseListComponent( suspenseContext, ForceSuspenseFallback ); - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } else { var didSuspendBefore = - current !== null && (current.effectTag & DidCapture) !== NoEffect; + current !== null && (current.flags & DidCapture) !== NoFlags; if (didSuspendBefore) { // If we previously forced a fallback, we need to schedule work @@ -13678,7 +14132,7 @@ function updateSuspenseListComponent( propagateSuspenseContextChange( workInProgress, workInProgress.child, - renderExpirationTime + renderLanes ); } @@ -13688,7 +14142,7 @@ function updateSuspenseListComponent( pushSuspenseContext(workInProgress, suspenseContext); if ((workInProgress.mode & BlockingMode) === NoMode) { - // Outside of blocking mode, SuspenseList doesn't work so we just + // In legacy mode, SuspenseList doesn't work so we just // use make it a noop by treating it as the default revealOrder. workInProgress.memoizedState = null; } else { @@ -13778,7 +14232,7 @@ function updateSuspenseListComponent( return workInProgress.child; } -function updatePortalComponent(current, workInProgress, renderExpirationTime) { +function updatePortalComponent(current, workInProgress, renderLanes) { pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); var nextChildren = workInProgress.pendingProps; @@ -13792,21 +14246,18 @@ function updatePortalComponent(current, workInProgress, renderExpirationTime) { workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ); } else { - reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); } return workInProgress.child; } -function updateContextProvider(current, workInProgress, renderExpirationTime) { +var hasWarnedAboutUsingNoValuePropOnContextProvider = false; + +function updateContextProvider(current, workInProgress, renderLanes) { var providerType = workInProgress.type; var context = providerType._context; var newProps = workInProgress.pendingProps; @@ -13814,6 +14265,16 @@ function updateContextProvider(current, workInProgress, renderExpirationTime) { var newValue = newProps.value; { + if (!("value" in newProps)) { + if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { + hasWarnedAboutUsingNoValuePropOnContextProvider = true; + + error( + "The `value` prop is required for the ``. Did you misspell it or forget to pass it?" + ); + } + } + var providerPropTypes = workInProgress.type.propTypes; if (providerPropTypes) { @@ -13833,29 +14294,24 @@ function updateContextProvider(current, workInProgress, renderExpirationTime) { return bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); } } else { // The context value changed. Search for matching consumers and schedule // them to update. - propagateContextChange( - workInProgress, - context, - changedBits, - renderExpirationTime - ); + propagateContextChange(workInProgress, context, changedBits, renderLanes); } } var newChildren = newProps.children; - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } var hasWarnedAboutUsingContextAsConsumer = false; -function updateContextConsumer(current, workInProgress, renderExpirationTime) { +function updateContextConsumer(current, workInProgress, renderLanes) { var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In // DEV mode, we create a separate object for Context.Consumer that acts // like a proxy to Context. This proxy object adds unnecessary code in PROD @@ -13898,7 +14354,7 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) { } } - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); var newValue = readContext(context, newProps.unstable_observedBits); var newChildren; @@ -13909,8 +14365,8 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) { setIsRendering(false); } // React DevTools reads this flag. - workInProgress.effectTag |= PerformedWork; - reconcileChildren(current, workInProgress, newChildren, renderExpirationTime); + workInProgress.flags |= PerformedWork; + reconcileChildren(current, workInProgress, newChildren, renderLanes); return workInProgress.child; } @@ -13918,13 +14374,7 @@ function markWorkInProgressReceivedUpdate() { didReceiveUpdate = true; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { - cancelWorkTimer(workInProgress); - +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { if (current !== null) { // Reuse previous dependencies workInProgress.dependencies = current.dependencies; @@ -13935,15 +14385,9 @@ function bailoutOnAlreadyFinishedWork( stopProfilerTimerIfRunning(); } - var updateExpirationTime = workInProgress.expirationTime; - - if (updateExpirationTime !== NoWork) { - markUnprocessedUpdateTime(updateExpirationTime); - } // Check if the children have any pending work. + markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. - var childExpirationTime = workInProgress.childExpirationTime; - - if (childExpirationTime < renderExpirationTime) { + if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { // The children don't have any work either. We can skip them. // TODO: Once we add back resuming, we should check if the children are // a work-in-progress set. If so, we need to transfer their effects. @@ -14004,15 +14448,15 @@ function remountFiber(current, oldWorkInProgress, newWorkInProgress) { } current.nextEffect = null; - current.effectTag = Deletion; - newWorkInProgress.effectTag |= Placement; // Restart work from the new fiber. + current.flags = Deletion; + newWorkInProgress.flags |= Placement; // Restart work from the new fiber. return newWorkInProgress; } } -function beginWork(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +function beginWork(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; { if (workInProgress._debugNeedsRemount && current !== null) { @@ -14026,7 +14470,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, - workInProgress.expirationTime + workInProgress.lanes ) ); } @@ -14044,7 +14488,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // If props or context changed, mark the fiber as having performed work. // This may be unset if the props are determined to be equal later (memo). didReceiveUpdate = true; - } else if (updateExpirationTime < renderExpirationTime) { + } else if (!includesSomeLane(renderLanes, updateLanes)) { didReceiveUpdate = false; // This fiber does not have any pending work. Bailout without entering // the begin phase. There's still some bookkeeping we that needs to be done // in this optimized path, mostly pushing stuff onto the stack. @@ -14056,20 +14500,6 @@ function beginWork(current, workInProgress, renderExpirationTime) { case HostComponent: pushHostContext(workInProgress); - - if ( - workInProgress.mode & ConcurrentMode && - renderExpirationTime !== Never && - shouldDeprioritizeSubtree(workInProgress.type) - ) { - { - markSpawnedWork(Never); - } // Schedule this fiber to re-render at offscreen priority. Then bailout. - - workInProgress.expirationTime = workInProgress.childExpirationTime = Never; - return null; - } - break; case ClassComponent: { @@ -14098,11 +14528,13 @@ function beginWork(current, workInProgress, renderExpirationTime) { case Profiler: { // Profiler should only call onRender when one of its descendants actually rendered. - var hasChildWork = - workInProgress.childExpirationTime >= renderExpirationTime; + var hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); if (hasChildWork) { - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Reset effect durations for the next eventual effect phase. // These are reset during render to allow the DevTools commit hook a chance to read them, @@ -14122,21 +14554,19 @@ function beginWork(current, workInProgress, renderExpirationTime) { // child fragment. var primaryChildFragment = workInProgress.child; - var primaryChildExpirationTime = - primaryChildFragment.childExpirationTime; + var primaryChildLanes = primaryChildFragment.childLanes; - if ( - primaryChildExpirationTime !== NoWork && - primaryChildExpirationTime >= renderExpirationTime - ) { + if (includesSomeLane(renderLanes, primaryChildLanes)) { // The primary children have pending work. Use the normal path // to attempt to render the primary children again. return updateSuspenseComponent( current, workInProgress, - renderExpirationTime + renderLanes ); } else { + // The primary child fragment does not have pending work marked + // on it pushSuspenseContext( workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current) @@ -14146,7 +14576,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { var child = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); if (child !== null) { @@ -14168,10 +14598,12 @@ function beginWork(current, workInProgress, renderExpirationTime) { } case SuspenseListComponent: { - var didSuspendBefore = (current.effectTag & DidCapture) !== NoEffect; + var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; - var _hasChildWork = - workInProgress.childExpirationTime >= renderExpirationTime; + var _hasChildWork = includesSomeLane( + renderLanes, + workInProgress.childLanes + ); if (didSuspendBefore) { if (_hasChildWork) { @@ -14183,13 +14615,13 @@ function beginWork(current, workInProgress, renderExpirationTime) { return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); } // If none of the children had any work, that means that none of // them got retried so they'll still be blocked in the same way // as before. We can fast bail out. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; } // If nothing suspended before and we're rendering the same children, // then the tail doesn't matter. Anything new that suspends will work // in the "together" mode, so we can continue from the state we had. @@ -14201,6 +14633,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // update in the past but didn't complete it. renderState.rendering = null; renderState.tail = null; + renderState.lastEffect = null; } pushSuspenseContext(workInProgress, suspenseStackCursor.current); @@ -14214,19 +14647,35 @@ function beginWork(current, workInProgress, renderExpirationTime) { return null; } } + + case OffscreenComponent: + case LegacyHiddenComponent: { + // Need to check if the tree still needs to be deferred. This is + // almost identical to the logic used in the normal update path, + // so we'll just enter that. The only difference is we'll bail out + // at the next level instead of this one, because the child props + // have not changed. Which is fine. + // TODO: Probably should refactor `beginWork` to split the bailout + // path from the normal path. I'm tempted to do a labeled break here + // but I won't :) + workInProgress.lanes = NoLanes; + return updateOffscreenComponent(current, workInProgress, renderLanes); + } } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else { - // An update was scheduled on this fiber, but there are no new props - // nor legacy context. Set this to false. If an update queue or context - // consumer produces a changed value, it will set this to true. Otherwise, - // the component will assume the children have not changed and bail out. - didReceiveUpdate = false; + if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { + // This is a special case that only exists for legacy mode. + // See https://github.com/facebook/react/pull/19216. + didReceiveUpdate = true; + } else { + // An update was scheduled on this fiber, but there are no new props + // nor legacy context. Set this to false. If an update queue or context + // consumer produces a changed value, it will set this to true. Otherwise, + // the component will assume the children have not changed and bail out. + didReceiveUpdate = false; + } } } else { didReceiveUpdate = false; @@ -14236,7 +14685,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { // sometimes bails out later in the begin phase. This indicates that we should // move this assignment out of the common path and into each branch. - workInProgress.expirationTime = NoWork; + workInProgress.lanes = NoLanes; switch (workInProgress.tag) { case IndeterminateComponent: { @@ -14244,7 +14693,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.type, - renderExpirationTime + renderLanes ); } @@ -14254,8 +14703,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { current, workInProgress, elementType, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -14271,7 +14720,7 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component, resolvedProps, - renderExpirationTime + renderLanes ); } @@ -14289,32 +14738,24 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component2, _resolvedProps, - renderExpirationTime + renderLanes ); } case HostRoot: - return updateHostRoot(current, workInProgress, renderExpirationTime); + return updateHostRoot(current, workInProgress, renderLanes); case HostComponent: - return updateHostComponent(current, workInProgress, renderExpirationTime); + return updateHostComponent(current, workInProgress, renderLanes); case HostText: return updateHostText(); case SuspenseComponent: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case HostPortal: - return updatePortalComponent( - current, - workInProgress, - renderExpirationTime - ); + return updatePortalComponent(current, workInProgress, renderLanes); case ForwardRef: { var type = workInProgress.type; @@ -14330,32 +14771,24 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, type, _resolvedProps2, - renderExpirationTime + renderLanes ); } case Fragment: - return updateFragment(current, workInProgress, renderExpirationTime); + return updateFragment(current, workInProgress, renderLanes); case Mode: - return updateMode(current, workInProgress, renderExpirationTime); + return updateMode(current, workInProgress, renderLanes); case Profiler: - return updateProfiler(current, workInProgress, renderExpirationTime); + return updateProfiler(current, workInProgress, renderLanes); case ContextProvider: - return updateContextProvider( - current, - workInProgress, - renderExpirationTime - ); + return updateContextProvider(current, workInProgress, renderLanes); case ContextConsumer: - return updateContextConsumer( - current, - workInProgress, - renderExpirationTime - ); + return updateContextConsumer(current, workInProgress, renderLanes); case MemoComponent: { var _type2 = workInProgress.type; @@ -14384,8 +14817,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _type2, _resolvedProps3, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -14395,8 +14828,8 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); } @@ -14414,16 +14847,28 @@ function beginWork(current, workInProgress, renderExpirationTime) { workInProgress, _Component3, _resolvedProps4, - renderExpirationTime + renderLanes ); } case SuspenseListComponent: { - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + } + + case FundamentalComponent: { + break; + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: { + return updateOffscreenComponent(current, workInProgress, renderLanes); + } + + case LegacyHiddenComponent: { + return updateLegacyHiddenComponent(current, workInProgress, renderLanes); } } @@ -14439,11 +14884,11 @@ function beginWork(current, workInProgress, renderExpirationTime) { function markUpdate(workInProgress) { // Tag the fiber with an update effect. This turns a Placement into // a PlacementAndUpdate. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } function markRef$1(workInProgress) { - workInProgress.effectTag |= Ref; + workInProgress.flags |= Ref; } var appendAllChildren; @@ -14607,7 +15052,7 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { @@ -14636,6 +15081,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { case HostRoot: { popHostContainer(workInProgress); popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); var fiberRoot = workInProgress.stateNode; if (fiberRoot.pendingContext) { @@ -14652,6 +15098,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { // If we hydrated, then we'll need to schedule an update for // the commit side-effects on the root. markUpdate(workInProgress); + } else if (!fiberRoot.hydrate) { + // Schedule an effect to clear this container at the start of the next commit. + // This handles the case of React rendering into a container with previous children. + // It's also safe to do for updates too, because current.child would only be null + // if the previous render was null (so the the container would already be empty). + workInProgress.flags |= Snapshot; } } @@ -14710,9 +15162,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { currentHostContext, workInProgress ); - appendAllChildren(instance, workInProgress, false, false); // This needs to be set before we mount Flare event listeners - - workInProgress.stateNode = instance; + appendAllChildren(instance, workInProgress, false, false); + workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. // (eg DOM renderer supports auto-focus for certain elements). // Make sure such renderers get scheduled for later work. @@ -14774,9 +15225,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { popSuspenseContext(workInProgress); var nextState = workInProgress.memoizedState; - if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + if ((workInProgress.flags & DidCapture) !== NoFlags) { // Something suspended. Re-render with the fallback children. - workInProgress.expirationTime = renderExpirationTime; // Do not reset the effect list. + workInProgress.lanes = renderLanes; // Do not reset the effect list. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } return workInProgress; } @@ -14789,29 +15244,6 @@ function completeWork(current, workInProgress, renderExpirationTime) { } else { var prevState = current.memoizedState; prevDidTimeout = prevState !== null; - - if (!nextDidTimeout && prevState !== null) { - // We just switched from the fallback to the normal children. - // Delete the fallback. - // TODO: Would it be better to store the fallback fragment on - // the stateNode during the begin phase? - var currentFallbackChild = current.child.sibling; - - if (currentFallbackChild !== null) { - // Deletions go at the beginning of the return fiber's effect list - var first = workInProgress.firstEffect; - - if (first !== null) { - workInProgress.firstEffect = currentFallbackChild; - currentFallbackChild.nextEffect = first; - } else { - workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChild; - currentFallbackChild.nextEffect = null; - } - - currentFallbackChild.effectTag = Deletion; - } - } } if (nextDidTimeout && !prevDidTimeout) { @@ -14858,7 +15290,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { // primary children. In mutation mode, we also need the flag to // *unhide* children that were previously hidden, so check if this // is currently timed out, too. - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } } @@ -14868,6 +15300,11 @@ function completeWork(current, workInProgress, renderExpirationTime) { case HostPortal: popHostContainer(workInProgress); updateHostContainer(workInProgress); + + if (current === null) { + preparePortalMount(workInProgress.stateNode.containerInfo); + } + return null; case ContextProvider: @@ -14897,8 +15334,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } - var didSuspendAlready = - (workInProgress.effectTag & DidCapture) !== NoEffect; + var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; var renderedTail = renderState.rendering; if (renderedTail === null) { @@ -14915,7 +15351,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { // findFirstSuspended. var cannotBeSuspended = renderHasNotSuspendedYet() && - (current === null || (current.effectTag & DidCapture) === NoEffect); + (current === null || (current.flags & DidCapture) === NoFlags); if (!cannotBeSuspended) { var row = workInProgress.child; @@ -14925,7 +15361,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (suspended !== null) { didSuspendAlready = true; - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as // part of the second pass. In that case nothing will subscribe to // its thennables. Instead, we'll transfer its thennables to the @@ -14943,7 +15379,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (newThennables !== null) { workInProgress.updateQueue = newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } // Rerender the whole list, but this time, we'll force fallbacks // to stay in place. // Reset the effect list before doing the second pass since that's now invalid. @@ -14954,7 +15390,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { workInProgress.lastEffect = renderState.lastEffect; // Reset the child fibers to their original state. - resetChildFibers(workInProgress, renderExpirationTime); // Set up the Suspense Context to force suspense and immediately + resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately // rerender the children. pushSuspenseContext( @@ -14967,7 +15403,29 @@ function completeWork(current, workInProgress, renderExpirationTime) { return workInProgress.child; } - row = row.sibling; + row = row.sibling; + } + } + + if (renderState.tail !== null && now() > getRenderTargetTime()) { + // We have already passed our CPU deadline but we still have rows + // left in the tail. We'll just give up further attempts to render + // the main content and only render fallbacks. + workInProgress.flags |= DidCapture; + didSuspendAlready = true; + cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. + + workInProgress.lanes = SomeRetryLane; + + { + markSpawnedWork(SomeRetryLane); } } } else { @@ -14979,7 +15437,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { var _suspended = findFirstSuspended(renderedTail); if (_suspended !== null) { - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't // get lost if this row ends up dropped during a second pass. @@ -14987,7 +15445,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (_newThennables !== null) { workInProgress.updateQueue = _newThennables; - workInProgress.effectTag |= Update; + workInProgress.flags |= Update; } cutOffTailIfNeeded(renderState, true); // This might have been modified. @@ -14995,7 +15453,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { if ( renderState.tail === null && renderState.tailMode === "hidden" && - !renderedTail.alternate + !renderedTail.alternate && + !getIsHydrating() // We don't cut it if we're hydrating. ) { // We need to delete the row we just rendered. // Reset the effect list to what it was before we rendered this @@ -15010,28 +15469,31 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } } else if ( - // The time it took to render last row is greater than time until - // the expiration. + // The time it took to render last row is greater than the remaining + // time we have to render. So rendering one more row would likely + // exceed it. now() * 2 - renderState.renderingStartTime > - renderState.tailExpiration && - renderExpirationTime > Never + getRenderTargetTime() && + renderLanes !== OffscreenLane ) { // We have now passed our CPU deadline and we'll just give up further // attempts to render the main content and only render fallbacks. // The assumption is that this is usually faster. - workInProgress.effectTag |= DidCapture; + workInProgress.flags |= DidCapture; didSuspendAlready = true; cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this - // to get it started back up to attempt the next item. If we can show - // them, then they really have the same priority as this render. - // So we'll pick it back up the very next render pass once we've had - // an opportunity to yield for paint. + // to get it started back up to attempt the next item. While in terms + // of priority this work has the same priority as this current render, + // it's not part of the same transition once the transition has + // committed. If it's sync, we still want to yield so that it can be + // painted. Conceptually, this is really the same as pinging. + // We can use any RetryLane even if it's the one currently rendering + // since we're leaving it behind on this node. - var nextPriority = renderExpirationTime - 1; - workInProgress.expirationTime = workInProgress.childExpirationTime = nextPriority; + workInProgress.lanes = SomeRetryLane; { - markSpawnedWork(nextPriority); + markSpawnedWork(SomeRetryLane); } } } @@ -15059,18 +15521,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { if (renderState.tail !== null) { // We still have tail rows to render. - if (renderState.tailExpiration === 0) { - // Heuristic for how long we're willing to spend rendering rows - // until we just give up and show what we have so far. - var TAIL_EXPIRATION_TIMEOUT_MS = 500; - renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS; // TODO: This is meant to mimic the train model or JND but this - // is a per component value. It should really be since the start - // of the total render or last commit. Consider using something like - // globalMostRecentFallbackTime. That doesn't account for being - // suspended for part of the time or when it's a new render. - // It should probably use a global start time value instead. - } // Pop a row. - + // Pop a row. var next = renderState.tail; renderState.rendering = next; renderState.tail = next.sibling; @@ -15098,6 +15549,35 @@ function completeWork(current, workInProgress, renderExpirationTime) { return null; } + + case FundamentalComponent: { + break; + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: + case LegacyHiddenComponent: { + popRenderLanes(workInProgress); + + if (current !== null) { + var _nextState = workInProgress.memoizedState; + var _prevState = current.memoizedState; + var prevIsHidden = _prevState !== null; + var nextIsHidden = _nextState !== null; + + if ( + prevIsHidden !== nextIsHidden && + newProps.mode !== "unstable-defer-without-hiding" + ) { + workInProgress.flags |= Update; + } + } + + return null; + } } { @@ -15109,7 +15589,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { } } -function unwindWork(workInProgress, renderExpirationTime) { +function unwindWork(workInProgress, renderLanes) { switch (workInProgress.tag) { case ClassComponent: { var Component = workInProgress.type; @@ -15118,211 +15598,571 @@ function unwindWork(workInProgress, renderExpirationTime) { popContext(workInProgress); } - var effectTag = workInProgress.effectTag; + var flags = workInProgress.flags; + + if (flags & ShouldCapture) { + workInProgress.flags = (flags & ~ShouldCapture) | DidCapture; + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } + + return workInProgress; + } + + return null; + } + + case HostRoot: { + popHostContainer(workInProgress); + popTopLevelContextObject(workInProgress); + resetWorkInProgressVersions(); + var _flags = workInProgress.flags; + + if (!((_flags & DidCapture) === NoFlags)) { + throw Error( + "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." + ); + } + + workInProgress.flags = (_flags & ~ShouldCapture) | DidCapture; + return workInProgress; + } + + case HostComponent: { + // TODO: popHydrationState + popHostContext(workInProgress); + return null; + } + + case SuspenseComponent: { + popSuspenseContext(workInProgress); + + var _flags2 = workInProgress.flags; + + if (_flags2 & ShouldCapture) { + workInProgress.flags = (_flags2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + + if ((workInProgress.mode & ProfileMode) !== NoMode) { + transferActualDuration(workInProgress); + } - if (effectTag & ShouldCapture) { - workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; return workInProgress; } - return null; - } + return null; + } + + case SuspenseListComponent: { + popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been + // caught by a nested boundary. If not, it should bubble through. + + return null; + } + + case HostPortal: + popHostContainer(workInProgress); + return null; + + case ContextProvider: + popProvider(workInProgress); + return null; + + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(workInProgress); + return null; + + default: + return null; + } +} + +function unwindInterruptedWork(interruptedWork) { + switch (interruptedWork.tag) { + case ClassComponent: { + var childContextTypes = interruptedWork.type.childContextTypes; + + if (childContextTypes !== null && childContextTypes !== undefined) { + popContext(interruptedWork); + } + + break; + } + + case HostRoot: { + popHostContainer(interruptedWork); + popTopLevelContextObject(interruptedWork); + resetWorkInProgressVersions(); + break; + } + + case HostComponent: { + popHostContext(interruptedWork); + break; + } + + case HostPortal: + popHostContainer(interruptedWork); + break; + + case SuspenseComponent: + popSuspenseContext(interruptedWork); + break; + + case SuspenseListComponent: + popSuspenseContext(interruptedWork); + break; + + case ContextProvider: + popProvider(interruptedWork); + break; + + case OffscreenComponent: + case LegacyHiddenComponent: + popRenderLanes(interruptedWork); + break; + } +} + +function createCapturedValue(value, source) { + // If the value is an error, call this function immediately after it is thrown + // so the stack is accurate. + return { + value: value, + source: source, + stack: getStackByFiberInDevAndProd(source) + }; +} + +if ( + !( + typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog === + "function" + ) +) { + throw Error( + "Expected ReactFiberErrorDialog.showErrorDialog to be a function." + ); +} + +function showErrorDialog(boundary, errorInfo) { + var capturedError = { + componentStack: errorInfo.stack !== null ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + boundary !== null && boundary.tag === ClassComponent + ? boundary.stateNode + : null + }; + return ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( + capturedError + ); +} + +function logCapturedError(boundary, errorInfo) { + try { + var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. + + if (logError === false) { + return; + } + + var error = errorInfo.value; + + if (true) { + var source = errorInfo.source; + var stack = errorInfo.stack; + var componentStack = stack !== null ? stack : ""; // Browsers support silencing uncaught errors by calling + // `preventDefault()` in window `error` handler. + // We record this information as an expando on the error. + + if (error != null && error._suppressLogging) { + if (boundary.tag === ClassComponent) { + // The error is recoverable and was silenced. + // Ignore it and don't print the stack addendum. + // This is handy for testing error boundaries without noise. + return; + } // The error is fatal. Since the silencing might have + // been accidental, we'll surface it anyway. + // However, the browser would have silenced the original error + // so we'll print it first, and then print the stack addendum. + + console["error"](error); // Don't transform to our wrapper + // For a more detailed description of this block, see: + // https://github.com/facebook/react/pull/13384 + } + + var componentName = source ? getComponentName(source.type) : null; + var componentNameMessage = componentName + ? "The above error occurred in the <" + componentName + "> component:" + : "The above error occurred in one of your React components:"; + var errorBoundaryMessage; + var errorBoundaryName = getComponentName(boundary.type); + + if (errorBoundaryName) { + errorBoundaryMessage = + "React will try to recreate this component tree from scratch " + + ("using the error boundary you provided, " + errorBoundaryName + "."); + } else { + errorBoundaryMessage = + "Consider adding an error boundary to your tree to customize error handling behavior.\n" + + "Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries."; + } + + var combinedMessage = + componentNameMessage + + "\n" + + componentStack + + "\n\n" + + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + + console["error"](combinedMessage); // Don't transform to our wrapper + } else { + // In production, we print the error directly. + // This will include the message, the JS stack, and anything the browser wants to show. + // We pass the error object instead of custom message so that the browser displays the error natively. + console["error"](error); // Don't transform to our wrapper + } + } catch (e) { + // This method must not throw, or React internal state will get messed up. + // If console.error is overridden, or logCapturedError() shows a dialog that throws, + // we want to report this error outside of the normal stack as a last resort. + // https://github.com/facebook/react/issues/13188 + setTimeout(function() { + throw e; + }); + } +} + +var PossiblyWeakMap$1 = typeof WeakMap === "function" ? WeakMap : Map; + +function createRootErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. + + update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property + // being called "element". + + update.payload = { + element: null + }; + var error = errorInfo.value; + + update.callback = function() { + onUncaughtError(error); + logCapturedError(fiber, errorInfo); + }; + + return update; +} + +function createClassErrorUpdate(fiber, errorInfo, lane) { + var update = createUpdate(NoTimestamp, lane); + update.tag = CaptureUpdate; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + + if (typeof getDerivedStateFromError === "function") { + var error$1 = errorInfo.value; + + update.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error$1); + }; + } + + var inst = fiber.stateNode; + + if (inst !== null && typeof inst.componentDidCatch === "function") { + update.callback = function callback() { + { + markFailedErrorBoundaryForHotReloading(fiber); + } + + if (typeof getDerivedStateFromError !== "function") { + // To preserve the preexisting retry behavior of error boundaries, + // we keep track of which ones already failed during this batch. + // This gets reset before we yield back to the browser. + // TODO: Warn in strict mode if getDerivedStateFromError is + // not defined. + markLegacyErrorBoundaryAsFailed(this); // Only log here if componentDidCatch is the only error boundary method defined + + logCapturedError(fiber, errorInfo); + } + + var error$1 = errorInfo.value; + var stack = errorInfo.stack; + this.componentDidCatch(error$1, { + componentStack: stack !== null ? stack : "" + }); + + { + if (typeof getDerivedStateFromError !== "function") { + // If componentDidCatch is the only error boundary method defined, + // then it needs to call setState to recover from errors. + // If no state update is scheduled then the boundary will swallow the error. + if (!includesSomeLane(fiber.lanes, SyncLane)) { + error( + "%s: Error boundaries should implement getDerivedStateFromError(). " + + "In that method, return a state update to display an error message or fallback UI.", + getComponentName(fiber.type) || "Unknown" + ); + } + } + } + }; + } else { + update.callback = function() { + markFailedErrorBoundaryForHotReloading(fiber); + }; + } + + return update; +} - case HostRoot: { - popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); - var _effectTag = workInProgress.effectTag; +function attachPingListener(root, wakeable, lanes) { + // Attach a listener to the promise to "ping" the root and retry. But only if + // one does not already exist for the lanes we're currently rendering (which + // acts like a "thread ID" here). + var pingCache = root.pingCache; + var threadIDs; - if (!((_effectTag & DidCapture) === NoEffect)) { - throw Error( - "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." - ); - } + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap$1(); + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); + } else { + threadIDs = pingCache.get(wakeable); - workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; - return workInProgress; + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(wakeable, threadIDs); } + } - case HostComponent: { - // TODO: popHydrationState - popHostContext(workInProgress); - return null; - } + if (!threadIDs.has(lanes)) { + // Memoize using the thread ID to prevent redundant listeners. + threadIDs.add(lanes); + var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); + wakeable.then(ping, ping); + } +} - case SuspenseComponent: { - popSuspenseContext(workInProgress); +function throwException( + root, + returnFiber, + sourceFiber, + value, + rootRenderLanes +) { + // The source fiber did not complete. + sourceFiber.flags |= Incomplete; // Its effect list is no longer valid. - var _effectTag2 = workInProgress.effectTag; + sourceFiber.firstEffect = sourceFiber.lastEffect = null; + + if ( + value !== null && + typeof value === "object" && + typeof value.then === "function" + ) { + // This is a wakeable. + var wakeable = value; - if (_effectTag2 & ShouldCapture) { - workInProgress.effectTag = (_effectTag2 & ~ShouldCapture) | DidCapture; // Captured a suspense effect. Re-render the boundary. + if ((sourceFiber.mode & BlockingMode) === NoMode) { + // Reset the memoizedState to what it was before we attempted + // to render it. + var currentSource = sourceFiber.alternate; - return workInProgress; + if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; + sourceFiber.memoizedState = currentSource.memoizedState; + sourceFiber.lanes = currentSource.lanes; + } else { + sourceFiber.updateQueue = null; + sourceFiber.memoizedState = null; } - - return null; } - case SuspenseListComponent: { - popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been - // caught by a nested boundary. If not, it should bubble through. - - return null; - } + var hasInvisibleParentBoundary = hasSuspenseContext( + suspenseStackCursor.current, + InvisibleParentSuspenseContext + ); // Schedule the nearest Suspense to re-render the timed out view. - case HostPortal: - popHostContainer(workInProgress); - return null; + var _workInProgress = returnFiber; - case ContextProvider: - popProvider(workInProgress); - return null; + do { + if ( + _workInProgress.tag === SuspenseComponent && + shouldCaptureSuspense(_workInProgress, hasInvisibleParentBoundary) + ) { + // Found the nearest boundary. + // Stash the promise on the boundary fiber. If the boundary times out, we'll + // attach another listener to flip the boundary back to its normal state. + var wakeables = _workInProgress.updateQueue; - default: - return null; - } -} + if (wakeables === null) { + var updateQueue = new Set(); + updateQueue.add(wakeable); + _workInProgress.updateQueue = updateQueue; + } else { + wakeables.add(wakeable); + } // If the boundary is outside of blocking mode, we should *not* + // suspend the commit. Pretend as if the suspended component rendered + // null and keep rendering. In the commit phase, we'll schedule a + // subsequent synchronous update to re-render the Suspense. + // + // Note: It doesn't matter whether the component that suspended was + // inside a blocking mode tree. If the Suspense is outside of it, we + // should *not* suspend the commit. -function unwindInterruptedWork(interruptedWork) { - switch (interruptedWork.tag) { - case ClassComponent: { - var childContextTypes = interruptedWork.type.childContextTypes; + if ((_workInProgress.mode & BlockingMode) === NoMode) { + _workInProgress.flags |= DidCapture; + sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. + // But we shouldn't call any lifecycle methods or callbacks. Remove + // all lifecycle effect tags. - if (childContextTypes !== null && childContextTypes !== undefined) { - popContext(interruptedWork); - } + sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); - break; - } + if (sourceFiber.tag === ClassComponent) { + var currentSourceFiber = sourceFiber.alternate; - case HostRoot: { - popHostContainer(interruptedWork); - popTopLevelContextObject(interruptedWork); - break; - } + if (currentSourceFiber === null) { + // This is a new mount. Change the tag so it's not mistaken for a + // completed class component. For example, we should not call + // componentWillUnmount if it is deleted. + sourceFiber.tag = IncompleteClassComponent; + } else { + // When we try rendering again, we should not reuse the current fiber, + // since it's known to be in an inconsistent state. Use a force update to + // prevent a bail out. + var update = createUpdate(NoTimestamp, SyncLane); + update.tag = ForceUpdate; + enqueueUpdate(sourceFiber, update); + } + } // The source fiber did not complete. Mark it with Sync priority to + // indicate that it still has pending work. - case HostComponent: { - popHostContext(interruptedWork); - break; - } + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); // Exit without suspending. - case HostPortal: - popHostContainer(interruptedWork); - break; + return; + } // Confirmed that the boundary is in a concurrent mode tree. Continue + // with the normal suspend path. + // + // After this we'll use a set of heuristics to determine whether this + // render pass will run to completion or restart or "suspend" the commit. + // The actual logic for this is spread out in different places. + // + // This first principle is that if we're going to suspend when we complete + // a root, then we should also restart if we get an update or ping that + // might unsuspend it, and vice versa. The only reason to suspend is + // because you think you might want to restart before committing. However, + // it doesn't make sense to restart only while in the period we're suspended. + // + // Restarting too aggressively is also not good because it starves out any + // intermediate loading state. So we use heuristics to determine when. + // Suspense Heuristics + // + // If nothing threw a Promise or all the same fallbacks are already showing, + // then don't suspend/restart. + // + // If this is an initial render of a new tree of Suspense boundaries and + // those trigger a fallback, then don't suspend/restart. We want to ensure + // that we can show the initial loading state as quickly as possible. + // + // If we hit a "Delayed" case, such as when we'd switch from content back into + // a fallback, then we should always suspend/restart. Transitions apply + // to this case. If none is defined, JND is used instead. + // + // If we're already showing a fallback and it gets "retried", allowing us to show + // another level, but there's still an inner boundary that would show a fallback, + // then we suspend/restart for 500ms since the last time we showed a fallback + // anywhere in the tree. This effectively throttles progressive loading into a + // consistent train of commits. This also gives us an opportunity to restart to + // get to the completed state slightly earlier. + // + // If there's ambiguity due to batching it's resolved in preference of: + // 1) "delayed", 2) "initial render", 3) "retry". + // + // We want to ensure that a "busy" state doesn't get force committed. We want to + // ensure that new initial loading states can commit as soon as possible. - case SuspenseComponent: - popSuspenseContext(interruptedWork); - break; + attachPingListener(root, wakeable, rootRenderLanes); + _workInProgress.flags |= ShouldCapture; + _workInProgress.lanes = rootRenderLanes; + return; + } // This boundary already captured during this render. Continue to the next + // boundary. - case SuspenseListComponent: - popSuspenseContext(interruptedWork); - break; + _workInProgress = _workInProgress.return; + } while (_workInProgress !== null); // No boundary was found. Fallthrough to error mode. + // TODO: Use invariant so the message is stripped in prod? - case ContextProvider: - popProvider(interruptedWork); - break; - } -} + value = new Error( + (getComponentName(sourceFiber.type) || "A React component") + + " suspended while rendering, but no fallback UI was specified.\n" + + "\n" + + "Add a component higher in the tree to " + + "provide a loading indicator or placeholder to display." + ); + } // We didn't find a boundary that could handle this type of exception. Start + // over and traverse parent path again, this time treating the exception + // as an error. -function createCapturedValue(value, source) { - // If the value is an error, call this function immediately after it is thrown - // so the stack is accurate. - return { - value: value, - source: source, - stack: getStackByFiberInDevAndProd(source) - }; -} + renderDidError(); + value = createCapturedValue(value, sourceFiber); + var workInProgress = returnFiber; -// Module provided by RN: + do { + switch (workInProgress.tag) { + case HostRoot: { + var _errorInfo = value; + workInProgress.flags |= ShouldCapture; + var lane = pickArbitraryLane(rootRenderLanes); + workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); -if ( - !( - typeof ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog === - "function" - ) -) { - throw Error( - "Expected ReactFiberErrorDialog.showErrorDialog to be a function." - ); -} + var _update = createRootErrorUpdate(workInProgress, _errorInfo, lane); -function showErrorDialog(capturedError) { - return ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ); -} + enqueueCapturedUpdate(workInProgress, _update); + return; + } -function logCapturedError(capturedError) { - var logError = showErrorDialog(capturedError); // Allow injected showErrorDialog() to prevent default console.error logging. - // This enables renderers like ReactNative to better manage redbox behavior. + case ClassComponent: + // Capture and retry + var errorInfo = value; + var ctor = workInProgress.type; + var instance = workInProgress.stateNode; - if (logError === false) { - return; - } + if ( + (workInProgress.flags & DidCapture) === NoFlags && + (typeof ctor.getDerivedStateFromError === "function" || + (instance !== null && + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance))) + ) { + workInProgress.flags |= ShouldCapture; - var error = capturedError.error; + var _lane = pickArbitraryLane(rootRenderLanes); - { - var componentName = capturedError.componentName, - componentStack = capturedError.componentStack, - errorBoundaryName = capturedError.errorBoundaryName, - errorBoundaryFound = capturedError.errorBoundaryFound, - willRetry = capturedError.willRetry; // Browsers support silencing uncaught errors by calling - // `preventDefault()` in window `error` handler. - // We record this information as an expando on the error. - - if (error != null && error._suppressLogging) { - if (errorBoundaryFound && willRetry) { - // The error is recoverable and was silenced. - // Ignore it and don't print the stack addendum. - // This is handy for testing error boundaries without noise. - return; - } // The error is fatal. Since the silencing might have - // been accidental, we'll surface it anyway. - // However, the browser would have silenced the original error - // so we'll print it first, and then print the stack addendum. + workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state - console["error"](error); // Don't transform to our wrapper - // For a more detailed description of this block, see: - // https://github.com/facebook/react/pull/13384 - } + var _update2 = createClassErrorUpdate( + workInProgress, + errorInfo, + _lane + ); - var componentNameMessage = componentName - ? "The above error occurred in the <" + componentName + "> component:" - : "The above error occurred in one of your React components:"; - var errorBoundaryMessage; // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow. + enqueueCapturedUpdate(workInProgress, _update2); + return; + } - if (errorBoundaryFound && errorBoundaryName) { - if (willRetry) { - errorBoundaryMessage = - "React will try to recreate this component tree from scratch " + - ("using the error boundary you provided, " + errorBoundaryName + "."); - } else { - errorBoundaryMessage = - "This error was initially handled by the error boundary " + - errorBoundaryName + - ".\n" + - "Recreating the tree from scratch failed so React will unmount the tree."; - } - } else { - errorBoundaryMessage = - "Consider adding an error boundary to your tree to customize error handling behavior.\n" + - "Visit https://fb.me/react-error-boundaries to learn more about error boundaries."; + break; } - var combinedMessage = - "" + - componentNameMessage + - componentStack + - "\n\n" + - ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. - // We don't include the original error message and JS stack because the browser - // has already printed it. Even if the application swallows the error, it is still - // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. - - console["error"](combinedMessage); // Don't transform to our wrapper - } + workInProgress = workInProgress.return; + } while (workInProgress !== null); } var didWarnAboutUndefinedSnapshotBeforeUpdate = null; @@ -15332,54 +16172,14 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; } var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source; - var stack = errorInfo.stack; - - if (stack === null && source !== null) { - stack = getStackByFiberInDevAndProd(source); - } - - var capturedError = { - componentName: source !== null ? getComponentName(source.type) : null, - componentStack: stack !== null ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: false, - willRetry: false - }; - - if (boundary !== null && boundary.tag === ClassComponent) { - capturedError.errorBoundary = boundary.stateNode; - capturedError.errorBoundaryName = getComponentName(boundary.type); - capturedError.errorBoundaryFound = true; - capturedError.willRetry = true; - } - - try { - logCapturedError(capturedError); - } catch (e) { - // This method must not throw, or React internal state will get messed up. - // If console.error is overridden, or logCapturedError() shows a dialog that throws, - // we want to report this error outside of the normal stack as a last resort. - // https://github.com/facebook/react/issues/13188 - setTimeout(function() { - throw e; - }); - } -} var callComponentWillUnmountWithTimer = function(current, instance) { - startPhaseTimer(current, "componentWillUnmount"); instance.props = current.memoizedProps; instance.state = current.memoizedState; { instance.componentWillUnmount(); } - - stopPhaseTimer(); }; // Capture errors so they don't interrupt unmounting. function safelyCallComponentWillUnmount(current, instance) { @@ -15405,7 +16205,9 @@ function safelyDetachRef(current) { if (ref !== null) { if (typeof ref === "function") { { - invokeGuardedCallback(null, ref, null, null); + { + invokeGuardedCallback(null, ref, null, null); + } if (hasCaughtError()) { var refError = clearCaughtError(); @@ -15433,17 +16235,15 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { return; } case ClassComponent: { - if (finishedWork.effectTag & Snapshot) { + if (finishedWork.flags & Snapshot) { if (current !== null) { var prevProps = current.memoizedProps; var prevState = current.memoizedState; - startPhaseTimer(finishedWork, "getSnapshotBeforeUpdate"); var instance = finishedWork.stateNode; // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -15499,14 +16299,23 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } instance.__reactInternalSnapshotBeforeUpdate = snapshot; - stopPhaseTimer(); } } return; } - case HostRoot: + case HostRoot: { + { + if (finishedWork.flags & Snapshot) { + var root = finishedWork.stateNode; + clearContainer(root.containerInfo); + } + } + + return; + } + case HostComponent: case HostText: case HostPortal: @@ -15583,16 +16392,15 @@ function commitHookEffectListMount(tag, finishedWork) { " }\n" + " fetchData();\n" + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + - "Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching"; + "Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"; } else { addendum = " You returned: " + destroy; } error( "An effect function must not return anything besides a function, " + - "which is used for clean-up.%s%s", - addendum, - getStackByFiberInDevAndProd(finishedWork) + "which is used for clean-up.%s", + addendum ); } } @@ -15603,38 +16411,34 @@ function commitHookEffectListMount(tag, finishedWork) { } } -function commitPassiveHookEffects(finishedWork) { - if ((finishedWork.effectTag & Passive) !== NoEffect) { - switch (finishedWork.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: - case Block: { - // TODO (#17945) We should call all passive destroy functions (for all fibers) - // before calling any create functions. The current approach only serializes - // these for a single fiber. - { - commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork); - commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); - } +function schedulePassiveEffects(finishedWork) { + var updateQueue = finishedWork.updateQueue; + var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; - break; + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + var effect = firstEffect; + + do { + var _effect = effect, + next = _effect.next, + tag = _effect.tag; + + if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) { + enqueuePendingPassiveHookEffectUnmount(finishedWork, effect); + enqueuePendingPassiveHookEffectMount(finishedWork, effect); } - } + + effect = next; + } while (effect !== firstEffect); } } -function commitLifeCycles( - finishedRoot, - current, - finishedWork, - committedExpirationTime -) { +function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) { switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // At this point layout effects have already been destroyed (during mutation phase). // This is done to prevent sibling component effects from interfering with each other, // e.g. a destroy function in one component should never override a ref set @@ -15643,18 +16447,18 @@ function commitLifeCycles( commitHookEffectListMount(Layout | HasEffect, finishedWork); } + schedulePassiveEffects(finishedWork); return; } case ClassComponent: { var instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update) { + if (finishedWork.flags & Update) { if (current === null) { - startPhaseTimer(finishedWork, "componentDidMount"); // We could update instance props and state here, + // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. - { if ( finishedWork.type === finishedWork.elementType && @@ -15687,15 +16491,12 @@ function commitLifeCycles( { instance.componentDidMount(); } - - stopPhaseTimer(); } else { var prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps); - var prevState = current.memoizedState; - startPhaseTimer(finishedWork, "componentDidUpdate"); // We could update instance props and state here, + var prevState = current.memoizedState; // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -15735,10 +16536,9 @@ function commitLifeCycles( instance.__reactInternalSnapshotBeforeUpdate ); } - - stopPhaseTimer(); } - } + } // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. var updateQueue = finishedWork.updateQueue; @@ -15781,6 +16581,8 @@ function commitLifeCycles( } case HostRoot: { + // TODO: I think this is now always non-null by the time it reaches the + // commit phase. Consider removing the type check. var _updateQueue = finishedWork.updateQueue; if (_updateQueue !== null) { @@ -15810,7 +16612,7 @@ function commitLifeCycles( // These effects should only be committed when components are first mounted, // aka when there is no current/alternate. - if (current === null && finishedWork.effectTag & Update) { + if (current === null && finishedWork.flags & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; } @@ -15862,6 +16664,8 @@ function commitLifeCycles( case IncompleteClassComponent: case FundamentalComponent: case ScopeComponent: + case OffscreenComponent: + case LegacyHiddenComponent: return; } @@ -15896,17 +16700,12 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) { unhideTextInstance(_instance3, node.memoizedProps); } } else if ( - node.tag === SuspenseComponent && + (node.tag === OffscreenComponent || + node.tag === LegacyHiddenComponent) && node.memoizedState !== null && - node.memoizedState.dehydrated === null - ) { - // Found a nested Suspense component that timed out. Skip over the - // primary child fragment, which should remain hidden. - var fallbackChildFragment = node.child.sibling; - fallbackChildFragment.return = node; - node = fallbackChildFragment; - continue; - } else if (node.child !== null) { + node !== finishedWork + ); + else if (node.child !== null) { node.child.return = node; node = node.child; continue; @@ -15947,15 +16746,16 @@ function commitAttachRef(finishedWork) { } // Moved outside to ensure DCE works with this flag if (typeof ref === "function") { - ref(instanceToUse); + { + ref(instanceToUse); + } } else { { if (!ref.hasOwnProperty("current")) { error( "Unexpected ref object provided for %s. " + - "Use either a ref-setter function or React.createRef().%s", - getComponentName(finishedWork.type), - getStackByFiberInDevAndProd(finishedWork) + "Use either a ref-setter function or React.createRef().", + getComponentName(finishedWork.type) ); } } @@ -15970,7 +16770,9 @@ function commitDetachRef(current) { if (currentRef !== null) { if (typeof currentRef === "function") { - currentRef(null); + { + currentRef(null); + } } else { currentRef.current = null; } @@ -15986,8 +16788,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { var updateQueue = current.updateQueue; if (updateQueue !== null) { @@ -15995,42 +16796,25 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { if (lastEffect !== null) { var firstEffect = lastEffect.next; + var effect = firstEffect; - { - // When the owner fiber is deleted, the destroy function of a passive - // effect hook is called during the synchronous commit phase. This is - // a concession to implementation complexity. Calling it in the - // passive effect phase (like they usually are, when dependencies - // change during an update) would require either traversing the - // children of the deleted fiber again, or including unmount effects - // as part of the fiber effect list. - // - // Because this is during the sync commit phase, we need to change - // the priority. - // - // TODO: Reconsider this implementation trade off. - var priorityLevel = - renderPriorityLevel > NormalPriority - ? NormalPriority - : renderPriorityLevel; - runWithPriority(priorityLevel, function() { - var effect = firstEffect; - - do { - var _effect3 = effect, - _destroy = _effect3.destroy, - _tag = _effect3.tag; - - if (_destroy !== undefined) { - { - safelyCallDestroy(current, _destroy); - } + do { + var _effect2 = effect, + destroy = _effect2.destroy, + tag = _effect2.tag; + + if (destroy !== undefined) { + if ((tag & Passive$1) !== NoFlags$1) { + enqueuePendingPassiveHookEffectUnmount(current, effect); + } else { + { + safelyCallDestroy(current, destroy); } + } + } - effect = effect.next; - } while (effect !== firstEffect); - }); - } + effect = effect.next; + } while (effect !== firstEffect); } } @@ -16058,7 +16842,7 @@ function commitUnmount(finishedRoot, current, renderPriorityLevel) { // We are also not using this parent because // the portal will get pushed immediately. { - unmountHostComponents(finishedRoot, current, renderPriorityLevel); + unmountHostComponents(finishedRoot, current); } return; @@ -16087,7 +16871,7 @@ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) { var node = root; while (true) { - commitUnmount(finishedRoot, node, renderPriorityLevel); // Visit children because they may contain more composite or host nodes. + commitUnmount(finishedRoot, node); // Visit children because they may contain more composite or host nodes. // Skip portals because commitUnmount() currently visits them recursively. if ( @@ -16117,27 +16901,33 @@ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) { } } -function detachFiber(current) { - var alternate = current.alternate; // Cut off the return pointers to disconnect it from the tree. Ideally, we +function detachFiberMutation(fiber) { + // Cut off the return pointers to disconnect it from the tree. Ideally, we // should clear the child pointer of the parent alternate to let this // get GC:ed but we don't know which for sure which parent is the current // one so we'll settle for GC:ing the subtree of this child. This child // itself will be GC:ed when the parent updates the next time. + // Note: we cannot null out sibling here, otherwise it can cause issues + // with findDOMNode and how it requires the sibling field to carry out + // traversal in a later effect. See PR #16820. We now clear the sibling + // field after effects, see: detachFiberAfterEffects. + // + // Don't disconnect stateNode now; it will be detached in detachFiberAfterEffects. + // It may be required if the current component is an error boundary, + // and one of its descendants throws while unmounting a passive effect. + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - - if (alternate !== null) { - detachFiber(alternate); + { + fiber._debugOwner = null; } } @@ -16196,7 +16986,7 @@ function getHostSibling(fiber) { ) { // If it is not host node and, we might have a host node inside it. // Try to search down until we find one. - if (node.effectTag & Placement) { + if (node.flags & Placement) { // If we don't have a child, try the siblings instead. continue siblings; } // If we don't have a child, try the siblings instead. @@ -16210,7 +17000,7 @@ function getHostSibling(fiber) { } } // Check if this host node is stable or about to be placed. - if (!(node.effectTag & Placement)) { + if (!(node.flags & Placement)) { // Found it! return node.stateNode; } @@ -16251,8 +17041,8 @@ function commitPlacement(finishedWork) { } } - if (parentFiber.effectTag & ContentReset) { - parentFiber.effectTag &= ~ContentReset; + if (parentFiber.flags & ContentReset) { + parentFiber.flags &= ~ContentReset; } var before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its @@ -16369,7 +17159,7 @@ function unmountHostComponents(finishedRoot, current, renderPriorityLevel) { } if (node.tag === HostComponent || node.tag === HostText) { - commitNestedUnmounts(finishedRoot, node, renderPriorityLevel); // After all the children have unmounted, it is now safe to remove the + commitNestedUnmounts(finishedRoot, node); // After all the children have unmounted, it is now safe to remove the // node from the tree. if (currentParentIsContainer) { @@ -16389,7 +17179,7 @@ function unmountHostComponents(finishedRoot, current, renderPriorityLevel) { continue; } } else { - commitUnmount(finishedRoot, node, renderPriorityLevel); // Visit children because we may find more host components below. + commitUnmount(finishedRoot, node); // Visit children because we may find more host components below. if (node.child !== null) { node.child.return = node; @@ -16425,10 +17215,15 @@ function commitDeletion(finishedRoot, current, renderPriorityLevel) { { // Recursively delete all host nodes from the parent. // Detach refs and call componentWillUnmount() on the whole subtree. - unmountHostComponents(finishedRoot, current, renderPriorityLevel); + unmountHostComponents(finishedRoot, current); } - detachFiber(current); + var alternate = current.alternate; + detachFiberMutation(current); + + if (alternate !== null) { + detachFiberMutation(alternate); + } } function commitWork(current, finishedWork) { @@ -16436,8 +17231,7 @@ function commitWork(current, finishedWork) { case FunctionComponent: case ForwardRef: case MemoComponent: - case SimpleMemoComponent: - case Block: { + case SimpleMemoComponent: { // Layout effects are destroyed during the mutation phase so that all // destroy functions for all fibers are called before any create functions. // This prevents sibling component effects from interfering with each other, @@ -16508,3118 +17302,3275 @@ function commitWork(current, finishedWork) { return; } - case SuspenseListComponent: { - attachSuspenseRetryListeners(finishedWork); - return; - } + case SuspenseListComponent: { + attachSuspenseRetryListeners(finishedWork); + return; + } + + case IncompleteClassComponent: { + return; + } + + case FundamentalComponent: { + break; + } + + case ScopeComponent: { + break; + } + + case OffscreenComponent: + case LegacyHiddenComponent: { + var newState = finishedWork.memoizedState; + var isHidden = newState !== null; + hideOrUnhideAllChildren(finishedWork, isHidden); + return; + } + } + + { + throw Error( + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." + ); + } +} + +function commitSuspenseComponent(finishedWork) { + var newState = finishedWork.memoizedState; + + if (newState !== null) { + markCommitTimeOfFallback(); + + { + // Hide the Offscreen component that contains the primary children. TODO: + // Ideally, this effect would have been scheduled on the Offscreen fiber + // itself. That's how unhiding works: the Offscreen component schedules an + // effect on itself. However, in this case, the component didn't complete, + // so the fiber was never added to the effect list in the normal path. We + // could have appended it to the effect list in the Suspense component's + // second pass, but doing it this way is less complicated. This would be + // simpler if we got rid of the effect list and traversed the tree, like + // we're planning to do. + var primaryChildParent = finishedWork.child; + hideOrUnhideAllChildren(primaryChildParent, true); + } + } +} + +function attachSuspenseRetryListeners(finishedWork) { + // If this boundary just timed out, then it will have a set of wakeables. + // For each wakeable, attach a listener so that when it resolves, React + // attempts to re-render the boundary in the primary (pre-timeout) state. + var wakeables = finishedWork.updateQueue; + + if (wakeables !== null) { + finishedWork.updateQueue = null; + var retryCache = finishedWork.stateNode; + + if (retryCache === null) { + retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + } + + wakeables.forEach(function(wakeable) { + // Memoize using the boundary fiber to prevent redundant listeners. + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + + if (!retryCache.has(wakeable)) { + { + if (wakeable.__reactDoNotTraceInteractions !== true) { + retry = tracing.unstable_wrap(retry); + } + } + + retryCache.add(wakeable); + wakeable.then(retry, retry); + } + }); + } +} // This function detects when a Suspense boundary goes from visible to hidden. +// It returns false if the boundary is already hidden. +// TODO: Use an effect tag. + +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + if (current !== null) { + var oldState = current.memoizedState; + + if (oldState === null || oldState.dehydrated !== null) { + var newState = finishedWork.memoizedState; + return newState !== null && newState.dehydrated === null; + } + } + + return false; +} + +function commitResetTextContent(current) { + resetTextContent(current.stateNode); +} + +var COMPONENT_TYPE = 0; +var HAS_PSEUDO_CLASS_TYPE = 1; +var ROLE_TYPE = 2; +var TEST_NAME_TYPE = 3; +var TEXT_TYPE = 4; + +if (typeof Symbol === "function" && Symbol.for) { + var symbolFor$1 = Symbol.for; + COMPONENT_TYPE = symbolFor$1("selector.component"); + HAS_PSEUDO_CLASS_TYPE = symbolFor$1("selector.has_pseudo_class"); + ROLE_TYPE = symbolFor$1("selector.role"); + TEST_NAME_TYPE = symbolFor$1("selector.test_id"); + TEXT_TYPE = symbolFor$1("selector.text"); +} + +var ceil = Math.ceil; +var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, + IsSomeRendererActing = ReactSharedInternals.IsSomeRendererActing; +var NoContext = + /* */ + 0; +var BatchedContext = + /* */ + 1; +var DiscreteEventContext = + /* */ + 4; +var LegacyUnbatchedContext = + /* */ + 8; +var RenderContext = + /* */ + 16; +var CommitContext = + /* */ + 32; +var RetryAfterError = + /* */ + 64; +var RootIncomplete = 0; +var RootFatalErrored = 1; +var RootErrored = 2; +var RootSuspended = 3; +var RootSuspendedWithDelay = 4; +var RootCompleted = 5; // Describes where we are in the React execution stack + +var executionContext = NoContext; // The root we're working on + +var workInProgressRoot = null; // The fiber we're working on + +var workInProgress = null; // The lanes we're rendering + +var workInProgressRootRenderLanes = NoLanes; // Stack that allows components to change the render lanes for its subtree +// This is a superset of the lanes we started working on at the root. The only +// case where it's different from `workInProgressRootRenderLanes` is when we +// enter a subtree that is hidden and needs to be unhidden: Suspense and +// Offscreen component. +// +// Most things in the work loop should deal with workInProgressRootRenderLanes. +// Most things in begin/complete phases should deal with subtreeRenderLanes. + +var subtreeRenderLanes = NoLanes; +var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. + +var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown + +var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's +// slightly different than `renderLanes` because `renderLanes` can change as you +// enter and exit an Offscreen tree. This value is the combination of all render +// lanes for the entire render phase. + +var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only +// includes unprocessed updates, not work in bailed out children. + +var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. + +var workInProgressRootUpdatedLanes = NoLanes; // Lanes that were pinged (in an interleaved event) during this render. + +var workInProgressRootPingedLanes = NoLanes; +var mostRecentlyUpdatedRoot = null; // The most recent time we committed a fallback. This lets us ensure a train +// model where we don't commit new loading states in too quick succession. + +var globalMostRecentFallbackTime = 0; +var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering +// more and prefer CPU suspense heuristics instead. + +var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU +// suspense heuristics and opt out of rendering more content. + +var RENDER_TIMEOUT_MS = 500; + +function resetRenderTimer() { + workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; +} + +function getRenderTargetTime() { + return workInProgressRootRenderTargetTime; +} +var nextEffect = null; +var hasUncaughtError = false; +var firstUncaughtError = null; +var legacyErrorBoundariesThatAlreadyFailed = null; +var rootDoesHavePassiveEffects = false; +var rootWithPendingPassiveEffects = null; +var pendingPassiveEffectsRenderPriority = NoPriority$1; +var pendingPassiveEffectsLanes = NoLanes; +var pendingPassiveHookEffectsMount = []; +var pendingPassiveHookEffectsUnmount = []; +var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates + +var NESTED_UPDATE_LIMIT = 50; +var nestedUpdateCount = 0; +var rootWithNestedUpdates = null; +var NESTED_PASSIVE_UPDATE_LIMIT = 50; +var nestedPassiveUpdateCount = 0; // Marks the need to reschedule pending interactions at these lanes +// during the commit phase. This enables them to be traced across components +// that spawn new work during render. E.g. hidden boundaries, suspended SSR +// hydration or SuspenseList. +// TODO: Can use a bitmask instead of an array + +var spawnedWorkDuringRender = null; // If two updates are scheduled within the same event, we should treat their +// event times as simultaneous, even if the actual clock time has advanced +// between the first and second call. - case IncompleteClassComponent: { - return; - } - } +var currentEventTime = NoTimestamp; +var currentEventWipLanes = NoLanes; +var currentEventPendingLanes = NoLanes; // Dev only flag that tracks if passive effects are currently being flushed. +// We warn about state updates for unmounted components differently in this case. - { - throw Error( - "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." - ); - } +var isFlushingPassiveEffects = false; +var focusedInstanceHandle = null; +var shouldFireAfterActiveInstanceBlur = false; +function getWorkInProgressRoot() { + return workInProgressRoot; } +function requestEventTime() { + if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { + // We're inside React, so it's fine to read the actual time. + return now(); + } // We're not inside React, so we may be in the middle of a browser event. -function commitSuspenseComponent(finishedWork) { - var newState = finishedWork.memoizedState; - var newDidTimeout; - var primaryChildParent = finishedWork; - - if (newState === null) { - newDidTimeout = false; - } else { - newDidTimeout = true; - primaryChildParent = finishedWork.child; - markCommitTimeOfFallback(); - } + if (currentEventTime !== NoTimestamp) { + // Use the same start time for all updates until we enter React again. + return currentEventTime; + } // This is the first update since React yielded. Compute a new start time. - if (primaryChildParent !== null) { - hideOrUnhideAllChildren(primaryChildParent, newDidTimeout); - } + currentEventTime = now(); + return currentEventTime; } +function requestUpdateLane(fiber) { + // Special cases + var mode = fiber.mode; -function attachSuspenseRetryListeners(finishedWork) { - // If this boundary just timed out, then it will have a set of thenables. - // For each thenable, attach a listener so that when it resolves, React - // attempts to re-render the boundary in the primary (pre-timeout) state. - var thenables = finishedWork.updateQueue; + if ((mode & BlockingMode) === NoMode) { + return SyncLane; + } else if ((mode & ConcurrentMode) === NoMode) { + return getCurrentPriorityLevel() === ImmediatePriority$1 + ? SyncLane + : SyncBatchedLane; + } // The algorithm for assigning an update to a lane should be stable for all + // updates at the same priority within the same event. To do this, the inputs + // to the algorithm must be the same. For example, we use the `renderLanes` + // to avoid choosing a lane that is already in the middle of rendering. + // + // However, the "included" lanes could be mutated in between updates in the + // same event, like if you perform an update inside `flushSync`. Or any other + // code path that might call `prepareFreshStack`. + // + // The trick we use is to cache the first of each of these inputs within an + // event. Then reset the cached values once we can be sure the event is over. + // Our heuristic for that is whenever we enter a concurrent work loop. + // + // We'll do the same for `currentEventPendingLanes` below. - if (thenables !== null) { - finishedWork.updateQueue = null; - var retryCache = finishedWork.stateNode; + if (currentEventWipLanes === NoLanes) { + currentEventWipLanes = workInProgressRootIncludedLanes; + } - if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + var isTransition = requestCurrentTransition() !== NoTransition; + + if (isTransition) { + if (currentEventPendingLanes !== NoLanes) { + currentEventPendingLanes = + mostRecentlyUpdatedRoot !== null + ? mostRecentlyUpdatedRoot.pendingLanes + : NoLanes; } - thenables.forEach(function(thenable) { - // Memoize using the boundary fiber to prevent redundant listeners. - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); + return findTransitionLane(currentEventWipLanes, currentEventPendingLanes); + } // TODO: Remove this dependency on the Scheduler priority. + // To do that, we're replacing it with an update lane priority. - if (!retryCache.has(thenable)) { - { - if (thenable.__reactDoNotTraceInteractions !== true) { - retry = tracing.unstable_wrap(retry); - } - } + var schedulerPriority = getCurrentPriorityLevel(); // The old behavior was using the priority level of the Scheduler. + // This couples React to the Scheduler internals, so we're replacing it + // with the currentUpdateLanePriority above. As an example of how this + // could be problematic, if we're not inside `Scheduler.runWithPriority`, + // then we'll get the priority of the current running Scheduler task, + // which is probably not what we want. - retryCache.add(thenable); - thenable.then(retry, retry); - } - }); - } -} + var lane; -function commitResetTextContent(current) { - resetTextContent(current.stateNode); -} + if ( + // TODO: Temporary. We're removing the concept of discrete updates. + (executionContext & DiscreteEventContext) !== NoContext && + schedulerPriority === UserBlockingPriority$1 + ) { + lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes); + } else { + var schedulerLanePriority = schedulerPriorityToLanePriority( + schedulerPriority + ); -var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes); + } -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - var update = createUpdate(expirationTime, null); // Unmount the root by rendering null. + return lane; +} - update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property - // being called "element". +function requestRetryLane(fiber) { + // This is a fork of `requestUpdateLane` designed specifically for Suspense + // "retries" — a special update that attempts to flip a Suspense boundary + // from its placeholder state to its primary/resolved state. + // Special cases + var mode = fiber.mode; - update.payload = { - element: null - }; - var error = errorInfo.value; + if ((mode & BlockingMode) === NoMode) { + return SyncLane; + } else if ((mode & ConcurrentMode) === NoMode) { + return getCurrentPriorityLevel() === ImmediatePriority$1 + ? SyncLane + : SyncBatchedLane; + } // See `requestUpdateLane` for explanation of `currentEventWipLanes` - update.callback = function() { - onUncaughtError(error); - logError(fiber, errorInfo); - }; + if (currentEventWipLanes === NoLanes) { + currentEventWipLanes = workInProgressRootIncludedLanes; + } - return update; + return findRetryLane(currentEventWipLanes); } -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - var update = createUpdate(expirationTime, null); - update.tag = CaptureUpdate; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; +function scheduleUpdateOnFiber(fiber, lane, eventTime) { + checkForNestedUpdates(); + warnAboutRenderPhaseUpdatesInDEV(fiber); + var root = markUpdateLaneFromFiberToRoot(fiber, lane); - if (typeof getDerivedStateFromError === "function") { - var error$1 = errorInfo.value; + if (root === null) { + warnAboutUpdateOnUnmountedFiberInDEV(fiber); + return null; + } // Mark that the root has a pending update. - update.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error$1); - }; - } + markRootUpdated(root, lane, eventTime); - var inst = fiber.stateNode; + if (root === workInProgressRoot) { + // Received an update to a tree that's in the middle of rendering. Mark + // that there was an interleaved update work on this root. Unless the + // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render + // phase update. In that case, we don't treat render phase updates as if + // they were interleaved, for backwards compat reasons. + { + workInProgressRootUpdatedLanes = mergeLanes( + workInProgressRootUpdatedLanes, + lane + ); + } - if (inst !== null && typeof inst.componentDidCatch === "function") { - update.callback = function callback() { - { - markFailedErrorBoundaryForHotReloading(fiber); - } + if (workInProgressRootExitStatus === RootSuspendedWithDelay) { + // The root already suspended with a delay, which means this render + // definitely won't finish. Since we have a new update, let's mark it as + // suspended now, right before marking the incoming update. This has the + // effect of interrupting the current render and switching to the update. + // TODO: Make sure this doesn't override pings that happen while we've + // already started rendering. + markRootSuspended$1(root, workInProgressRootRenderLanes); + } + } // TODO: requestUpdateLanePriority also reads the priority. Pass the + // priority as an argument to that function and this one. - if (typeof getDerivedStateFromError !== "function") { - // To preserve the preexisting retry behavior of error boundaries, - // we keep track of which ones already failed during this batch. - // This gets reset before we yield back to the browser. - // TODO: Warn in strict mode if getDerivedStateFromError is - // not defined. - markLegacyErrorBoundaryAsFailed(this); // Only log here if componentDidCatch is the only error boundary method defined + var priorityLevel = getCurrentPriorityLevel(); - logError(fiber, errorInfo); - } + if (lane === SyncLane) { + if ( + // Check if we're inside unbatchedUpdates + (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering + (executionContext & (RenderContext | CommitContext)) === NoContext + ) { + // Register pending interactions on the root to avoid losing traced interaction data. + schedulePendingInteractions(root, lane); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed + // root inside of batchedUpdates should be synchronous, but layout updates + // should be deferred until the end of the batch. - var error$1 = errorInfo.value; - var stack = errorInfo.stack; - this.componentDidCatch(error$1, { - componentStack: stack !== null ? stack : "" - }); + performSyncWorkOnRoot(root); + } else { + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, lane); - { - if (typeof getDerivedStateFromError !== "function") { - // If componentDidCatch is the only error boundary method defined, - // then it needs to call setState to recover from errors. - // If no state update is scheduled then the boundary will swallow the error. - if (fiber.expirationTime !== Sync) { - error( - "%s: Error boundaries should implement getDerivedStateFromError(). " + - "In that method, return a state update to display an error message or fallback UI.", - getComponentName(fiber.type) || "Unknown" - ); - } - } + if (executionContext === NoContext) { + // Flush the synchronous work now, unless we're already working or inside + // a batch. This is intentionally inside scheduleUpdateOnFiber instead of + // scheduleCallbackForFiber to preserve the ability to schedule a callback + // without immediately flushing it. We only do this for user-initiated + // updates, to preserve historical behavior of legacy mode. + resetRenderTimer(); + flushSyncCallbackQueue(); } - }; + } } else { - update.callback = function() { - markFailedErrorBoundaryForHotReloading(fiber); - }; + // Schedule a discrete update but only if it's not Sync. + if ( + (executionContext & DiscreteEventContext) !== NoContext && // Only updates at user-blocking priority or greater are considered + // discrete, even inside a discrete event. + (priorityLevel === UserBlockingPriority$1 || + priorityLevel === ImmediatePriority$1) + ) { + // This is the result of a discrete event. Track the lowest priority + // discrete update per root so we can flush them early, if needed. + if (rootsWithPendingDiscreteUpdates === null) { + rootsWithPendingDiscreteUpdates = new Set([root]); + } else { + rootsWithPendingDiscreteUpdates.add(root); + } + } // Schedule other updates after in case the callback is sync. + + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, lane); + } // We use this when assigning a lane for a transition inside + // `requestUpdateLane`. We assume it's the same as the root being updated, + // since in the common case of a single root app it probably is. If it's not + // the same root, then it's not a huge deal, we just might batch more stuff + // together more than necessary. + + mostRecentlyUpdatedRoot = root; +} // This is split into a separate function so we can mark a fiber with pending +// work without treating it as a typical update that originates from an event; +// e.g. retrying a Suspense boundary isn't an update, but it does schedule work +// on a fiber. + +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + // Update the source fiber's lanes + sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); + var alternate = sourceFiber.alternate; + + if (alternate !== null) { + alternate.lanes = mergeLanes(alternate.lanes, lane); } - return update; -} + { + if ( + alternate === null && + (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags + ) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } // Walk the parent path to the root and update the child expiration time. -function attachPingListener(root, renderExpirationTime, thenable) { - // Attach a listener to the promise to "ping" the root and retry. But - // only if one does not already exist for the current render expiration - // time (which acts like a "thread ID" here). - var pingCache = root.pingCache; - var threadIDs; + var node = sourceFiber; + var parent = sourceFiber.return; - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } else { - threadIDs = pingCache.get(thenable); + while (parent !== null) { + parent.childLanes = mergeLanes(parent.childLanes, lane); + alternate = parent.alternate; - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); + if (alternate !== null) { + alternate.childLanes = mergeLanes(alternate.childLanes, lane); + } else { + { + if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { + warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); + } + } } + + node = parent; + parent = parent.return; } - if (!threadIDs.has(renderExpirationTime)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(renderExpirationTime); - var ping = pingSuspendedRoot.bind( - null, - root, - thenable, - renderExpirationTime - ); - thenable.then(ping, ping); + if (node.tag === HostRoot) { + var root = node.stateNode; + return root; + } else { + return null; } -} +} // Use this function to schedule a task for a root. There's only one task per +// root; if a task was already scheduled, we'll check to make sure the priority +// of the existing task is the same as the priority of the next level that the +// root has work on. This function is called on every update, and right before +// exiting a task. -function throwException( - root, - returnFiber, - sourceFiber, - value, - renderExpirationTime -) { - // The source fiber did not complete. - sourceFiber.effectTag |= Incomplete; // Its effect list is no longer valid. +function ensureRootIsScheduled(root, currentTime) { + var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as + // expired so we know to work on those next. - sourceFiber.firstEffect = sourceFiber.lastEffect = null; + markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. - if ( - value !== null && - typeof value === "object" && - typeof value.then === "function" - ) { - // This is a thenable. - var thenable = value; + var nextLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); // This returns the priority level computed during the `getNextLanes` call. - if ((sourceFiber.mode & BlockingMode) === NoMode) { - // Reset the memoizedState to what it was before we attempted - // to render it. - var currentSource = sourceFiber.alternate; + var newCallbackPriority = returnNextLanesPriority(); - if (currentSource) { - sourceFiber.updateQueue = currentSource.updateQueue; - sourceFiber.memoizedState = currentSource.memoizedState; - sourceFiber.expirationTime = currentSource.expirationTime; - } else { - sourceFiber.updateQueue = null; - sourceFiber.memoizedState = null; - } + if (nextLanes === NoLanes) { + // Special case: There's nothing to work on. + if (existingCallbackNode !== null) { + cancelCallback(existingCallbackNode); + root.callbackNode = null; + root.callbackPriority = NoLanePriority; } - var hasInvisibleParentBoundary = hasSuspenseContext( - suspenseStackCursor.current, - InvisibleParentSuspenseContext - ); // Schedule the nearest Suspense to re-render the timed out view. - - var _workInProgress = returnFiber; + return; + } // Check if there's an existing task. We may be able to reuse it. - do { - if ( - _workInProgress.tag === SuspenseComponent && - shouldCaptureSuspense(_workInProgress, hasInvisibleParentBoundary) - ) { - // Found the nearest boundary. - // Stash the promise on the boundary fiber. If the boundary times out, we'll - // attach another listener to flip the boundary back to its normal state. - var thenables = _workInProgress.updateQueue; + if (existingCallbackNode !== null) { + var existingCallbackPriority = root.callbackPriority; - if (thenables === null) { - var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else { - thenables.add(thenable); - } // If the boundary is outside of blocking mode, we should *not* - // suspend the commit. Pretend as if the suspended component rendered - // null and keep rendering. In the commit phase, we'll schedule a - // subsequent synchronous update to re-render the Suspense. - // - // Note: It doesn't matter whether the component that suspended was - // inside a blocking mode tree. If the Suspense is outside of it, we - // should *not* suspend the commit. + if (existingCallbackPriority === newCallbackPriority) { + // The priority hasn't changed. We can reuse the existing task. Exit. + return; + } // The priority changed. Cancel the existing callback. We'll schedule a new + // one below. - if ((_workInProgress.mode & BlockingMode) === NoMode) { - _workInProgress.effectTag |= DidCapture; // We're going to commit this fiber even though it didn't complete. - // But we shouldn't call any lifecycle methods or callbacks. Remove - // all lifecycle effect tags. + cancelCallback(existingCallbackNode); + } // Schedule a new callback. - sourceFiber.effectTag &= ~(LifecycleEffectMask | Incomplete); + var newCallbackNode; - if (sourceFiber.tag === ClassComponent) { - var currentSourceFiber = sourceFiber.alternate; + if (newCallbackPriority === SyncLanePriority) { + // Special case: Sync React callbacks are scheduled on a special + // internal queue + newCallbackNode = scheduleSyncCallback( + performSyncWorkOnRoot.bind(null, root) + ); + } else if (newCallbackPriority === SyncBatchedLanePriority) { + newCallbackNode = scheduleCallback( + ImmediatePriority$1, + performSyncWorkOnRoot.bind(null, root) + ); + } else { + var schedulerPriorityLevel = lanePriorityToSchedulerPriority( + newCallbackPriority + ); + newCallbackNode = scheduleCallback( + schedulerPriorityLevel, + performConcurrentWorkOnRoot.bind(null, root) + ); + } - if (currentSourceFiber === null) { - // This is a new mount. Change the tag so it's not mistaken for a - // completed class component. For example, we should not call - // componentWillUnmount if it is deleted. - sourceFiber.tag = IncompleteClassComponent; - } else { - // When we try rendering again, we should not reuse the current fiber, - // since it's known to be in an inconsistent state. Use a force update to - // prevent a bail out. - var update = createUpdate(Sync, null); - update.tag = ForceUpdate; - enqueueUpdate(sourceFiber, update); - } - } // The source fiber did not complete. Mark it with Sync priority to - // indicate that it still has pending work. + root.callbackPriority = newCallbackPriority; + root.callbackNode = newCallbackNode; +} // This is the entry point for every concurrent task, i.e. anything that +// goes through Scheduler. - sourceFiber.expirationTime = Sync; // Exit without suspending. +function performConcurrentWorkOnRoot(root) { + // Since we know we're in a React event, we can clear the current + // event time. The next update will compute a new event time. + currentEventTime = NoTimestamp; + currentEventWipLanes = NoLanes; + currentEventPendingLanes = NoLanes; - return; - } // Confirmed that the boundary is in a concurrent mode tree. Continue - // with the normal suspend path. - // - // After this we'll use a set of heuristics to determine whether this - // render pass will run to completion or restart or "suspend" the commit. - // The actual logic for this is spread out in different places. - // - // This first principle is that if we're going to suspend when we complete - // a root, then we should also restart if we get an update or ping that - // might unsuspend it, and vice versa. The only reason to suspend is - // because you think you might want to restart before committing. However, - // it doesn't make sense to restart only while in the period we're suspended. - // - // Restarting too aggressively is also not good because it starves out any - // intermediate loading state. So we use heuristics to determine when. - // Suspense Heuristics - // - // If nothing threw a Promise or all the same fallbacks are already showing, - // then don't suspend/restart. - // - // If this is an initial render of a new tree of Suspense boundaries and - // those trigger a fallback, then don't suspend/restart. We want to ensure - // that we can show the initial loading state as quickly as possible. - // - // If we hit a "Delayed" case, such as when we'd switch from content back into - // a fallback, then we should always suspend/restart. SuspenseConfig applies to - // this case. If none is defined, JND is used instead. - // - // If we're already showing a fallback and it gets "retried", allowing us to show - // another level, but there's still an inner boundary that would show a fallback, - // then we suspend/restart for 500ms since the last time we showed a fallback - // anywhere in the tree. This effectively throttles progressive loading into a - // consistent train of commits. This also gives us an opportunity to restart to - // get to the completed state slightly earlier. - // - // If there's ambiguity due to batching it's resolved in preference of: - // 1) "delayed", 2) "initial render", 3) "retry". - // - // We want to ensure that a "busy" state doesn't get force committed. We want to - // ensure that new initial loading states can commit as soon as possible. + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); + } // Flush any pending passive effects before deciding which lanes to work on, + // in case they schedule additional work. - attachPingListener(root, renderExpirationTime, thenable); - _workInProgress.effectTag |= ShouldCapture; - _workInProgress.expirationTime = renderExpirationTime; - return; - } // This boundary already captured during this render. Continue to the next - // boundary. + var originalCallbackNode = root.callbackNode; + var didFlushPassiveEffects = flushPassiveEffects(); + + if (didFlushPassiveEffects) { + // Something in the passive effect phase may have canceled the current task. + // Check if the task node for this root was changed. + if (root.callbackNode !== originalCallbackNode) { + // The current task was canceled. Exit. We don't need to call + // `ensureRootIsScheduled` because the check above implies either that + // there's a new task, or that there's no remaining work on this root. + return null; + } + } // Determine the next expiration time to work on, using the fields stored + // on the root. - _workInProgress = _workInProgress.return; - } while (_workInProgress !== null); // No boundary was found. Fallthrough to error mode. - // TODO: Use invariant so the message is stripped in prod? + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes + ); - value = new Error( - (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n" + - "\n" + - "Add a component higher in the tree to " + - "provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) - ); - } // We didn't find a boundary that could handle this type of exception. Start - // over and traverse parent path again, this time treating the exception - // as an error. + if (lanes === NoLanes) { + // Defensive coding. This is never expected to happen. + return null; + } - renderDidError(); - value = createCapturedValue(value, sourceFiber); - var workInProgress = returnFiber; + var exitStatus = renderRootConcurrent(root, lanes); - do { - switch (workInProgress.tag) { - case HostRoot: { - var _errorInfo = value; - workInProgress.effectTag |= ShouldCapture; - workInProgress.expirationTime = renderExpirationTime; + if ( + includesSomeLane( + workInProgressRootIncludedLanes, + workInProgressRootUpdatedLanes + ) + ) { + // The render included lanes that were updated during the render phase. + // For example, when unhiding a hidden tree, we include all the lanes + // that were previously skipped when the tree was hidden. That set of + // lanes is a superset of the lanes we started rendering with. + // + // So we'll throw out the current work and restart. + prepareFreshStack(root, NoLanes); + } else if (exitStatus !== RootIncomplete) { + if (exitStatus === RootErrored) { + executionContext |= RetryAfterError; // If an error occurred during hydration, + // discard server response and fall back to client side render. - var _update = createRootErrorUpdate( - workInProgress, - _errorInfo, - renderExpirationTime - ); + if (root.hydrate) { + root.hydrate = false; + clearContainer(root.containerInfo); + } // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. - enqueueCapturedUpdate(workInProgress, _update); - return; + lanes = getLanesToRetrySynchronouslyOnError(root); + + if (lanes !== NoLanes) { + exitStatus = renderRootSync(root, lanes); } + } - case ClassComponent: - // Capture and retry - var errorInfo = value; - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } // We now have a consistent tree. The next step is either to commit it, + // or, if something suspended, wait to commit it after a timeout. - if ( - (workInProgress.effectTag & DidCapture) === NoEffect && - (typeof ctor.getDerivedStateFromError === "function" || - (instance !== null && - typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance))) - ) { - workInProgress.effectTag |= ShouldCapture; - workInProgress.expirationTime = renderExpirationTime; // Schedule the error boundary to re-render using updated state + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + finishConcurrentRender(root, exitStatus, lanes); + } - var _update2 = createClassErrorUpdate( - workInProgress, - errorInfo, - renderExpirationTime - ); + ensureRootIsScheduled(root, now()); - enqueueCapturedUpdate(workInProgress, _update2); - return; - } + if (root.callbackNode === originalCallbackNode) { + // The task node scheduled for this root is the same one that's + // currently executed. Need to return a continuation. + return performConcurrentWorkOnRoot.bind(null, root); + } - break; + return null; +} + +function finishConcurrentRender(root, exitStatus, lanes) { + switch (exitStatus) { + case RootIncomplete: + case RootFatalErrored: { + { + throw Error("Root did not complete. This is a bug in React."); + } } + // Flow knows about invariant, so it complains if I add a break + // statement, but eslint doesn't know about invariant, so it complains + // if I do. eslint-disable-next-line no-fallthrough - workInProgress = workInProgress.return; - } while (workInProgress !== null); -} + case RootErrored: { + // We should have already attempted to retry this tree. If we reached + // this point, it errored again. Commit it. + commitRoot(root); + break; + } -var ceil = Math.ceil; -var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, - ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - IsSomeRendererActing = ReactSharedInternals.IsSomeRendererActing; -var NoContext = - /* */ - 0; -var BatchedContext = - /* */ - 1; -var DiscreteEventContext = - /* */ - 4; -var LegacyUnbatchedContext = - /* */ - 8; -var RenderContext = - /* */ - 16; -var CommitContext = - /* */ - 32; -var RootIncomplete = 0; -var RootFatalErrored = 1; -var RootErrored = 2; -var RootSuspended = 3; -var RootSuspendedWithDelay = 4; -var RootCompleted = 5; -// Describes where we are in the React execution stack -var executionContext = NoContext; // The root we're working on + case RootSuspended: { + markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we + // should immediately commit it or wait a bit. -var workInProgressRoot = null; // The fiber we're working on + if ( + includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope + !shouldForceFlushFallbacksInDEV() + ) { + // This render only included retries, no updates. Throttle committing + // retries so that we don't show too many loading states too quickly. + var msUntilTimeout = + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. -var workInProgress = null; // The expiration time we're rendering + if (msUntilTimeout > 10) { + var nextLanes = getNextLanes(root, NoLanes); -var renderExpirationTime$1 = NoWork; // Whether to root completed, errored, suspended, etc. + if (nextLanes !== NoLanes) { + // There's additional work on this root. + break; + } -var workInProgressRootExitStatus = RootIncomplete; // A fatal error, if one is thrown + var suspendedLanes = root.suspendedLanes; -var workInProgressRootFatalError = null; // Most recent event time among processed updates during this render. -// This is conceptually a time stamp but expressed in terms of an ExpirationTime -// because we deal mostly with expiration times in the hot path, so this avoids -// the conversion happening in the hot path. + if (!isSubsetOfLanes(suspendedLanes, lanes)) { + // We should prefer to render the fallback of at the last + // suspended level. Ping the last suspended level to try + // rendering it again. + // FIXME: What if the suspended lanes are Idle? Should not restart. + var eventTime = requestEventTime(); + markRootPinged(root, suspendedLanes); + break; + } // The render is suspended, it hasn't timed out, and there's no + // lower priority work to do. Instead of committing the fallback + // immediately, wait for more data to arrive. -var workInProgressRootLatestProcessedExpirationTime = Sync; -var workInProgressRootLatestSuspenseTimeout = Sync; -var workInProgressRootCanSuspendUsingConfig = null; // The work left over by components that were visited during this render. Only -// includes unprocessed updates, not work in bailed out children. + root.timeoutHandle = scheduleTimeout( + commitRoot.bind(null, root), + msUntilTimeout + ); + break; + } + } // The work expired. Commit immediately. -var workInProgressRootNextUnprocessedUpdateTime = NoWork; // If we're pinged while rendering we don't always restart immediately. -// This flag determines if it might be worthwhile to restart if an opportunity -// happens latere. + commitRoot(root); + break; + } -var workInProgressRootHasPendingPing = false; // The most recent time we committed a fallback. This lets us ensure a train -// model where we don't commit new loading states in too quick succession. + case RootSuspendedWithDelay: { + markRootSuspended$1(root, lanes); -var globalMostRecentFallbackTime = 0; -var FALLBACK_THROTTLE_MS = 500; -var nextEffect = null; -var hasUncaughtError = false; -var firstUncaughtError = null; -var legacyErrorBoundariesThatAlreadyFailed = null; -var rootDoesHavePassiveEffects = false; -var rootWithPendingPassiveEffects = null; -var pendingPassiveEffectsRenderPriority = NoPriority; -var pendingPassiveEffectsExpirationTime = NoWork; -var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates + if (includesOnlyTransitions(lanes)) { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + break; + } -var NESTED_UPDATE_LIMIT = 50; -var nestedUpdateCount = 0; -var rootWithNestedUpdates = null; -var NESTED_PASSIVE_UPDATE_LIMIT = 50; -var nestedPassiveUpdateCount = 0; -var interruptedBy = null; // Marks the need to reschedule pending interactions at these expiration times -// during the commit phase. This enables them to be traced across components -// that spawn new work during render. E.g. hidden boundaries, suspended SSR -// hydration or SuspenseList. + if (!shouldForceFlushFallbacksInDEV()) { + // This is not a transition, but we did trigger an avoided state. + // Schedule a placeholder to display after a short delay, using the Just + // Noticeable Difference. + // TODO: Is the JND optimization worth the added complexity? If this is + // the only reason we track the event time, then probably not. + // Consider removing. + var mostRecentEventTime = getMostRecentEventTime(root, lanes); + var eventTimeMs = mostRecentEventTime; + var timeElapsedMs = now() - eventTimeMs; -var spawnedWorkDuringRender = null; // Expiration times are computed by adding to the current time (the start -// time). However, if two updates are scheduled within the same event, we -// should treat their start times as simultaneous, even if the actual clock -// time has advanced between the first and second call. -// In other words, because expiration times determine how updates are batched, -// we want all updates of like priority that occur within the same event to -// receive the same expiration time. Otherwise we get tearing. + var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. -var currentEventTime = NoWork; -function requestCurrentTimeForUpdate() { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - // We're inside React, so it's fine to read the actual time. - return msToExpirationTime(now()); - } // We're not inside React, so we may be in the middle of a browser event. + if (_msUntilTimeout > 10) { + // Instead of committing the fallback immediately, wait for more data + // to arrive. + root.timeoutHandle = scheduleTimeout( + commitRoot.bind(null, root), + _msUntilTimeout + ); + break; + } + } // Commit the placeholder. - if (currentEventTime !== NoWork) { - // Use the same start time for all updates until we enter React again. - return currentEventTime; - } // This is the first update since React yielded. Compute a new start time. + commitRoot(root); + break; + } - currentEventTime = msToExpirationTime(now()); - return currentEventTime; -} -function getCurrentTime() { - return msToExpirationTime(now()); -} -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { - var mode = fiber.mode; + case RootCompleted: { + // The work completed. Ready to commit. + commitRoot(root); + break; + } - if ((mode & BlockingMode) === NoMode) { - return Sync; + default: { + { + throw Error("Unknown root exit status."); + } + } } +} - var priorityLevel = getCurrentPriorityLevel(); +function markRootSuspended$1(root, suspendedLanes) { + // When suspending, we should always exclude lanes that were pinged or (more + // rarely, since we try to avoid it) updated during the render phase. + // TODO: Lol maybe there's a better way to factor this besides this + // obnoxiously named function :) + suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); + suspendedLanes = removeLanes(suspendedLanes, workInProgressRootUpdatedLanes); + markRootSuspended(root, suspendedLanes); +} // This is the entry point for synchronous tasks that don't go +// through Scheduler - if ((mode & ConcurrentMode) === NoMode) { - return priorityLevel === ImmediatePriority ? Sync : Batched; +function performSyncWorkOnRoot(root) { + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); } - if ((executionContext & RenderContext) !== NoContext) { - // Use whatever time we're already rendering - // TODO: Should there be a way to opt out, like with `runWithPriority`? - return renderExpirationTime$1; - } + flushPassiveEffects(); + var lanes; + var exitStatus; - var expirationTime; + if ( + root === workInProgressRoot && + includesSomeLane(root.expiredLanes, workInProgressRootRenderLanes) + ) { + // There's a partial tree, and at least one of its lanes has expired. Finish + // rendering it before rendering the rest of the expired work. + lanes = workInProgressRootRenderLanes; + exitStatus = renderRootSync(root, lanes); - if (suspenseConfig !== null) { - // Compute an expiration time based on the Suspense timeout. - expirationTime = computeSuspenseExpiration( - currentTime, - suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION - ); + if ( + includesSomeLane( + workInProgressRootIncludedLanes, + workInProgressRootUpdatedLanes + ) + ) { + // The render included lanes that were updated during the render phase. + // For example, when unhiding a hidden tree, we include all the lanes + // that were previously skipped when the tree was hidden. That set of + // lanes is a superset of the lanes we started rendering with. + // + // Note that this only happens when part of the tree is rendered + // concurrently. If the whole tree is rendered synchronously, then there + // are no interleaved events. + lanes = getNextLanes(root, lanes); + exitStatus = renderRootSync(root, lanes); + } } else { - // Compute an expiration time based on the Scheduler priority. - switch (priorityLevel) { - case ImmediatePriority: - expirationTime = Sync; - break; + lanes = getNextLanes(root, NoLanes); + exitStatus = renderRootSync(root, lanes); + } - case UserBlockingPriority: - // TODO: Rename this to computeUserBlockingExpiration - expirationTime = computeInteractiveExpiration(currentTime); - break; + if (root.tag !== LegacyRoot && exitStatus === RootErrored) { + executionContext |= RetryAfterError; // If an error occurred during hydration, + // discard server response and fall back to client side render. - case NormalPriority: - case LowPriority: - // TODO: Handle LowPriority - // TODO: Rename this to... something better. - expirationTime = computeAsyncExpiration(currentTime); - break; + if (root.hydrate) { + root.hydrate = false; + clearContainer(root.containerInfo); + } // If something threw an error, try rendering one more time. We'll render + // synchronously to block concurrent data mutations, and we'll includes + // all pending updates are included. If it still fails after the second + // attempt, we'll give up and commit the resulting tree. - case IdlePriority: - expirationTime = Idle; - break; + lanes = getLanesToRetrySynchronouslyOnError(root); - default: { - throw Error("Expected a valid priority level"); - } + if (lanes !== NoLanes) { + exitStatus = renderRootSync(root, lanes); } - } // If we're in the middle of rendering a tree, do not update at the same - // expiration time that is already rendering. - // TODO: We shouldn't have to do this if the update is on a different root. - // Refactor computeExpirationForFiber + scheduleUpdate so we have access to - // the root when we check for this condition. - - if ( - workInProgressRoot !== null && - expirationTime === renderExpirationTime$1 - ) { - // This is a trick to move this update into a separate batch - expirationTime -= 1; } - return expirationTime; -} -function scheduleUpdateOnFiber(fiber, expirationTime) { - checkForNestedUpdates(); - warnAboutRenderPhaseUpdatesInDEV(fiber); - var root = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - - if (root === null) { - warnAboutUpdateOnUnmountedFiberInDEV(fiber); - return; - } + if (exitStatus === RootFatalErrored) { + var fatalError = workInProgressRootFatalError; + prepareFreshStack(root, NoLanes); + markRootSuspended$1(root, lanes); + ensureRootIsScheduled(root, now()); + throw fatalError; + } // We now have a consistent tree. Because this is a sync render, we + // will commit it even if something suspended. - checkForInterruption(fiber, expirationTime); - recordScheduleUpdate(); // TODO: computeExpirationForFiber also reads the priority. Pass the - // priority as an argument to that function and this one. + var finishedWork = root.current.alternate; + root.finishedWork = finishedWork; + root.finishedLanes = lanes; + commitRoot(root); // Before exiting, make sure there's a callback scheduled for the next + // pending level. - var priorityLevel = getCurrentPriorityLevel(); + ensureRootIsScheduled(root, now()); + return null; +} - if (expirationTime === Sync) { - if ( - // Check if we're inside unbatchedUpdates - (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering - (executionContext & (RenderContext | CommitContext)) === NoContext - ) { - // Register pending interactions on the root to avoid losing traced interaction data. - schedulePendingInteractions(root, expirationTime); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed - // root inside of batchedUpdates should be synchronous, but layout updates - // should be deferred until the end of the batch. +function batchedUpdates$1(fn, a) { + var prevExecutionContext = executionContext; + executionContext |= BatchedContext; - performSyncWorkOnRoot(root); - } else { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, expirationTime); + try { + return fn(a); + } finally { + executionContext = prevExecutionContext; - if (executionContext === NoContext) { - // Flush the synchronous work now, unless we're already working or inside - // a batch. This is intentionally inside scheduleUpdateOnFiber instead of - // scheduleCallbackForFiber to preserve the ability to schedule a callback - // without immediately flushing it. We only do this for user-initiated - // updates, to preserve historical behavior of legacy mode. - flushSyncCallbackQueue(); - } + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + resetRenderTimer(); + flushSyncCallbackQueue(); } - } else { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, expirationTime); } +} +function flushSync(fn, a) { + var prevExecutionContext = executionContext; - if ( - (executionContext & DiscreteEventContext) !== NoContext && // Only updates at user-blocking priority or greater are considered - // discrete, even inside a discrete event. - (priorityLevel === UserBlockingPriority || - priorityLevel === ImmediatePriority) - ) { - // This is the result of a discrete event. Track the lowest priority - // discrete update per root so we can flush them early, if needed. - if (rootsWithPendingDiscreteUpdates === null) { - rootsWithPendingDiscreteUpdates = new Map([[root, expirationTime]]); - } else { - var lastDiscreteTime = rootsWithPendingDiscreteUpdates.get(root); - - if (lastDiscreteTime === undefined || lastDiscreteTime > expirationTime) { - rootsWithPendingDiscreteUpdates.set(root, expirationTime); - } + if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) { + { + error( + "flushSync was called from inside a lifecycle method. React cannot " + + "flush when React is already rendering. Consider moving this call to " + + "a scheduler task or micro task." + ); } - } -} -var scheduleWork = scheduleUpdateOnFiber; // This is split into a separate function so we can mark a fiber with pending -// work without treating it as a typical update that originates from an event; -// e.g. retrying a Suspense boundary isn't an update, but it does schedule work -// on a fiber. -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - // Update the source fiber's expiration time - if (fiber.expirationTime < expirationTime) { - fiber.expirationTime = expirationTime; + return fn(a); } - var alternate = fiber.alternate; + executionContext |= BatchedContext; - if (alternate !== null && alternate.expirationTime < expirationTime) { - alternate.expirationTime = expirationTime; - } // Walk the parent path to the root and update the child expiration time. + { + try { + if (fn) { + return runWithPriority(ImmediatePriority$1, fn.bind(null, a)); + } else { + return undefined; + } + } finally { + executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. - var node = fiber.return; - var root = null; + flushSyncCallbackQueue(); + } + } +} +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); + subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); + workInProgressRootIncludedLanes = mergeLanes( + workInProgressRootIncludedLanes, + lanes + ); +} +function popRenderLanes(fiber) { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor, fiber); +} - if (node === null && fiber.tag === HostRoot) { - root = fiber.stateNode; - } else { - while (node !== null) { - alternate = node.alternate; +function prepareFreshStack(root, lanes) { + root.finishedWork = null; + root.finishedLanes = NoLanes; + var timeoutHandle = root.timeoutHandle; - if (node.childExpirationTime < expirationTime) { - node.childExpirationTime = expirationTime; + if (timeoutHandle !== noTimeout) { + // The root previous suspended and scheduled a timeout to commit a fallback + // state. Now that we have additional work, cancel the timeout. + root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above - if ( - alternate !== null && - alternate.childExpirationTime < expirationTime - ) { - alternate.childExpirationTime = expirationTime; - } - } else if ( - alternate !== null && - alternate.childExpirationTime < expirationTime - ) { - alternate.childExpirationTime = expirationTime; - } + cancelTimeout(timeoutHandle); + } - if (node.return === null && node.tag === HostRoot) { - root = node.stateNode; - break; - } + if (workInProgress !== null) { + var interruptedWork = workInProgress.return; - node = node.return; + while (interruptedWork !== null) { + unwindInterruptedWork(interruptedWork); + interruptedWork = interruptedWork.return; } } - if (root !== null) { - if (workInProgressRoot === root) { - // Received an update to a tree that's in the middle of rendering. Mark - // that's unprocessed work on this root. - markUnprocessedUpdateTime(expirationTime); - - if (workInProgressRootExitStatus === RootSuspendedWithDelay) { - // The root already suspended with a delay, which means this render - // definitely won't finish. Since we have a new update, let's mark it as - // suspended now, right before marking the incoming update. This has the - // effect of interrupting the current render and switching to the update. - // TODO: This happens to work when receiving an update during the render - // phase, because of the trick inside computeExpirationForFiber to - // subtract 1 from `renderExpirationTime` to move it into a - // separate bucket. But we should probably model it with an exception, - // using the same mechanism we use to force hydration of a subtree. - // TODO: This does not account for low pri updates that were already - // scheduled before the root started rendering. Need to track the next - // pending expiration time (perhaps by backtracking the return path) and - // then trigger a restart in the `renderDidSuspendDelayIfPossible` path. - markRootSuspendedAtTime(root, renderExpirationTime$1); - } - } // Mark that the root has a pending update. - - markRootUpdatedAtTime(root, expirationTime); + workInProgressRoot = root; + workInProgress = createWorkInProgress(root.current, null); + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = RootIncomplete; + workInProgressRootFatalError = null; + workInProgressRootSkippedLanes = NoLanes; + workInProgressRootUpdatedLanes = NoLanes; + workInProgressRootPingedLanes = NoLanes; + + { + spawnedWorkDuringRender = null; } - return root; + { + ReactStrictModeWarnings.discardPendingWarnings(); + } } -function getNextRootExpirationTimeToWorkOn(root) { - // Determines the next expiration time that the root should render, taking - // into account levels that may be suspended, or levels that may have - // received a ping. - var lastExpiredTime = root.lastExpiredTime; +function handleError(root, thrownValue) { + do { + var erroredWork = workInProgress; - if (lastExpiredTime !== NoWork) { - return lastExpiredTime; - } // "Pending" refers to any update that hasn't committed yet, including if it - // suspended. The "suspended" range is therefore a subset. + try { + // Reset module-level state that was set during the render phase. + resetContextDependencies(); + resetHooksAfterThrow(); + resetCurrentFiber(); // TODO: I found and added this missing line while investigating a + // separate issue. Write a regression test using string refs. - var firstPendingTime = root.firstPendingTime; + ReactCurrentOwner$2.current = null; - if (!isRootSuspendedAtTime(root, firstPendingTime)) { - // The highest priority pending time is not suspended. Let's work on that. - return firstPendingTime; - } // If the first pending time is suspended, check if there's a lower priority - // pending level that we know about. Or check if we received a ping. Work - // on whichever is higher priority. + if (erroredWork === null || erroredWork.return === null) { + // Expected to be working on a non-root fiber. This is a fatal error + // because there's no ancestor that can handle it; the root is + // supposed to capture all errors that weren't caught by an error + // boundary. + workInProgressRootExitStatus = RootFatalErrored; + workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next + // sibling, or the parent if there are no siblings. But since the root + // has no siblings nor a parent, we set it to null. Usually this is + // handled by `completeUnitOfWork` or `unwindWork`, but since we're + // intentionally not calling those, we need set it here. + // TODO: Consider calling `unwindWork` to pop the contexts. - var lastPingedTime = root.lastPingedTime; - var nextKnownPendingLevel = root.nextKnownPendingLevel; - var nextLevel = - lastPingedTime > nextKnownPendingLevel - ? lastPingedTime - : nextKnownPendingLevel; + workInProgress = null; + return; + } - if (nextLevel <= Idle && firstPendingTime !== nextLevel) { - // Don't work on Idle/Never priority unless everything else is committed. - return NoWork; - } + if (enableProfilerTimer && erroredWork.mode & ProfileMode) { + // Record the time spent rendering before an error was thrown. This + // avoids inaccurate Profiler durations in the case of a + // suspended render. + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); + } - return nextLevel; -} // Use this function to schedule a task for a root. There's only one task per -// root; if a task was already scheduled, we'll check to make sure the -// expiration time of the existing task is the same as the expiration time of -// the next level that the root has work on. This function is called on every -// update, and right before exiting a task. - -function ensureRootIsScheduled(root) { - var lastExpiredTime = root.lastExpiredTime; - - if (lastExpiredTime !== NoWork) { - // Special case: Expired work should flush synchronously. - root.callbackExpirationTime = Sync; - root.callbackPriority = ImmediatePriority; - root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - ); - return; - } + throwException( + root, + erroredWork.return, + erroredWork, + thrownValue, + workInProgressRootRenderLanes + ); + completeUnitOfWork(erroredWork); + } catch (yetAnotherThrownValue) { + // Something in the return path also threw. + thrownValue = yetAnotherThrownValue; - var expirationTime = getNextRootExpirationTimeToWorkOn(root); - var existingCallbackNode = root.callbackNode; + if (workInProgress === erroredWork && erroredWork !== null) { + // If this boundary has already errored, then we had trouble processing + // the error. Bubble it to the next boundary. + erroredWork = erroredWork.return; + workInProgress = erroredWork; + } else { + erroredWork = workInProgress; + } - if (expirationTime === NoWork) { - // There's nothing to work on. - if (existingCallbackNode !== null) { - root.callbackNode = null; - root.callbackExpirationTime = NoWork; - root.callbackPriority = NoPriority; - } + continue; + } // Return to the normal work loop. return; - } // TODO: If this is an update, we already read the current time. Pass the - // time as an argument. + } while (true); +} - var currentTime = requestCurrentTimeForUpdate(); - var priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); // If there's an existing render task, confirm it has the correct priority and - // expiration time. Otherwise, we'll cancel it and schedule a new one. +function pushDispatcher() { + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; - if (existingCallbackNode !== null) { - var existingCallbackPriority = root.callbackPriority; - var existingCallbackExpirationTime = root.callbackExpirationTime; + if (prevDispatcher === null) { + // The React isomorphic package does not include a default dispatcher. + // Instead the first renderer will lazily attach one, in order to give + // nicer error messages. + return ContextOnlyDispatcher; + } else { + return prevDispatcher; + } +} - if ( - // Callback must have the exact same expiration time. - existingCallbackExpirationTime === expirationTime && // Callback must have greater or equal priority. - existingCallbackPriority >= priorityLevel - ) { - // Existing callback is sufficient. - return; - } // Need to schedule a new task. - // TODO: Instead of scheduling a new task, we should be able to change the - // priority of the existing one. +function popDispatcher(prevDispatcher) { + ReactCurrentDispatcher$2.current = prevDispatcher; +} - cancelCallback(existingCallbackNode); +function pushInteractions(root) { + { + var prevInteractions = tracing.__interactionsRef.current; + tracing.__interactionsRef.current = root.memoizedInteractions; + return prevInteractions; + } +} + +function popInteractions(prevInteractions) { + { + tracing.__interactionsRef.current = prevInteractions; + } +} + +function markCommitTimeOfFallback() { + globalMostRecentFallbackTime = now(); +} +function markSkippedUpdateLanes(lane) { + workInProgressRootSkippedLanes = mergeLanes( + lane, + workInProgressRootSkippedLanes + ); +} +function renderDidSuspend() { + if (workInProgressRootExitStatus === RootIncomplete) { + workInProgressRootExitStatus = RootSuspended; + } +} +function renderDidSuspendDelayIfPossible() { + if ( + workInProgressRootExitStatus === RootIncomplete || + workInProgressRootExitStatus === RootSuspended + ) { + workInProgressRootExitStatus = RootSuspendedWithDelay; + } // Check if there are updates that we skipped tree that might have unblocked + // this render. + + if ( + workInProgressRoot !== null && + (includesNonIdleWork(workInProgressRootSkippedLanes) || + includesNonIdleWork(workInProgressRootUpdatedLanes)) + ) { + // Mark the current render as suspended so that we switch to working on + // the updates that were skipped. Usually we only suspend at the end of + // the render phase. + // TODO: We should probably always mark the root as suspended immediately + // (inside this function), since by suspending at the end of the render + // phase introduces a potential mistake where we suspend lanes that were + // pinged or updated while we were rendering. + markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); + } +} +function renderDidError() { + if (workInProgressRootExitStatus !== RootCompleted) { + workInProgressRootExitStatus = RootErrored; } +} // Called during render to determine if anything has suspended. +// Returns false if we're not sure. + +function renderHasNotSuspendedYet() { + // If something errored or completed, we can't really be sure, + // so those are false. + return workInProgressRootExitStatus === RootIncomplete; +} - root.callbackExpirationTime = expirationTime; - root.callbackPriority = priorityLevel; - var callbackNode; +function renderRootSync(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (expirationTime === Sync) { - // Sync React callbacks are scheduled on a special internal queue - callbackNode = scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); - } else { - callbackNode = scheduleCallback( - priorityLevel, - performConcurrentWorkOnRoot.bind(null, root), // Compute a task timeout based on the expiration time. This also affects - // ordering because tasks are processed in timeout order. - { - timeout: expirationTimeToMs(expirationTime) - now() - } - ); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + prepareFreshStack(root, lanes); + startWorkOnPendingInteractions(root, lanes); } - root.callbackNode = callbackNode; -} // This is the entry point for every concurrent task, i.e. anything that -// goes through Scheduler. - -function performConcurrentWorkOnRoot(root, didTimeout) { - // Since we know we're in a React event, we can clear the current - // event time. The next update will compute a new event time. - currentEventTime = NoWork; // Check if the render expired. - - if (didTimeout) { - // The render task took too long to complete. Mark the current time as - // expired to synchronously render all expired work in a single batch. - var currentTime = requestCurrentTimeForUpdate(); - markRootExpiredAtTime(root, currentTime); // This will schedule a synchronous callback. + var prevInteractions = pushInteractions(root); - ensureRootIsScheduled(root); - return null; - } // Determine the next expiration time to work on, using the fields stored - // on the root. + do { + try { + workLoopSync(); + break; + } catch (thrownValue) { + handleError(root, thrownValue); + } + } while (true); - var expirationTime = getNextRootExpirationTimeToWorkOn(root); + resetContextDependencies(); - if (expirationTime === NoWork) { - return null; + { + popInteractions(prevInteractions); } - var originalCallbackNode = root.callbackNode; + executionContext = prevExecutionContext; + popDispatcher(prevDispatcher); - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); + if (workInProgress !== null) { + // This is a sync render, so we should have finished the whole tree. + { + throw Error( + "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." + ); + } } - flushPassiveEffects(); - var exitStatus = renderRootConcurrent(root, expirationTime); - - if (exitStatus !== RootIncomplete) { - if (exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll - // render synchronously to block concurrent data mutations, and we'll - // render at Idle (or lower) so that all pending updates are included. - // If it still fails after the second attempt, we'll give up and commit - // the resulting tree. - expirationTime = expirationTime > Idle ? Idle : expirationTime; - exitStatus = renderRootSync(root, expirationTime); - } + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; + return workInProgressRootExitStatus; +} // The work loop is an extremely hot path. Tell Closure not to inline it. - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, expirationTime); - markRootSuspendedAtTime(root, expirationTime); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. The next step is either to commit it, - // or, if something suspended, wait to commit it after a timeout. +/** @noinline */ - var finishedWork = (root.finishedWork = root.current.alternate); - root.finishedExpirationTime = expirationTime; - finishConcurrentRender(root, finishedWork, exitStatus, expirationTime); +function workLoopSync() { + // Already timed out, so perform work without checking if we need to yield. + while (workInProgress !== null) { + performUnitOfWork(workInProgress); } +} - ensureRootIsScheduled(root); +function renderRootConcurrent(root, lanes) { + var prevExecutionContext = executionContext; + executionContext |= RenderContext; + var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack + // and prepare a fresh one. Otherwise we'll continue where we left off. - if (root.callbackNode === originalCallbackNode) { - // The task node scheduled for this root is the same one that's - // currently executed. Need to return a continuation. - return performConcurrentWorkOnRoot.bind(null, root); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { + resetRenderTimer(); + prepareFreshStack(root, lanes); + startWorkOnPendingInteractions(root, lanes); } - return null; -} - -function finishConcurrentRender( - root, - finishedWork, - exitStatus, - expirationTime -) { - switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: { - { - throw Error("Root did not complete. This is a bug in React."); - } - } - // Flow knows about invariant, so it complains if I add a break - // statement, but eslint doesn't know about invariant, so it complains - // if I do. eslint-disable-next-line no-fallthrough + var prevInteractions = pushInteractions(root); - case RootErrored: { - // We should have already attempted to retry this tree. If we reached - // this point, it errored again. Commit it. - commitRoot(root); + do { + try { + workLoopConcurrent(); break; + } catch (thrownValue) { + handleError(root, thrownValue); } + } while (true); - case RootSuspended: { - markRootSuspendedAtTime(root, expirationTime); - var lastSuspendedTime = root.lastSuspendedTime; - - if (expirationTime === lastSuspendedTime) { - root.nextKnownPendingLevel = getRemainingExpirationTime(finishedWork); - } // We have an acceptable loading state. We need to figure out if we - // should immediately commit it or wait a bit. - // If we have processed new updates during this render, we may now - // have a new loading state ready. We want to ensure that we commit - // that as soon as possible. - - var hasNotProcessedNewUpdates = - workInProgressRootLatestProcessedExpirationTime === Sync; + resetContextDependencies(); - if ( - hasNotProcessedNewUpdates && // do not delay if we're inside an act() scope - !IsThisRendererActing.current - ) { - // If we have not processed any new updates during this pass, then - // this is either a retry of an existing fallback state or a - // hidden tree. Hidden trees shouldn't be batched with other work - // and after that's fixed it can only be a retry. We're going to - // throttle committing retries so that we don't show too many - // loading states too quickly. - var msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. + { + popInteractions(prevInteractions); + } - if (msUntilTimeout > 10) { - if (workInProgressRootHasPendingPing) { - var lastPingedTime = root.lastPingedTime; - - if (lastPingedTime === NoWork || lastPingedTime >= expirationTime) { - // This render was pinged but we didn't get to restart - // earlier so try restarting now instead. - root.lastPingedTime = expirationTime; - prepareFreshStack(root, expirationTime); - break; - } - } + popDispatcher(prevDispatcher); + executionContext = prevExecutionContext; - var nextTime = getNextRootExpirationTimeToWorkOn(root); + if (workInProgress !== null) { + return RootIncomplete; + } else { + workInProgressRoot = null; + workInProgressRootRenderLanes = NoLanes; // Return the final exit status. - if (nextTime !== NoWork && nextTime !== expirationTime) { - // There's additional work on this root. - break; - } + return workInProgressRootExitStatus; + } +} +/** @noinline */ - if ( - lastSuspendedTime !== NoWork && - lastSuspendedTime !== expirationTime - ) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - root.lastPingedTime = lastSuspendedTime; - break; - } // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. +function workLoopConcurrent() { + // Perform work until Scheduler asks us to yield + while (workInProgress !== null && !shouldYield()) { + performUnitOfWork(workInProgress); + } +} - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. +function performUnitOfWork(unitOfWork) { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = unitOfWork.alternate; + setCurrentFiber(unitOfWork); + var next; - commitRoot(root); - break; - } + if ((unitOfWork.mode & ProfileMode) !== NoMode) { + startProfilerTimer(unitOfWork); + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + } else { + next = beginWork$1(current, unitOfWork, subtreeRenderLanes); + } - case RootSuspendedWithDelay: { - markRootSuspendedAtTime(root, expirationTime); - var _lastSuspendedTime = root.lastSuspendedTime; + resetCurrentFiber(); + unitOfWork.memoizedProps = unitOfWork.pendingProps; - if (expirationTime === _lastSuspendedTime) { - root.nextKnownPendingLevel = getRemainingExpirationTime(finishedWork); - } + if (next === null) { + // If this doesn't spawn new work, complete the current work. + completeUnitOfWork(unitOfWork); + } else { + workInProgress = next; + } - { - // We're suspended in a state that should be avoided. We'll try to - // avoid committing it for as long as the timeouts let us. - if (workInProgressRootHasPendingPing) { - var _lastPingedTime = root.lastPingedTime; - - if (_lastPingedTime === NoWork || _lastPingedTime >= expirationTime) { - // This render was pinged but we didn't get to restart earlier - // so try restarting now instead. - root.lastPingedTime = expirationTime; - prepareFreshStack(root, expirationTime); - break; - } - } + ReactCurrentOwner$2.current = null; +} - var _nextTime = getNextRootExpirationTimeToWorkOn(root); +function completeUnitOfWork(unitOfWork) { + // Attempt to complete the current unit of work, then move to the next + // sibling. If there are no more siblings, return to the parent fiber. + var completedWork = unitOfWork; - if (_nextTime !== NoWork && _nextTime !== expirationTime) { - // There's additional work on this root. - break; - } + do { + // The current, flushed, state of this fiber is the alternate. Ideally + // nothing should rely on this, but relying on it here means that we don't + // need an additional field on the work in progress. + var current = completedWork.alternate; + var returnFiber = completedWork.return; // Check if the work completed or if something threw. - if ( - _lastSuspendedTime !== NoWork && - _lastSuspendedTime !== expirationTime - ) { - // We should prefer to render the fallback of at the last - // suspended level. Ping the last suspended level to try - // rendering it again. - root.lastPingedTime = _lastSuspendedTime; - break; - } + if ((completedWork.flags & Incomplete) === NoFlags) { + setCurrentFiber(completedWork); + var next = void 0; - var _msUntilTimeout; - - if (workInProgressRootLatestSuspenseTimeout !== Sync) { - // We have processed a suspense config whose expiration time we - // can use as the timeout. - _msUntilTimeout = - expirationTimeToMs(workInProgressRootLatestSuspenseTimeout) - now(); - } else if (workInProgressRootLatestProcessedExpirationTime === Sync) { - // This should never normally happen because only new updates - // cause delayed states, so we should have processed something. - // However, this could also happen in an offscreen tree. - _msUntilTimeout = 0; - } else { - // If we don't have a suspense config, we're going to use a - // heuristic to determine how long we can suspend. - var eventTimeMs = inferTimeFromExpirationTime( - workInProgressRootLatestProcessedExpirationTime - ); - var currentTimeMs = now(); - var timeUntilExpirationMs = - expirationTimeToMs(expirationTime) - currentTimeMs; - var timeElapsed = currentTimeMs - eventTimeMs; - - if (timeElapsed < 0) { - // We get this wrong some time since we estimate the time. - timeElapsed = 0; - } + if ((completedWork.mode & ProfileMode) === NoMode) { + next = completeWork(current, completedWork, subtreeRenderLanes); + } else { + startProfilerTimer(completedWork); + next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. - _msUntilTimeout = jnd(timeElapsed) - timeElapsed; // Clamp the timeout to the expiration time. TODO: Once the - // event time is exact instead of inferred from expiration time - // we don't need this. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); + } - if (timeUntilExpirationMs < _msUntilTimeout) { - _msUntilTimeout = timeUntilExpirationMs; - } - } // Don't bother with a very short suspense time. + resetCurrentFiber(); - if (_msUntilTimeout > 10) { - // The render is suspended, it hasn't timed out, and there's no - // lower priority work to do. Instead of committing the fallback - // immediately, wait for more data to arrive. - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout - ); - break; - } - } // The work expired. Commit immediately. + if (next !== null) { + // Completing this fiber spawned new work. Work on that next. + workInProgress = next; + return; + } - commitRoot(root); - break; - } + resetChildLanes(completedWork); - case RootCompleted: { - // The work completed. Ready to commit. if ( - // do not delay if we're inside an act() scope - workInProgressRootLatestProcessedExpirationTime !== Sync && - workInProgressRootCanSuspendUsingConfig !== null + returnFiber !== null && // Do not append effects to parents if a sibling failed to complete + (returnFiber.flags & Incomplete) === NoFlags ) { - // If we have exceeded the minimum loading delay, which probably - // means we have shown a spinner already, we might have to suspend - // a bit longer to ensure that the spinner is shown for - // enough time. - var _msUntilTimeout2 = computeMsUntilSuspenseLoadingDelay( - workInProgressRootLatestProcessedExpirationTime, - expirationTime, - workInProgressRootCanSuspendUsingConfig - ); - - if (_msUntilTimeout2 > 10) { - markRootSuspendedAtTime(root, expirationTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - _msUntilTimeout2 - ); - break; + // Append all the effects of the subtree and this fiber onto the effect + // list of the parent. The completion order of the children affects the + // side-effect order. + if (returnFiber.firstEffect === null) { + returnFiber.firstEffect = completedWork.firstEffect; } - } - commitRoot(root); - break; - } - - default: { - { - throw Error("Unknown root exit status."); - } - } - } -} // This is the entry point for synchronous tasks that don't go -// through Scheduler - -function performSyncWorkOnRoot(root) { - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); - } - - flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - var expirationTime; + if (completedWork.lastEffect !== null) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = completedWork.firstEffect; + } - if (lastExpiredTime !== NoWork) { - // There's expired work on this root. Check if we have a partial tree - // that we can reuse. - if ( - root === workInProgressRoot && - renderExpirationTime$1 >= lastExpiredTime - ) { - // There's a partial tree with equal or greater than priority than the - // expired level. Finish rendering it before rendering the rest of the - // expired work. - expirationTime = renderExpirationTime$1; - } else { - // Start a fresh tree. - expirationTime = lastExpiredTime; - } - } else { - // There's no expired work. This must be a new, synchronous render. - expirationTime = Sync; - } + returnFiber.lastEffect = completedWork.lastEffect; + } // If this fiber had side-effects, we append it AFTER the children's + // side-effects. We can perform certain side-effects earlier if needed, + // by doing multiple passes over the effect list. We don't want to + // schedule our own side-effect on our own list because if end up + // reusing children we'll schedule this effect onto itself since we're + // at the end. - var exitStatus = renderRootSync(root, expirationTime); + var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect + // list. PerformedWork effect is read by React DevTools but shouldn't be + // committed. - if (root.tag !== LegacyRoot && exitStatus === RootErrored) { - // If something threw an error, try rendering one more time. We'll - // render synchronously to block concurrent data mutations, and we'll - // render at Idle (or lower) so that all pending updates are included. - // If it still fails after the second attempt, we'll give up and commit - // the resulting tree. - expirationTime = expirationTime > Idle ? Idle : expirationTime; - exitStatus = renderRootSync(root, expirationTime); - } + if (flags > PerformedWork) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = completedWork; + } else { + returnFiber.firstEffect = completedWork; + } - if (exitStatus === RootFatalErrored) { - var fatalError = workInProgressRootFatalError; - prepareFreshStack(root, expirationTime); - markRootSuspendedAtTime(root, expirationTime); - ensureRootIsScheduled(root); - throw fatalError; - } // We now have a consistent tree. Because this is a sync render, we - // will commit it even if something suspended. + returnFiber.lastEffect = completedWork; + } + } + } else { + // This fiber did not complete because something threw. Pop values off + // the stack without entering the complete phase. If this is a boundary, + // capture values if possible. + var _next = unwindWork(completedWork); // Because this fiber did not complete, don't reset its expiration time. - root.finishedWork = root.current.alternate; - root.finishedExpirationTime = expirationTime; - commitRoot(root); // Before exiting, make sure there's a callback scheduled for the next - // pending level. + if (_next !== null) { + // If completing this work spawned new work, do that next. We'll come + // back here again. + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + _next.flags &= HostEffectMask; + workInProgress = _next; + return; + } - ensureRootIsScheduled(root); - return null; -} -function syncUpdates(fn, a, b, c) { - return runWithPriority(ImmediatePriority, fn.bind(null, a, b, c)); -} + if ((completedWork.mode & ProfileMode) !== NoMode) { + // Record the render duration for the fiber that errored. + stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. -function batchedUpdates$1(fn, a) { - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + var actualDuration = completedWork.actualDuration; + var child = completedWork.child; - try { - return fn(a); - } finally { - executionContext = prevExecutionContext; + while (child !== null) { + actualDuration += child.actualDuration; + child = child.sibling; + } - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); - } - } -} -function flushSync(fn, a) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { - { - throw Error( - "flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering." - ); - } - } + completedWork.actualDuration = actualDuration; + } - var prevExecutionContext = executionContext; - executionContext |= BatchedContext; + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its effect list. + returnFiber.firstEffect = returnFiber.lastEffect = null; + returnFiber.flags |= Incomplete; + } + } - try { - return runWithPriority(ImmediatePriority, fn.bind(null, a)); - } finally { - executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. + var siblingFiber = completedWork.sibling; - flushSyncCallbackQueue(); - } -} + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + workInProgress = siblingFiber; + return; + } // Otherwise, return to the parent -function prepareFreshStack(root, expirationTime) { - root.finishedWork = null; - root.finishedExpirationTime = NoWork; - var timeoutHandle = root.timeoutHandle; + completedWork = returnFiber; // Update the next thing we're working on in case something throws. - if (timeoutHandle !== noTimeout) { - // The root previous suspended and scheduled a timeout to commit a fallback - // state. Now that we have additional work, cancel the timeout. - root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above + workInProgress = completedWork; + } while (completedWork !== null); // We've reached the root. - cancelTimeout(timeoutHandle); + if (workInProgressRootExitStatus === RootIncomplete) { + workInProgressRootExitStatus = RootCompleted; } +} - if (workInProgress !== null) { - var interruptedWork = workInProgress.return; - - while (interruptedWork !== null) { - unwindInterruptedWork(interruptedWork); - interruptedWork = interruptedWork.return; - } +function resetChildLanes(completedWork) { + if ( + // TODO: Move this check out of the hot path by moving `resetChildLanes` + // to switch statement in `completeWork`. + (completedWork.tag === LegacyHiddenComponent || + completedWork.tag === OffscreenComponent) && + completedWork.memoizedState !== null && + !includesSomeLane(subtreeRenderLanes, OffscreenLane) && + (completedWork.mode & ConcurrentMode) !== NoLanes + ) { + // The children of this component are hidden. Don't bubble their + // expiration times. + return; } - workInProgressRoot = root; - workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; - workInProgressRootFatalError = null; - workInProgressRootLatestProcessedExpirationTime = Sync; - workInProgressRootLatestSuspenseTimeout = Sync; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = NoWork; - workInProgressRootHasPendingPing = false; - - { - spawnedWorkDuringRender = null; - } + var newChildLanes = NoLanes; // Bubble up the earliest expiration time. - { - ReactStrictModeWarnings.discardPendingWarnings(); - } -} + if ((completedWork.mode & ProfileMode) !== NoMode) { + // In profiling mode, resetChildExpirationTime is also used to reset + // profiler durations. + var actualDuration = completedWork.actualDuration; + var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will + // only be updated if work is done on the fiber (i.e. it doesn't bailout). + // When work is done, it should bubble to the parent's actualDuration. If + // the fiber has not been cloned though, (meaning no work was done), then + // this value will reflect the amount of time spent working on a previous + // render. In that case it should not bubble. We determine whether it was + // cloned by comparing the child pointer. -function handleError(root, thrownValue) { - do { - try { - // Reset module-level state that was set during the render phase. - resetContextDependencies(); - resetHooksAfterThrow(); - resetCurrentFiber(); + var shouldBubbleActualDurations = + completedWork.alternate === null || + completedWork.child !== completedWork.alternate.child; + var child = completedWork.child; - if (workInProgress === null || workInProgress.return === null) { - // Expected to be working on a non-root fiber. This is a fatal error - // because there's no ancestor that can handle it; the root is - // supposed to capture all errors that weren't caught by an error - // boundary. - workInProgressRootExitStatus = RootFatalErrored; - workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next - // sibling, or the parent if there are no siblings. But since the root - // has no siblings nor a parent, we set it to null. Usually this is - // handled by `completeUnitOfWork` or `unwindWork`, but since we're - // interntionally not calling those, we need set it here. - // TODO: Consider calling `unwindWork` to pop the contexts. + while (child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(child.lanes, child.childLanes) + ); - workInProgress = null; - return null; + if (shouldBubbleActualDurations) { + actualDuration += child.actualDuration; } - if (enableProfilerTimer && workInProgress.mode & ProfileMode) { - // Record the time spent rendering before an error was thrown. This - // avoids inaccurate Profiler durations in the case of a - // suspended render. - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, true); - } + treeBaseDuration += child.treeBaseDuration; + child = child.sibling; + } - throwException( - root, - workInProgress.return, - workInProgress, - thrownValue, - renderExpirationTime$1 - ); - workInProgress = completeUnitOfWork(workInProgress); - } catch (yetAnotherThrownValue) { - // Something in the return path also threw. - thrownValue = yetAnotherThrownValue; - continue; - } // Return to the normal work loop. + var isTimedOutSuspense = + completedWork.tag === SuspenseComponent && + completedWork.memoizedState !== null; - return; - } while (true); -} + if (isTimedOutSuspense) { + // Don't count time spent in a timed out Suspense subtree as part of the base duration. + var primaryChildFragment = completedWork.child; -function pushDispatcher(root) { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (primaryChildFragment !== null) { + treeBaseDuration -= primaryChildFragment.treeBaseDuration; + } + } - if (prevDispatcher === null) { - // The React isomorphic package does not include a default dispatcher. - // Instead the first renderer will lazily attach one, in order to give - // nicer error messages. - return ContextOnlyDispatcher; + completedWork.actualDuration = actualDuration; + completedWork.treeBaseDuration = treeBaseDuration; } else { - return prevDispatcher; + var _child = completedWork.child; + + while (_child !== null) { + newChildLanes = mergeLanes( + newChildLanes, + mergeLanes(_child.lanes, _child.childLanes) + ); + _child = _child.sibling; + } } -} -function popDispatcher(prevDispatcher) { - ReactCurrentDispatcher$1.current = prevDispatcher; + completedWork.childLanes = newChildLanes; } -function pushInteractions(root) { - { - var prevInteractions = tracing.__interactionsRef.current; - tracing.__interactionsRef.current = root.memoizedInteractions; - return prevInteractions; - } +function commitRoot(root) { + var renderPriorityLevel = getCurrentPriorityLevel(); + runWithPriority( + ImmediatePriority$1, + commitRootImpl.bind(null, root, renderPriorityLevel) + ); + return null; } -function popInteractions(prevInteractions) { - { - tracing.__interactionsRef.current = prevInteractions; - } -} +function commitRootImpl(root, renderPriorityLevel) { + do { + // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which + // means `flushPassiveEffects` will sometimes result in additional + // passive effects. So we need to keep flushing in a loop until there are + // no more pending effects. + // TODO: Might be better if `flushPassiveEffects` did not automatically + // flush synchronous work at the end, to avoid factoring hazards like this. + flushPassiveEffects(); + } while (rootWithPendingPassiveEffects !== null); -function markCommitTimeOfFallback() { - globalMostRecentFallbackTime = now(); -} -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - if ( - expirationTime < workInProgressRootLatestProcessedExpirationTime && - expirationTime > Idle - ) { - workInProgressRootLatestProcessedExpirationTime = expirationTime; + flushRenderPhaseStrictModeWarningsInDEV(); + + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Should not already be working."); } - if (suspenseConfig !== null) { - if ( - expirationTime < workInProgressRootLatestSuspenseTimeout && - expirationTime > Idle - ) { - workInProgressRootLatestSuspenseTimeout = expirationTime; // Most of the time we only have one config and getting wrong is not bad. + var finishedWork = root.finishedWork; + var lanes = root.finishedLanes; - workInProgressRootCanSuspendUsingConfig = suspenseConfig; - } - } -} -function markUnprocessedUpdateTime(expirationTime) { - if (expirationTime > workInProgressRootNextUnprocessedUpdateTime) { - workInProgressRootNextUnprocessedUpdateTime = expirationTime; - } -} -function renderDidSuspend() { - if (workInProgressRootExitStatus === RootIncomplete) { - workInProgressRootExitStatus = RootSuspended; + if (finishedWork === null) { + return null; } -} -function renderDidSuspendDelayIfPossible() { - if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended - ) { - workInProgressRootExitStatus = RootSuspendedWithDelay; - } // Check if there's a lower priority update somewhere else in the tree. - if ( - workInProgressRootNextUnprocessedUpdateTime !== NoWork && - workInProgressRoot !== null - ) { - // Mark the current render as suspended, and then mark that there's a - // pending update. - // TODO: This should immediately interrupt the current render, instead - // of waiting until the next time we yield. - markRootSuspendedAtTime(workInProgressRoot, renderExpirationTime$1); - markRootUpdatedAtTime( - workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime + root.finishedWork = null; + root.finishedLanes = NoLanes; + + if (!(finishedWork !== root.current)) { + throw Error( + "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - } -} -function renderDidError() { - if (workInProgressRootExitStatus !== RootCompleted) { - workInProgressRootExitStatus = RootErrored; - } -} // Called during render to determine if anything has suspended. -// Returns false if we're not sure. + } // commitRoot never returns a continuation; it always finishes synchronously. + // So we can clear these now to allow a new callback to be scheduled. -function renderHasNotSuspendedYet() { - // If something errored or completed, we can't really be sure, - // so those are false. - return workInProgressRootExitStatus === RootIncomplete; -} + root.callbackNode = null; // Update the first and last pending times on this root. The new first + // pending time is whatever is left on the root fiber. -function inferTimeFromExpirationTime(expirationTime) { - // We don't know exactly when the update was scheduled, but we can infer an - // approximate start time from the expiration time. - var earliestExpirationTimeMs = expirationTimeToMs(expirationTime); - return earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION; -} + var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); + markRootFinished(root, remainingLanes); // Clear already finished discrete updates in case that a later call of + // `flushDiscreteUpdates` starts a useless render pass which may cancels + // a scheduled timeout. -function inferTimeFromExpirationTimeWithSuspenseConfig( - expirationTime, - suspenseConfig -) { - // We don't know exactly when the update was scheduled, but we can infer an - // approximate start time from the expiration time by subtracting the timeout - // that was added to the event time. - var earliestExpirationTimeMs = expirationTimeToMs(expirationTime); - return ( - earliestExpirationTimeMs - - (suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION) - ); -} + if (rootsWithPendingDiscreteUpdates !== null) { + if ( + !hasDiscreteLanes(remainingLanes) && + rootsWithPendingDiscreteUpdates.has(root) + ) { + rootsWithPendingDiscreteUpdates.delete(root); + } + } -function renderRootSync(root, expirationTime) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // If the root or expiration time have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + if (root === workInProgressRoot) { + // We can reset these now that they are finished. + workInProgressRoot = null; + workInProgress = null; + workInProgressRootRenderLanes = NoLanes; + } // Get the list of effects. - if ( - root !== workInProgressRoot || - expirationTime !== renderExpirationTime$1 - ) { - prepareFreshStack(root, expirationTime); - startWorkOnPendingInteractions(root, expirationTime); + var firstEffect; + + if (finishedWork.flags > PerformedWork) { + // A fiber's effect list consists only of its children, not itself. So if + // the root has an effect, we need to add it to the end of the list. The + // resulting list is the set that would belong to the root's parent, if it + // had one; that is, all the effects in the tree including the root. + if (finishedWork.lastEffect !== null) { + finishedWork.lastEffect.nextEffect = finishedWork; + firstEffect = finishedWork.firstEffect; + } else { + firstEffect = finishedWork; + } + } else { + // There is no effect on the root. + firstEffect = finishedWork.firstEffect; } - var prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); + if (firstEffect !== null) { + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + var prevInteractions = pushInteractions(root); // Reset this to null before calling lifecycles - do { - try { - workLoopSync(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass + // of the effect list for each phase: all mutation effects come before all + // layout effects, and so on. + // The first phase a "before mutation" phase. We use this phase to read the + // state of the host tree right before we mutate it. This is where + // getSnapshotBeforeUpdate is called. - resetContextDependencies(); + focusedInstanceHandle = prepareForCommit(root.containerInfo); + shouldFireAfterActiveInstanceBlur = false; + nextEffect = firstEffect; - { - popInteractions(prevInteractions); - } + do { + { + invokeGuardedCallback(null, commitBeforeMutationEffects, null); - executionContext = prevExecutionContext; - popDispatcher(prevDispatcher); + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - if (workInProgress !== null) { - // This is a sync render, so we should have finished the whole tree. - { - throw Error( - "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." - ); - } - } + var error = clearCaughtError(); + captureCommitPhaseError(nextEffect, error); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); // We no longer need to track the active instance fiber - stopFinishedWorkLoopTimer(); // Set this to null to indicate there's no in-progress render. + focusedInstanceHandle = null; - workInProgressRoot = null; - return workInProgressRootExitStatus; -} // The work loop is an extremely hot path. Tell Closure not to inline it. + { + // Mark the current commit time to be shared by all Profilers in this + // batch. This enables them to be grouped later. + recordCommitTime(); + } // The next phase is the mutation phase, where we mutate the host tree. -/** @noinline */ + nextEffect = firstEffect; -function workLoopSync() { - // Already timed out, so perform work without checking if we need to yield. - while (workInProgress !== null) { - workInProgress = performUnitOfWork(workInProgress); - } -} + do { + { + invokeGuardedCallback( + null, + commitMutationEffects, + null, + root, + renderPriorityLevel + ); -function renderRootConcurrent(root, expirationTime) { - var prevExecutionContext = executionContext; - executionContext |= RenderContext; - var prevDispatcher = pushDispatcher(); // If the root or expiration time have changed, throw out the existing stack - // and prepare a fresh one. Otherwise we'll continue where we left off. + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - if ( - root !== workInProgressRoot || - expirationTime !== renderExpirationTime$1 - ) { - prepareFreshStack(root, expirationTime); - startWorkOnPendingInteractions(root, expirationTime); - } + var _error = clearCaughtError(); - var prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); + captureCommitPhaseError(nextEffect, _error); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); - do { - try { - workLoopConcurrent(); - break; - } catch (thrownValue) { - handleError(root, thrownValue); - } - } while (true); + resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after + // the mutation phase, so that the previous tree is still current during + // componentWillUnmount, but before the layout phase, so that the finished + // work is current during componentDidMount/Update. - resetContextDependencies(); + root.current = finishedWork; // The next phase is the layout phase, where we call effects that read + // the host tree after it's been mutated. The idiomatic use case for this is + // layout, but class component lifecycles also fire here for legacy reasons. - { - popInteractions(prevInteractions); - } + nextEffect = firstEffect; - popDispatcher(prevDispatcher); - executionContext = prevExecutionContext; // Check if the tree has completed. + do { + { + invokeGuardedCallback(null, commitLayoutEffects, null, root, lanes); - if (workInProgress !== null) { - // Still work remaining. - stopInterruptedWorkLoopTimer(); - return RootIncomplete; - } else { - // Completed the tree. - stopFinishedWorkLoopTimer(); // Set this to null to indicate there's no in-progress render. + if (hasCaughtError()) { + if (!(nextEffect !== null)) { + throw Error("Should be working on an effect."); + } - workInProgressRoot = null; // Return the final exit status. + var _error2 = clearCaughtError(); - return workInProgressRootExitStatus; - } -} -/** @noinline */ + captureCommitPhaseError(nextEffect, _error2); + nextEffect = nextEffect.nextEffect; + } + } + } while (nextEffect !== null); -function workLoopConcurrent() { - // Perform work until Scheduler asks us to yield - while (workInProgress !== null && !shouldYield()) { - workInProgress = performUnitOfWork(workInProgress); - } -} + nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an + // opportunity to paint. -function performUnitOfWork(unitOfWork) { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = unitOfWork.alternate; - startWorkTimer(unitOfWork); - setCurrentFiber(unitOfWork); - var next; + requestPaint(); - if ((unitOfWork.mode & ProfileMode) !== NoMode) { - startProfilerTimer(unitOfWork); - next = beginWork$1(current, unitOfWork, renderExpirationTime$1); - stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); + { + popInteractions(prevInteractions); + } + + executionContext = prevExecutionContext; } else { - next = beginWork$1(current, unitOfWork, renderExpirationTime$1); + // No effects. + root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were + // no effects. + // TODO: Maybe there's a better way to report this. + + { + recordCommitTime(); + } } - resetCurrentFiber(); - unitOfWork.memoizedProps = unitOfWork.pendingProps; + var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - if (next === null) { - // If this doesn't spawn new work, complete the current work. - next = completeUnitOfWork(unitOfWork); - } + if (rootDoesHavePassiveEffects) { + // This commit has passive effects. Stash a reference to them. But don't + // schedule a callback until after flushing layout work. + rootDoesHavePassiveEffects = false; + rootWithPendingPassiveEffects = root; + pendingPassiveEffectsLanes = lanes; + pendingPassiveEffectsRenderPriority = renderPriorityLevel; + } else { + // We are done with the effect chain at this point so let's clear the + // nextEffect pointers to assist with GC. If we have passive effects, we'll + // clear this in flushPassiveEffects. + nextEffect = firstEffect; - ReactCurrentOwner$2.current = null; - return next; -} + while (nextEffect !== null) { + var nextNextEffect = nextEffect.nextEffect; + nextEffect.nextEffect = null; -function completeUnitOfWork(unitOfWork) { - // Attempt to complete the current unit of work, then move to the next - // sibling. If there are no more siblings, return to the parent fiber. - workInProgress = unitOfWork; + if (nextEffect.flags & Deletion) { + detachFiberAfterEffects(nextEffect); + } - do { - // The current, flushed, state of this fiber is the alternate. Ideally - // nothing should rely on this, but relying on it here means that we don't - // need an additional field on the work in progress. - var current = workInProgress.alternate; - var returnFiber = workInProgress.return; // Check if the work completed or if something threw. + nextEffect = nextNextEffect; + } + } // Read this again, since an effect might have updated it - if ((workInProgress.effectTag & Incomplete) === NoEffect) { - setCurrentFiber(workInProgress); - var next = void 0; + remainingLanes = root.pendingLanes; // Check if there's remaining work on this root - if ((workInProgress.mode & ProfileMode) === NoMode) { - next = completeWork(current, workInProgress, renderExpirationTime$1); - } else { - startProfilerTimer(workInProgress); - next = completeWork(current, workInProgress, renderExpirationTime$1); // Update render duration assuming we didn't error. + if (remainingLanes !== NoLanes) { + { + if (spawnedWorkDuringRender !== null) { + var expirationTimes = spawnedWorkDuringRender; + spawnedWorkDuringRender = null; - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false); + for (var i = 0; i < expirationTimes.length; i++) { + scheduleInteractions( + root, + expirationTimes[i], + root.memoizedInteractions + ); + } } - stopWorkTimer(workInProgress); - resetCurrentFiber(); - resetChildExpirationTime(workInProgress); + schedulePendingInteractions(root, remainingLanes); + } + } else { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null; + } + + { + if (!rootDidHavePassiveEffects) { + // If there are no passive effects, then we can complete the pending interactions. + // Otherwise, we'll wait until after the passive effects are flushed. + // Wait to do this until after remaining work has been scheduled, + // so that we don't prematurely signal complete for interactions when there's e.g. hidden work. + finishPendingInteractions(root, lanes); + } + } - if (next !== null) { - // Completing this fiber spawned new work. Work on that next. - return next; - } + if (remainingLanes === SyncLane) { + // Count the number of times the root synchronously re-renders without + // finishing. If there are too many, it indicates an infinite update loop. + if (root === rootWithNestedUpdates) { + nestedUpdateCount++; + } else { + nestedUpdateCount = 0; + rootWithNestedUpdates = root; + } + } else { + nestedUpdateCount = 0; + } - if ( - returnFiber !== null && // Do not append effects to parents if a sibling failed to complete - (returnFiber.effectTag & Incomplete) === NoEffect - ) { - // Append all the effects of the subtree and this fiber onto the effect - // list of the parent. The completion order of the children affects the - // side-effect order. - if (returnFiber.firstEffect === null) { - returnFiber.firstEffect = workInProgress.firstEffect; - } + onCommitRoot(finishedWork.stateNode, renderPriorityLevel); + // additional work on this root is scheduled. - if (workInProgress.lastEffect !== null) { - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = workInProgress.firstEffect; - } + ensureRootIsScheduled(root, now()); - returnFiber.lastEffect = workInProgress.lastEffect; - } // If this fiber had side-effects, we append it AFTER the children's - // side-effects. We can perform certain side-effects earlier if needed, - // by doing multiple passes over the effect list. We don't want to - // schedule our own side-effect on our own list because if end up - // reusing children we'll schedule this effect onto itself since we're - // at the end. + if (hasUncaughtError) { + hasUncaughtError = false; + var _error3 = firstUncaughtError; + firstUncaughtError = null; + throw _error3; + } - var effectTag = workInProgress.effectTag; // Skip both NoWork and PerformedWork tags when creating the effect - // list. PerformedWork effect is read by React DevTools but shouldn't be - // committed. + if ((executionContext & LegacyUnbatchedContext) !== NoContext) { + // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired + // synchronously, but layout updates should be deferred until the end + // of the batch. - if (effectTag > PerformedWork) { - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = workInProgress; - } else { - returnFiber.firstEffect = workInProgress; - } + return null; + } // If layout work was scheduled, flush it now. - returnFiber.lastEffect = workInProgress; - } - } - } else { - // This fiber did not complete because something threw. Pop values off - // the stack without entering the complete phase. If this is a boundary, - // capture values if possible. - var _next = unwindWork(workInProgress); // Because this fiber did not complete, don't reset its expiration time. + flushSyncCallbackQueue(); - if ((workInProgress.mode & ProfileMode) !== NoMode) { - // Record the render duration for the fiber that errored. - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false); // Include the time spent working on failed children before continuing. + return null; +} - var actualDuration = workInProgress.actualDuration; - var child = workInProgress.child; +function commitBeforeMutationEffects() { + while (nextEffect !== null) { + var current = nextEffect.alternate; - while (child !== null) { - actualDuration += child.actualDuration; - child = child.sibling; + if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) { + if ((nextEffect.flags & Deletion) !== NoFlags) { + if (doesFiberContain(nextEffect, focusedInstanceHandle)) { + shouldFireAfterActiveInstanceBlur = true; + } + } else { + // TODO: Move this out of the hot path using a dedicated effect tag. + if ( + nextEffect.tag === SuspenseComponent && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) + ) { + shouldFireAfterActiveInstanceBlur = true; } - - workInProgress.actualDuration = actualDuration; } + } - if (_next !== null) { - // If completing this work spawned new work, do that next. We'll come - // back here again. - // Since we're restarting, remove anything that is not a host effect - // from the effect tag. - // TODO: The name stopFailedWorkTimer is misleading because Suspense - // also captures and restarts. - stopFailedWorkTimer(workInProgress); - _next.effectTag &= HostEffectMask; - return _next; - } + var flags = nextEffect.flags; - stopWorkTimer(workInProgress); + if ((flags & Snapshot) !== NoFlags) { + setCurrentFiber(nextEffect); + commitBeforeMutationLifeCycles(current, nextEffect); + resetCurrentFiber(); + } - if (returnFiber !== null) { - // Mark the parent fiber as incomplete and clear its effect list. - returnFiber.firstEffect = returnFiber.lastEffect = null; - returnFiber.effectTag |= Incomplete; + if ((flags & Passive) !== NoFlags) { + // If there are passive effects, schedule a callback to flush at + // the earliest opportunity. + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); } } - var siblingFiber = workInProgress.sibling; + nextEffect = nextEffect.nextEffect; + } +} - if (siblingFiber !== null) { - // If there is more work to do in this returnFiber, do that next. - return siblingFiber; - } // Otherwise, return to the parent +function commitMutationEffects(root, renderPriorityLevel) { + // TODO: Should probably move the bulk of this function to commitWork. + while (nextEffect !== null) { + setCurrentFiber(nextEffect); + var flags = nextEffect.flags; - workInProgress = returnFiber; - } while (workInProgress !== null); // We've reached the root. + if (flags & ContentReset) { + commitResetTextContent(nextEffect); + } - if (workInProgressRootExitStatus === RootIncomplete) { - workInProgressRootExitStatus = RootCompleted; - } + if (flags & Ref) { + var current = nextEffect.alternate; - return null; -} + if (current !== null) { + commitDetachRef(current); + } + } // The following switch statement is only concerned about placement, + // updates, and deletions. To avoid needing to add a case for every possible + // bitmap value, we remove the secondary effects from the effect tag and + // switch on that value. -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - var childExpirationTime = fiber.childExpirationTime; - return updateExpirationTime > childExpirationTime - ? updateExpirationTime - : childExpirationTime; -} + var primaryFlags = flags & (Placement | Update | Deletion | Hydrating); -function resetChildExpirationTime(completedWork) { - if ( - renderExpirationTime$1 !== Never && - completedWork.childExpirationTime === Never - ) { - // The children of this component are hidden. Don't bubble their - // expiration times. - return; - } + switch (primaryFlags) { + case Placement: { + commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted does + // and isMounted is deprecated anyway so we should be able to kill this. - var newChildExpirationTime = NoWork; // Bubble up the earliest expiration time. + nextEffect.flags &= ~Placement; + break; + } - if ((completedWork.mode & ProfileMode) !== NoMode) { - // In profiling mode, resetChildExpirationTime is also used to reset - // profiler durations. - var actualDuration = completedWork.actualDuration; - var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will - // only be updated if work is done on the fiber (i.e. it doesn't bailout). - // When work is done, it should bubble to the parent's actualDuration. If - // the fiber has not been cloned though, (meaning no work was done), then - // this value will reflect the amount of time spent working on a previous - // render. In that case it should not bubble. We determine whether it was - // cloned by comparing the child pointer. + case PlacementAndUpdate: { + // Placement + commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is + // inserted, before any life-cycles like componentDidMount gets called. - var shouldBubbleActualDurations = - completedWork.alternate === null || - completedWork.child !== completedWork.alternate.child; - var child = completedWork.child; + nextEffect.flags &= ~Placement; // Update - while (child !== null) { - var childUpdateExpirationTime = child.expirationTime; - var childChildExpirationTime = child.childExpirationTime; + var _current = nextEffect.alternate; + commitWork(_current, nextEffect); + break; + } - if (childUpdateExpirationTime > newChildExpirationTime) { - newChildExpirationTime = childUpdateExpirationTime; + case Hydrating: { + nextEffect.flags &= ~Hydrating; + break; } - if (childChildExpirationTime > newChildExpirationTime) { - newChildExpirationTime = childChildExpirationTime; + case HydratingAndUpdate: { + nextEffect.flags &= ~Hydrating; // Update + + var _current2 = nextEffect.alternate; + commitWork(_current2, nextEffect); + break; } - if (shouldBubbleActualDurations) { - actualDuration += child.actualDuration; + case Update: { + var _current3 = nextEffect.alternate; + commitWork(_current3, nextEffect); + break; } - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; + case Deletion: { + commitDeletion(root, nextEffect); + break; + } } - completedWork.actualDuration = actualDuration; - completedWork.treeBaseDuration = treeBaseDuration; - } else { - var _child = completedWork.child; + resetCurrentFiber(); + nextEffect = nextEffect.nextEffect; + } +} - while (_child !== null) { - var _childUpdateExpirationTime = _child.expirationTime; - var _childChildExpirationTime = _child.childExpirationTime; +function commitLayoutEffects(root, committedLanes) { + while (nextEffect !== null) { + setCurrentFiber(nextEffect); + var flags = nextEffect.flags; - if (_childUpdateExpirationTime > newChildExpirationTime) { - newChildExpirationTime = _childUpdateExpirationTime; - } + if (flags & (Update | Callback)) { + var current = nextEffect.alternate; + commitLifeCycles(root, current, nextEffect); + } - if (_childChildExpirationTime > newChildExpirationTime) { - newChildExpirationTime = _childChildExpirationTime; + { + if (flags & Ref) { + commitAttachRef(nextEffect); } - - _child = _child.sibling; } - } - - completedWork.childExpirationTime = newChildExpirationTime; -} -function commitRoot(root) { - var renderPriorityLevel = getCurrentPriorityLevel(); - runWithPriority( - ImmediatePriority, - commitRootImpl.bind(null, root, renderPriorityLevel) - ); - return null; + resetCurrentFiber(); + nextEffect = nextEffect.nextEffect; + } } -function commitRootImpl(root, renderPriorityLevel) { - do { - // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which - // means `flushPassiveEffects` will sometimes result in additional - // passive effects. So we need to keep flushing in a loop until there are - // no more pending effects. - // TODO: Might be better if `flushPassiveEffects` did not automatically - // flush synchronous work at the end, to avoid factoring hazards like this. - flushPassiveEffects(); - } while (rootWithPendingPassiveEffects !== null); - - flushRenderPhaseStrictModeWarningsInDEV(); +function flushPassiveEffects() { + // Returns whether passive effects were flushed. + if (pendingPassiveEffectsRenderPriority !== NoPriority$1) { + var priorityLevel = + pendingPassiveEffectsRenderPriority > NormalPriority$1 + ? NormalPriority$1 + : pendingPassiveEffectsRenderPriority; + pendingPassiveEffectsRenderPriority = NoPriority$1; - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Should not already be working."); + { + return runWithPriority(priorityLevel, flushPassiveEffectsImpl); + } } - var finishedWork = root.finishedWork; - var expirationTime = root.finishedExpirationTime; + return false; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); - if (finishedWork === null) { - return null; + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); } +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); - root.finishedWork = null; - root.finishedExpirationTime = NoWork; + { + fiber.flags |= PassiveUnmountPendingDev; + var alternate = fiber.alternate; - if (!(finishedWork !== root.current)) { - throw Error( - "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." - ); - } // commitRoot never returns a continuation; it always finishes synchronously. - // So we can clear these now to allow a new callback to be scheduled. + if (alternate !== null) { + alternate.flags |= PassiveUnmountPendingDev; + } + } - root.callbackNode = null; - root.callbackExpirationTime = NoWork; - root.callbackPriority = NoPriority; - root.nextKnownPendingLevel = NoWork; - startCommitTimer(); // Update the first and last pending times on this root. The new first - // pending time is whatever is left on the root fiber. + if (!rootDoesHavePassiveEffects) { + rootDoesHavePassiveEffects = true; + scheduleCallback(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + }); + } +} - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - markRootFinishedAtTime( - root, - expirationTime, - remainingExpirationTimeBeforeCommit - ); +function invokePassiveEffectCreate(effect) { + var create = effect.create; + effect.destroy = create(); +} - if (root === workInProgressRoot) { - // We can reset these now that they are finished. - workInProgressRoot = null; - workInProgress = null; - renderExpirationTime$1 = NoWork; - } // This indicates that the last root we worked on is not the same one that - // we're committing now. This most commonly happens when a suspended root - // times out. - // Get the list of effects. +function flushPassiveEffectsImpl() { + if (rootWithPendingPassiveEffects === null) { + return false; + } - var firstEffect; + var root = rootWithPendingPassiveEffects; + var lanes = pendingPassiveEffectsLanes; + rootWithPendingPassiveEffects = null; + pendingPassiveEffectsLanes = NoLanes; - if (finishedWork.effectTag > PerformedWork) { - // A fiber's effect list consists only of its children, not itself. So if - // the root has an effect, we need to add it to the end of the list. The - // resulting list is the set that would belong to the root's parent, if it - // had one; that is, all the effects in the tree including the root. - if (finishedWork.lastEffect !== null) { - finishedWork.lastEffect.nextEffect = finishedWork; - firstEffect = finishedWork.firstEffect; - } else { - firstEffect = finishedWork; - } - } else { - // There is no effect on the root. - firstEffect = finishedWork.firstEffect; + if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { + throw Error("Cannot flush passive effects while already rendering."); } - if (firstEffect !== null) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root); // Reset this to null before calling lifecycles + { + isFlushingPassiveEffects = true; + } - ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass - // of the effect list for each phase: all mutation effects come before all - // layout effects, and so on. - // The first phase a "before mutation" phase. We use this phase to read the - // state of the host tree right before we mutate it. This is where - // getSnapshotBeforeUpdate is called. + var prevExecutionContext = executionContext; + executionContext |= CommitContext; + var prevInteractions = pushInteractions(root); // It's important that ALL pending passive effect destroy functions are called + // before ANY passive effect create functions are called. + // Otherwise effects in sibling components might interfere with each other. + // e.g. a destroy function in one component may unintentionally override a ref + // value set by a create function in another component. + // Layout effects have the same constraint. + // First pass: Destroy stale passive effects. + + var unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + + for (var i = 0; i < unmountEffects.length; i += 2) { + var _effect = unmountEffects[i]; + var fiber = unmountEffects[i + 1]; + var destroy = _effect.destroy; + _effect.destroy = undefined; - startCommitSnapshotEffectsTimer(); - prepareForCommit(root.containerInfo); - nextEffect = firstEffect; + { + fiber.flags &= ~PassiveUnmountPendingDev; + var alternate = fiber.alternate; - do { + if (alternate !== null) { + alternate.flags &= ~PassiveUnmountPendingDev; + } + } + + if (typeof destroy === "function") { { - invokeGuardedCallback(null, commitBeforeMutationEffects, null); + setCurrentFiber(fiber); + + { + invokeGuardedCallback(null, destroy, null); + } if (hasCaughtError()) { - if (!(nextEffect !== null)) { + if (!(fiber !== null)) { throw Error("Should be working on an effect."); } var error = clearCaughtError(); - captureCommitPhaseError(nextEffect, error); - nextEffect = nextEffect.nextEffect; + captureCommitPhaseError(fiber, error); } + + resetCurrentFiber(); } - } while (nextEffect !== null); + } + } // Second pass: Create new passive effects. - stopCommitSnapshotEffectsTimer(); + var mountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; - { - // Mark the current commit time to be shared by all Profilers in this - // batch. This enables them to be grouped later. - recordCommitTime(); - } // The next phase is the mutation phase, where we mutate the host tree. + for (var _i = 0; _i < mountEffects.length; _i += 2) { + var _effect2 = mountEffects[_i]; + var _fiber = mountEffects[_i + 1]; - startCommitHostEffectsTimer(); - nextEffect = firstEffect; + { + setCurrentFiber(_fiber); - do { { - invokeGuardedCallback( - null, - commitMutationEffects, - null, - root, - renderPriorityLevel - ); + invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2); + } - if (hasCaughtError()) { - if (!(nextEffect !== null)) { - throw Error("Should be working on an effect."); - } + if (hasCaughtError()) { + if (!(_fiber !== null)) { + throw Error("Should be working on an effect."); + } - var _error = clearCaughtError(); + var _error4 = clearCaughtError(); - captureCommitPhaseError(nextEffect, _error); - nextEffect = nextEffect.nextEffect; - } + captureCommitPhaseError(_fiber, _error4); } - } while (nextEffect !== null); - stopCommitHostEffectsTimer(); - resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after - // the mutation phase, so that the previous tree is still current during - // componentWillUnmount, but before the layout phase, so that the finished - // work is current during componentDidMount/Update. + resetCurrentFiber(); + } + } // Note: This currently assumes there are no passive effects on the root fiber + // because the root is not part of its own effect list. + // This could change in the future. - root.current = finishedWork; // The next phase is the layout phase, where we call effects that read - // the host tree after it's been mutated. The idiomatic use case for this is - // layout, but class component lifecycles also fire here for legacy reasons. + var effect = root.current.firstEffect; - startCommitLifeCyclesTimer(); - nextEffect = firstEffect; + while (effect !== null) { + var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC - do { - { - invokeGuardedCallback( - null, - commitLayoutEffects, - null, - root, - expirationTime - ); + effect.nextEffect = null; - if (hasCaughtError()) { - if (!(nextEffect !== null)) { - throw Error("Should be working on an effect."); - } + if (effect.flags & Deletion) { + detachFiberAfterEffects(effect); + } - var _error2 = clearCaughtError(); + effect = nextNextEffect; + } - captureCommitPhaseError(nextEffect, _error2); - nextEffect = nextEffect.nextEffect; + { + popInteractions(prevInteractions); + finishPendingInteractions(root, lanes); + } + + { + isFlushingPassiveEffects = false; + } + + executionContext = prevExecutionContext; + flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this + // exceeds the limit, we'll fire a warning. + + nestedPassiveUpdateCount = + rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; + return true; +} + +function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ); +} +function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance); + } +} + +function prepareToThrowUncaughtError(error) { + if (!hasUncaughtError) { + hasUncaughtError = true; + firstUncaughtError = error; + } +} + +var onUncaughtError = prepareToThrowUncaughtError; + +function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + var errorInfo = createCapturedValue(error, sourceFiber); + var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); + enqueueUpdate(rootFiber, update); + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(rootFiber, SyncLane); + + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, SyncLane); + } +} + +function captureCommitPhaseError(sourceFiber, error) { + if (sourceFiber.tag === HostRoot) { + // Error was thrown at the root. There is no parent, so the root + // itself should capture it. + captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error); + return; + } + + var fiber = sourceFiber.return; + + while (fiber !== null) { + if (fiber.tag === HostRoot) { + captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error); + return; + } else if (fiber.tag === ClassComponent) { + var ctor = fiber.type; + var instance = fiber.stateNode; + + if ( + typeof ctor.getDerivedStateFromError === "function" || + (typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance)) + ) { + var errorInfo = createCapturedValue(error, sourceFiber); + var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); + enqueueUpdate(fiber, update); + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(fiber, SyncLane); + + if (root !== null) { + markRootUpdated(root, SyncLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, SyncLane); + } else { + // This component has already been unmounted. + // We can't schedule any follow up work for the root because the fiber is already unmounted, + // but we can still call the log-only boundary so the error isn't swallowed. + // + // TODO This is only a temporary bandaid for the old reconciler fork. + // We can delete this special case once the new fork is merged. + if ( + typeof instance.componentDidCatch === "function" && + !isAlreadyFailedLegacyErrorBoundary(instance) + ) { + try { + instance.componentDidCatch(error, errorInfo); + } catch (errorToIgnore) { + // TODO Ignore this error? Rethrow it? + // This is kind of an edge case. + } + } } + + return; } - } while (nextEffect !== null); + } - stopCommitLifeCyclesTimer(); - nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an - // opportunity to paint. + fiber = fiber.return; + } +} +function pingSuspendedRoot(root, wakeable, pingedLanes) { + var pingCache = root.pingCache; - requestPaint(); + if (pingCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + pingCache.delete(wakeable); + } - { - popInteractions(prevInteractions); + var eventTime = requestEventTime(); + markRootPinged(root, pingedLanes); + + if ( + workInProgressRoot === root && + isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes) + ) { + // Received a ping at the same priority level at which we're currently + // rendering. We might want to restart this render. This should mirror + // the logic of whether or not a root suspends once it completes. + // TODO: If we're rendering sync either due to Sync, Batched or expired, + // we should probably never restart. + // If we're suspended with delay, or if it's a retry, we'll always suspend + // so we can always restart. + if ( + workInProgressRootExitStatus === RootSuspendedWithDelay || + (workInProgressRootExitStatus === RootSuspended && + includesOnlyRetries(workInProgressRootRenderLanes) && + now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + ) { + // Restart from the root. + prepareFreshStack(root, NoLanes); + } else { + // Even though we can't restart right now, we might get an + // opportunity later. So we mark this render as having a ping. + workInProgressRootPingedLanes = mergeLanes( + workInProgressRootPingedLanes, + pingedLanes + ); } + } - executionContext = prevExecutionContext; - } else { - // No effects. - root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were - // no effects. - // TODO: Maybe there's a better way to report this. + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, pingedLanes); +} + +function retryTimedOutBoundary(boundaryFiber, retryLane) { + // The boundary fiber (a Suspense component or SuspenseList component) + // previously was rendered in its fallback state. One of the promises that + // suspended it has resolved, which means at least part of the tree was + // likely unblocked. Try rendering again, at a new expiration time. + if (retryLane === NoLane) { + retryLane = requestRetryLane(boundaryFiber); + } // TODO: Special case idle priority? + + var eventTime = requestEventTime(); + var root = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane); + + if (root !== null) { + markRootUpdated(root, retryLane, eventTime); + ensureRootIsScheduled(root, eventTime); + schedulePendingInteractions(root, retryLane); + } +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = NoLane; // Default + + var retryCache; + + { + retryCache = boundaryFiber.stateNode; + } + + if (retryCache !== null) { + // The wakeable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(wakeable); + } + + retryTimedOutBoundary(boundaryFiber, retryLane); +} // Computes the next Just Noticeable Difference (JND) boundary. +// The theory is that a person can't tell the difference between small differences in time. +// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable +// difference in the experience. However, waiting for longer might mean that we can avoid +// showing an intermediate loading state. The longer we have already waited, the harder it +// is to tell small differences in time. Therefore, the longer we've already waited, +// the longer we can wait additionally. At some point we have to give up though. +// We pick a train model where the next boundary commits at a consistent schedule. +// These particular numbers are vague estimates. We expect to adjust them based on research. - startCommitSnapshotEffectsTimer(); - stopCommitSnapshotEffectsTimer(); +function jnd(timeElapsed) { + return timeElapsed < 120 + ? 120 + : timeElapsed < 480 + ? 480 + : timeElapsed < 1080 + ? 1080 + : timeElapsed < 1920 + ? 1920 + : timeElapsed < 3000 + ? 3000 + : timeElapsed < 4320 + ? 4320 + : ceil(timeElapsed / 1960) * 1960; +} + +function checkForNestedUpdates() { + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + nestedUpdateCount = 0; + rootWithNestedUpdates = null; { - recordCommitTime(); + throw Error( + "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." + ); } - - startCommitHostEffectsTimer(); - stopCommitHostEffectsTimer(); - startCommitLifeCyclesTimer(); - stopCommitLifeCyclesTimer(); } - stopCommitTimer(); - var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; - - if (rootDoesHavePassiveEffects) { - // This commit has passive effects. Stash a reference to them. But don't - // schedule a callback until after flushing layout work. - rootDoesHavePassiveEffects = false; - rootWithPendingPassiveEffects = root; - pendingPassiveEffectsExpirationTime = expirationTime; - pendingPassiveEffectsRenderPriority = renderPriorityLevel; - } else { - // We are done with the effect chain at this point so let's clear the - // nextEffect pointers to assist with GC. If we have passive effects, we'll - // clear this in flushPassiveEffects. - nextEffect = firstEffect; + { + if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { + nestedPassiveUpdateCount = 0; - while (nextEffect !== null) { - var nextNextEffect = nextEffect.nextEffect; - nextEffect.nextEffect = null; - nextEffect = nextNextEffect; + error( + "Maximum update depth exceeded. This can happen when a component " + + "calls setState inside useEffect, but useEffect either doesn't " + + "have a dependency array, or one of the dependencies changes on " + + "every render." + ); } - } // Check if there's remaining work on this root + } +} - var remainingExpirationTime = root.firstPendingTime; +function flushRenderPhaseStrictModeWarningsInDEV() { + { + ReactStrictModeWarnings.flushLegacyContextWarning(); - if (remainingExpirationTime !== NoWork) { { - if (spawnedWorkDuringRender !== null) { - var expirationTimes = spawnedWorkDuringRender; - spawnedWorkDuringRender = null; - - for (var i = 0; i < expirationTimes.length; i++) { - scheduleInteractions( - root, - expirationTimes[i], - root.memoizedInteractions - ); - } - } - - schedulePendingInteractions(root, remainingExpirationTime); + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); } - } else { - // If there's no remaining work, we can clear the set of already failed - // error boundaries. - legacyErrorBoundariesThatAlreadyFailed = null; } +} + +var didWarnStateUpdateForNotYetMountedComponent = null; +function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { { - if (!rootDidHavePassiveEffects) { - // If there are no passive effects, then we can complete the pending interactions. - // Otherwise, we'll wait until after the passive effects are flushed. - // Wait to do this until after remaining work has been scheduled, - // so that we don't prematurely signal complete for interactions when there's e.g. hidden work. - finishPendingInteractions(root, expirationTime); + if ((executionContext & RenderContext) !== NoContext) { + // We let the other warning about render phase updates deal with this one. + return; } - } - if (remainingExpirationTime === Sync) { - // Count the number of times the root synchronously re-renders without - // finishing. If there are too many, it indicates an infinite update loop. - if (root === rootWithNestedUpdates) { - nestedUpdateCount++; - } else { - nestedUpdateCount = 0; - rootWithNestedUpdates = root; + if (!(fiber.mode & (BlockingMode | ConcurrentMode))) { + return; } - } else { - nestedUpdateCount = 0; - } - onCommitRoot(finishedWork.stateNode, expirationTime); // Always call this before exiting `commitRoot`, to ensure that any - // additional work on this root is scheduled. + var tag = fiber.tag; - ensureRootIsScheduled(root); + if ( + tag !== IndeterminateComponent && + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. - if (hasUncaughtError) { - hasUncaughtError = false; - var _error3 = firstUncaughtError; - firstUncaughtError = null; - throw _error3; - } + var componentName = getComponentName(fiber.type) || "ReactComponent"; - if ((executionContext & LegacyUnbatchedContext) !== NoContext) { - // This is a legacy edge case. We just committed the initial mount of - // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired - // synchronously, but layout updates should be deferred until the end - // of the batch. - return null; - } // If layout work was scheduled, flush it now. + if (didWarnStateUpdateForNotYetMountedComponent !== null) { + if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { + return; + } - flushSyncCallbackQueue(); - return null; -} + didWarnStateUpdateForNotYetMountedComponent.add(componentName); + } else { + didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); + } -function commitBeforeMutationEffects() { - while (nextEffect !== null) { - var effectTag = nextEffect.effectTag; + var previousFiber = current; - if ((effectTag & Snapshot) !== NoEffect) { - setCurrentFiber(nextEffect); - recordEffect(); - var current = nextEffect.alternate; - commitBeforeMutationLifeCycles(current, nextEffect); - resetCurrentFiber(); - } + try { + setCurrentFiber(fiber); - if ((effectTag & Passive) !== NoEffect) { - // If there are passive effects, schedule a callback to flush at - // the earliest opportunity. - if (!rootDoesHavePassiveEffects) { - rootDoesHavePassiveEffects = true; - scheduleCallback(NormalPriority, function() { - flushPassiveEffects(); - return null; - }); + error( + "Can't perform a React state update on a component that hasn't mounted yet. " + + "This indicates that you have a side-effect in your render function that " + + "asynchronously later calls tries to update the component. Move this work to " + + "useEffect instead." + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); } } - - nextEffect = nextEffect.nextEffect; } } -function commitMutationEffects(root, renderPriorityLevel) { - // TODO: Should probably move the bulk of this function to commitWork. - while (nextEffect !== null) { - setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; - - if (effectTag & ContentReset) { - commitResetTextContent(nextEffect); - } +var didWarnStateUpdateForUnmountedComponent = null; - if (effectTag & Ref) { - var current = nextEffect.alternate; +function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { + { + var tag = fiber.tag; - if (current !== null) { - commitDetachRef(current); - } - } // The following switch statement is only concerned about placement, - // updates, and deletions. To avoid needing to add a case for every possible - // bitmap value, we remove the secondary effects from the effect tag and - // switch on that value. + if ( + tag !== HostRoot && + tag !== ClassComponent && + tag !== FunctionComponent && + tag !== ForwardRef && + tag !== MemoComponent && + tag !== SimpleMemoComponent + ) { + // Only warn for user-defined components, not internal ones like Suspense. + return; + } // If there are pending passive effects unmounts for this Fiber, + // we can assume that they would have prevented this update. - var primaryEffectTag = - effectTag & (Placement | Update | Deletion | Hydrating); + if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) { + return; + } // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. - switch (primaryEffectTag) { - case Placement: { - commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. - // TODO: findDOMNode doesn't rely on this any more but isMounted does - // and isMounted is deprecated anyway so we should be able to kill this. + var componentName = getComponentName(fiber.type) || "ReactComponent"; - nextEffect.effectTag &= ~Placement; - break; + if (didWarnStateUpdateForUnmountedComponent !== null) { + if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { + return; } - case PlacementAndUpdate: { - // Placement - commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is - // inserted, before any life-cycles like componentDidMount gets called. + didWarnStateUpdateForUnmountedComponent.add(componentName); + } else { + didWarnStateUpdateForUnmountedComponent = new Set([componentName]); + } - nextEffect.effectTag &= ~Placement; // Update + if (isFlushingPassiveEffects); + else { + var previousFiber = current; - var _current = nextEffect.alternate; - commitWork(_current, nextEffect); - break; - } + try { + setCurrentFiber(fiber); - case Hydrating: { - nextEffect.effectTag &= ~Hydrating; - break; + error( + "Can't perform a React state update on an unmounted component. This " + + "is a no-op, but it indicates a memory leak in your application. To " + + "fix, cancel all subscriptions and asynchronous tasks in %s.", + tag === ClassComponent + ? "the componentWillUnmount method" + : "a useEffect cleanup function" + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } } + } + } +} - case HydratingAndUpdate: { - nextEffect.effectTag &= ~Hydrating; // Update +var beginWork$1; - var _current2 = nextEffect.alternate; - commitWork(_current2, nextEffect); - break; - } +{ + var dummyFiber = null; - case Update: { - var _current3 = nextEffect.alternate; - commitWork(_current3, nextEffect); - break; - } + beginWork$1 = function(current, unitOfWork, lanes) { + // If a component throws an error, we replay it again in a synchronously + // dispatched event, so that the debugger will treat it as an uncaught + // error See ReactErrorUtils for more information. + // Before entering the begin phase, copy the work-in-progress onto a dummy + // fiber. If beginWork throws, we'll use this to reset the state. + var originalWorkInProgressCopy = assignFiberPropertiesInDEV( + dummyFiber, + unitOfWork + ); - case Deletion: { - commitDeletion(root, nextEffect, renderPriorityLevel); - break; - } - } // TODO: Only record a mutation effect if primaryEffectTag is non-zero. + try { + return beginWork(current, unitOfWork, lanes); + } catch (originalError) { + if ( + originalError !== null && + typeof originalError === "object" && + typeof originalError.then === "function" + ) { + // Don't replay promises. Treat everything else like an error. + throw originalError; + } // Keep this code in sync with handleError; any changes here must have + // corresponding changes there. + + resetContextDependencies(); + resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the + // same fiber again. + // Unwind the failed stack frame + + unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber. + + assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); - recordEffect(); - resetCurrentFiber(); - nextEffect = nextEffect.nextEffect; - } -} + if (unitOfWork.mode & ProfileMode) { + // Reset the profiler timer. + startProfilerTimer(unitOfWork); + } // Run beginWork again. -function commitLayoutEffects(root, committedExpirationTime) { - // TODO: Should probably move the bulk of this function to commitWork. - while (nextEffect !== null) { - setCurrentFiber(nextEffect); - var effectTag = nextEffect.effectTag; + invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); - if (effectTag & (Update | Callback)) { - recordEffect(); - var current = nextEffect.alternate; - commitLifeCycles(root, current, nextEffect); - } + if (hasCaughtError()) { + var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`. + // Rethrow this error instead of the original one. - if (effectTag & Ref) { - recordEffect(); - commitAttachRef(nextEffect); + throw replayError; + } else { + // This branch is reachable if the render phase is impure. + throw originalError; + } } - - resetCurrentFiber(); - nextEffect = nextEffect.nextEffect; - } + }; } -function flushPassiveEffects() { - if (pendingPassiveEffectsRenderPriority !== NoPriority) { - var priorityLevel = - pendingPassiveEffectsRenderPriority > NormalPriority - ? NormalPriority - : pendingPassiveEffectsRenderPriority; - pendingPassiveEffectsRenderPriority = NoPriority; - return runWithPriority(priorityLevel, flushPassiveEffectsImpl); - } +var didWarnAboutUpdateInRender = false; +var didWarnAboutUpdateInRenderForAnotherComponent; + +{ + didWarnAboutUpdateInRenderForAnotherComponent = new Set(); } -function flushPassiveEffectsImpl() { - if (rootWithPendingPassiveEffects === null) { - return false; - } +function warnAboutRenderPhaseUpdatesInDEV(fiber) { + { + if ( + isRendering && + (executionContext & RenderContext) !== NoContext && + !getIsUpdatingOpaqueValueInRenderPhaseInDEV() + ) { + switch (fiber.tag) { + case FunctionComponent: + case ForwardRef: + case SimpleMemoComponent: { + var renderingComponentName = + (workInProgress && getComponentName(workInProgress.type)) || + "Unknown"; // Dedupe by the rendering component because it's the one that needs to be fixed. - var root = rootWithPendingPassiveEffects; - var expirationTime = pendingPassiveEffectsExpirationTime; - rootWithPendingPassiveEffects = null; - pendingPassiveEffectsExpirationTime = NoWork; + var dedupeKey = renderingComponentName; - if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) { - throw Error("Cannot flush passive effects while already rendering."); - } + if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { + didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); + var setStateComponentName = + getComponentName(fiber.type) || "Unknown"; - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root); + error( + "Cannot update a component (`%s`) while rendering a " + + "different component (`%s`). To locate the bad setState() call inside `%s`, " + + "follow the stack trace as described in https://reactjs.org/link/setstate-in-render", + setStateComponentName, + renderingComponentName, + renderingComponentName + ); + } - { - // Note: This currently assumes there are no passive effects on the root fiber - // because the root is not part of its own effect list. - // This could change in the future. - var _effect2 = root.current.firstEffect; + break; + } - while (_effect2 !== null) { - { - setCurrentFiber(_effect2); - invokeGuardedCallback(null, commitPassiveHookEffects, null, _effect2); + case ClassComponent: { + if (!didWarnAboutUpdateInRender) { + error( + "Cannot update during an existing state transition (such as " + + "within `render`). Render methods should be a pure " + + "function of props and state." + ); - if (hasCaughtError()) { - if (!(_effect2 !== null)) { - throw Error("Should be working on an effect."); + didWarnAboutUpdateInRender = true; } - var _error5 = clearCaughtError(); - - captureCommitPhaseError(_effect2, _error5); + break; } - - resetCurrentFiber(); } - - var nextNextEffect = _effect2.nextEffect; // Remove nextEffect pointer to assist GC - - _effect2.nextEffect = null; - _effect2 = nextNextEffect; } } +} // a 'shared' variable that changes when act() opens/closes in tests. +var IsThisRendererActing = { + current: false +}; +function warnIfNotScopedWithMatchingAct(fiber) { { - popInteractions(prevInteractions); - finishPendingInteractions(root, expirationTime); - } - - executionContext = prevExecutionContext; - flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this - // exceeds the limit, we'll fire a warning. - - nestedPassiveUpdateCount = - rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1; - return true; -} + if ( + IsSomeRendererActing.current === true && + IsThisRendererActing.current !== true + ) { + var previousFiber = current; -function isAlreadyFailedLegacyErrorBoundary(instance) { - return ( - legacyErrorBoundariesThatAlreadyFailed !== null && - legacyErrorBoundariesThatAlreadyFailed.has(instance) - ); -} -function markLegacyErrorBoundaryAsFailed(instance) { - if (legacyErrorBoundariesThatAlreadyFailed === null) { - legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); - } else { - legacyErrorBoundariesThatAlreadyFailed.add(instance); - } -} + try { + setCurrentFiber(fiber); -function prepareToThrowUncaughtError(error) { - if (!hasUncaughtError) { - hasUncaughtError = true; - firstUncaughtError = error; + error( + "It looks like you're using the wrong act() around your test interactions.\n" + + "Be sure to use the matching version of act() corresponding to your renderer:\n\n" + + "// for react-dom:\n" + // Break up imports to avoid accidentally parsing them as dependencies. + "import {act} fr" + + "om 'react-dom/test-utils';\n" + + "// ...\n" + + "act(() => ...);\n\n" + + "// for react-test-renderer:\n" + // Break up imports to avoid accidentally parsing them as dependencies. + "import TestRenderer fr" + + "om react-test-renderer';\n" + + "const {act} = TestRenderer;\n" + + "// ...\n" + + "act(() => ...);" + ); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); + } + } + } } } - -var onUncaughtError = prepareToThrowUncaughtError; - -function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { - var errorInfo = createCapturedValue(error, sourceFiber); - var update = createRootErrorUpdate(rootFiber, errorInfo, Sync); - enqueueUpdate(rootFiber, update); - var root = markUpdateTimeFromFiberToRoot(rootFiber, Sync); - - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, Sync); +function warnIfNotCurrentlyActingEffectsInDEV(fiber) { + { + if ( + (fiber.mode & StrictMode) !== NoMode && + IsSomeRendererActing.current === false && + IsThisRendererActing.current === false + ) { + error( + "An update to %s ran an effect, but was not wrapped in act(...).\n\n" + + "When testing, code that causes React state updates should be " + + "wrapped into act(...):\n\n" + + "act(() => {\n" + + " /* fire events that update state */\n" + + "});\n" + + "/* assert on the output */\n\n" + + "This ensures that you're testing the behavior the user would see " + + "in the browser." + + " Learn more at https://reactjs.org/link/wrap-tests-with-act", + getComponentName(fiber.type) + ); + } } } -function captureCommitPhaseError(sourceFiber, error) { - if (sourceFiber.tag === HostRoot) { - // Error was thrown at the root. There is no parent, so the root - // itself should capture it. - captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error); - return; - } - - var fiber = sourceFiber.return; +function warnIfNotCurrentlyActingUpdatesInDEV(fiber) { + { + if ( + executionContext === NoContext && + IsSomeRendererActing.current === false && + IsThisRendererActing.current === false + ) { + var previousFiber = current; - while (fiber !== null) { - if (fiber.tag === HostRoot) { - captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error); - return; - } else if (fiber.tag === ClassComponent) { - var ctor = fiber.type; - var instance = fiber.stateNode; + try { + setCurrentFiber(fiber); - if ( - typeof ctor.getDerivedStateFromError === "function" || - (typeof instance.componentDidCatch === "function" && - !isAlreadyFailedLegacyErrorBoundary(instance)) - ) { - var errorInfo = createCapturedValue(error, sourceFiber); - var update = createClassErrorUpdate( - fiber, - errorInfo, // TODO: This is always sync - Sync + error( + "An update to %s inside a test was not wrapped in act(...).\n\n" + + "When testing, code that causes React state updates should be " + + "wrapped into act(...):\n\n" + + "act(() => {\n" + + " /* fire events that update state */\n" + + "});\n" + + "/* assert on the output */\n\n" + + "This ensures that you're testing the behavior the user would see " + + "in the browser." + + " Learn more at https://reactjs.org/link/wrap-tests-with-act", + getComponentName(fiber.type) ); - enqueueUpdate(fiber, update); - var root = markUpdateTimeFromFiberToRoot(fiber, Sync); - - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, Sync); + } finally { + if (previousFiber) { + setCurrentFiber(fiber); + } else { + resetCurrentFiber(); } - - return; } } - - fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { - var pingCache = root.pingCache; - if (pingCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - pingCache.delete(thenable); - } +var warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV; // In tests, we want to enforce a mocked scheduler. - if (workInProgressRoot === root && renderExpirationTime$1 === suspendedTime) { - // Received a ping at the same priority level at which we're currently - // rendering. We might want to restart this render. This should mirror - // the logic of whether or not a root suspends once it completes. - // TODO: If we're rendering sync either due to Sync, Batched or expired, - // we should probably never restart. - // If we're suspended with delay, we'll always suspend so we can always - // restart. If we're suspended without any updates, it might be a retry. - // If it's early in the retry we can restart. We can't know for sure - // whether we'll eventually process an update during this render pass, - // but it's somewhat unlikely that we get to a ping before that, since - // getting to the root most update is usually very fast. +var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked +// scheduler is the actual recommendation. The alternative could be a testing build, +// a new lib, or whatever; we dunno just yet. This message is for early adopters +// to get their tests right. + +function warnIfUnmockedScheduler(fiber) { + { if ( - workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - workInProgressRootLatestProcessedExpirationTime === Sync && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) + didWarnAboutUnmockedScheduler === false && + Scheduler.unstable_flushAllWithoutAsserting === undefined ) { - // Restart from the root. Don't need to schedule a ping because - // we're already working on this tree. - prepareFreshStack(root, renderExpirationTime$1); - } else { - // Even though we can't restart right now, we might get an - // opportunity later. So we mark this render as having a ping. - workInProgressRootHasPendingPing = true; - } + if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { + didWarnAboutUnmockedScheduler = true; - return; + error( + 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + + "to guarantee consistent behaviour across tests and browsers. " + + "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. + "jest.mock('scheduler', () => require" + + "('scheduler/unstable_mock'));\n\n" + + "For more info, visit https://reactjs.org/link/mock-scheduler" + ); + } + } } +} - if (!isRootSuspendedAtTime(root, suspendedTime)) { - // The root is no longer suspended at this time. - return; +function computeThreadID(root, lane) { + // Interaction threads are unique per root and expiration time. + // NOTE: Intentionally unsound cast. All that matters is that it's a number + // and it represents a batch of work. Could make a helper function instead, + // but meh this is fine for now. + return lane * 1000 + root.interactionThreadID; +} + +function markSpawnedWork(lane) { + if (spawnedWorkDuringRender === null) { + spawnedWorkDuringRender = [lane]; + } else { + spawnedWorkDuringRender.push(lane); } +} - var lastPingedTime = root.lastPingedTime; +function scheduleInteractions(root, lane, interactions) { + if (interactions.size > 0) { + var pendingInteractionMap = root.pendingInteractionMap; + var pendingInteractions = pendingInteractionMap.get(lane); - if (lastPingedTime !== NoWork && lastPingedTime < suspendedTime) { - // There's already a lower priority ping scheduled. - return; - } // Mark the time at which this ping was scheduled. + if (pendingInteractions != null) { + interactions.forEach(function(interaction) { + if (!pendingInteractions.has(interaction)) { + // Update the pending async work count for previously unscheduled interaction. + interaction.__count++; + } - root.lastPingedTime = suspendedTime; - ensureRootIsScheduled(root); - schedulePendingInteractions(root, suspendedTime); -} + pendingInteractions.add(interaction); + }); + } else { + pendingInteractionMap.set(lane, new Set(interactions)); // Update the pending async work count for the current interactions. -function retryTimedOutBoundary(boundaryFiber, retryTime) { - // The boundary fiber (a Suspense component or SuspenseList component) - // previously was rendered in its fallback state. One of the promises that - // suspended it has resolved, which means at least part of the tree was - // likely unblocked. Try rendering again, at a new expiration time. - if (retryTime === NoWork) { - var suspenseConfig = null; // Retries don't carry over the already committed update. - - var currentTime = requestCurrentTimeForUpdate(); - retryTime = computeExpirationForFiber( - currentTime, - boundaryFiber, - suspenseConfig - ); - } // TODO: Special case idle priority? + interactions.forEach(function(interaction) { + interaction.__count++; + }); + } - var root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime); + var subscriber = tracing.__subscriberRef.current; - if (root !== null) { - ensureRootIsScheduled(root); - schedulePendingInteractions(root, retryTime); + if (subscriber !== null) { + var threadID = computeThreadID(root, lane); + subscriber.onWorkScheduled(interactions, threadID); + } } } -function resolveRetryThenable(boundaryFiber, thenable) { - var retryTime = NoWork; // Default - var retryCache; +function schedulePendingInteractions(root, lane) { + scheduleInteractions(root, lane, tracing.__interactionsRef.current); +} - { - retryCache = boundaryFiber.stateNode; - } +function startWorkOnPendingInteractions(root, lanes) { + // we can accurately attribute time spent working on it, And so that cascading + // work triggered during the render phase will be associated with it. - if (retryCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(thenable); - } + var interactions = new Set(); + root.pendingInteractionMap.forEach(function( + scheduledInteractions, + scheduledLane + ) { + if (includesSomeLane(lanes, scheduledLane)) { + scheduledInteractions.forEach(function(interaction) { + return interactions.add(interaction); + }); + } + }); // Store the current set of interactions on the FiberRoot for a few reasons: + // We can re-use it in hot functions like performConcurrentWorkOnRoot() + // without having to recalculate it. We will also use it in commitWork() to + // pass to any Profiler onRender() hooks. This also provides DevTools with a + // way to access it when the onCommitRoot() hook is called. - retryTimedOutBoundary(boundaryFiber, retryTime); -} // Computes the next Just Noticeable Difference (JND) boundary. -// The theory is that a person can't tell the difference between small differences in time. -// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable -// difference in the experience. However, waiting for longer might mean that we can avoid -// showing an intermediate loading state. The longer we have already waited, the harder it -// is to tell small differences in time. Therefore, the longer we've already waited, -// the longer we can wait additionally. At some point we have to give up though. -// We pick a train model where the next boundary commits at a consistent schedule. -// These particular numbers are vague estimates. We expect to adjust them based on research. + root.memoizedInteractions = interactions; -function jnd(timeElapsed) { - return timeElapsed < 120 - ? 120 - : timeElapsed < 480 - ? 480 - : timeElapsed < 1080 - ? 1080 - : timeElapsed < 1920 - ? 1920 - : timeElapsed < 3000 - ? 3000 - : timeElapsed < 4320 - ? 4320 - : ceil(timeElapsed / 1960) * 1960; -} + if (interactions.size > 0) { + var subscriber = tracing.__subscriberRef.current; -function computeMsUntilSuspenseLoadingDelay( - mostRecentEventTime, - committedExpirationTime, - suspenseConfig -) { - var busyMinDurationMs = suspenseConfig.busyMinDurationMs | 0; + if (subscriber !== null) { + var threadID = computeThreadID(root, lanes); - if (busyMinDurationMs <= 0) { - return 0; + try { + subscriber.onWorkStarted(interactions, threadID); + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } + } } +} - var busyDelayMs = suspenseConfig.busyDelayMs | 0; // Compute the time until this render pass would expire. +function finishPendingInteractions(root, committedLanes) { + var remainingLanesAfterCommit = root.pendingLanes; + var subscriber; - var currentTimeMs = now(); - var eventTimeMs = inferTimeFromExpirationTimeWithSuspenseConfig( - mostRecentEventTime, - suspenseConfig - ); - var timeElapsed = currentTimeMs - eventTimeMs; + try { + subscriber = tracing.__subscriberRef.current; - if (timeElapsed <= busyDelayMs) { - // If we haven't yet waited longer than the initial delay, we don't - // have to wait any additional time. - return 0; - } + if (subscriber !== null && root.memoizedInteractions.size > 0) { + // FIXME: More than one lane can finish in a single commit. + var threadID = computeThreadID(root, committedLanes); + subscriber.onWorkStopped(root.memoizedInteractions, threadID); + } + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } finally { + // Clear completed interactions from the pending Map. + // Unless the render was suspended or cascading work was scheduled, + // In which case– leave pending interactions until the subsequent render. + var pendingInteractionMap = root.pendingInteractionMap; + pendingInteractionMap.forEach(function(scheduledInteractions, lane) { + // Only decrement the pending interaction count if we're done. + // If there's still work at the current priority, + // That indicates that we are waiting for suspense data. + if (!includesSomeLane(remainingLanesAfterCommit, lane)) { + pendingInteractionMap.delete(lane); + scheduledInteractions.forEach(function(interaction) { + interaction.__count--; - var msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed; // This is the value that is passed to `setTimeout`. + if (subscriber !== null && interaction.__count === 0) { + try { + subscriber.onInteractionScheduledWorkCompleted(interaction); + } catch (error) { + // If the subscriber throws, rethrow it in a separate task + scheduleCallback(ImmediatePriority$1, function() { + throw error; + }); + } + } + }); + } + }); + } +} // `act` testing API - return msUntilTimeout; +function shouldForceFlushFallbacksInDEV() { + // Never force flush in production. This function should get stripped out. + return actingUpdatesScopeDepth > 0; } +// so we can tell if any async act() calls try to run in parallel. -function checkForNestedUpdates() { - if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { - nestedUpdateCount = 0; - rootWithNestedUpdates = null; +var actingUpdatesScopeDepth = 0; - { - throw Error( - "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." - ); - } - } +function detachFiberAfterEffects(fiber) { + fiber.sibling = null; + fiber.stateNode = null; +} - { - if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { - nestedPassiveUpdateCount = 0; +var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. - error( - "Maximum update depth exceeded. This can happen when a component " + - "calls setState inside useEffect, but useEffect either doesn't " + - "have a dependency array, or one of the dependencies changes on " + - "every render." - ); - } +var failedBoundaries = null; +var setRefreshHandler = function(handler) { + { + resolveFamily = handler; } -} - -function flushRenderPhaseStrictModeWarningsInDEV() { +}; +function resolveFunctionForHotReloading(type) { { - ReactStrictModeWarnings.flushLegacyContextWarning(); - - { - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; } - } -} -function stopFinishedWorkLoopTimer() { - var didCompleteRoot = true; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} + var family = resolveFamily(type); -function stopInterruptedWorkLoopTimer() { - // TODO: Track which fiber caused the interruption. - var didCompleteRoot = false; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} + if (family === undefined) { + return type; + } // Use the latest known implementation. -function checkForInterruption(fiberThatReceivedUpdate, updateExpirationTime) { - if ( - workInProgressRoot !== null && - updateExpirationTime > renderExpirationTime$1 - ) { - interruptedBy = fiberThatReceivedUpdate; + return family.current; } } +function resolveClassForHotReloading(type) { + // No implementation differences. + return resolveFunctionForHotReloading(type); +} +function resolveForwardRefForHotReloading(type) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return type; + } -var didWarnStateUpdateForUnmountedComponent = null; + var family = resolveFamily(type); -function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { - { - var tag = fiber.tag; + if (family === undefined) { + // Check if we're dealing with a real forwardRef. Don't want to crash early. + if ( + type !== null && + type !== undefined && + typeof type.render === "function" + ) { + // ForwardRef is special because its resolved .type is an object, + // but it's possible that we only have its inner render function in the map. + // If that inner render function is different, we'll build a new forwardRef type. + var currentRender = resolveFunctionForHotReloading(type.render); - if ( - tag !== HostRoot && - tag !== ClassComponent && - tag !== FunctionComponent && - tag !== ForwardRef && - tag !== MemoComponent && - tag !== SimpleMemoComponent && - tag !== Block - ) { - // Only warn for user-defined components, not internal ones like Suspense. - return; - } - // the problematic code almost always lies inside that component. + if (type.render !== currentRender) { + var syntheticType = { + $$typeof: REACT_FORWARD_REF_TYPE, + render: currentRender + }; - var componentName = getComponentName(fiber.type) || "ReactComponent"; + if (type.displayName !== undefined) { + syntheticType.displayName = type.displayName; + } - if (didWarnStateUpdateForUnmountedComponent !== null) { - if (didWarnStateUpdateForUnmountedComponent.has(componentName)) { - return; + return syntheticType; + } } - didWarnStateUpdateForUnmountedComponent.add(componentName); - } else { - didWarnStateUpdateForUnmountedComponent = new Set([componentName]); - } + return type; + } // Use the latest known implementation. - error( - "Can't perform a React state update on an unmounted component. This " + - "is a no-op, but it indicates a memory leak in your application. To " + - "fix, cancel all subscriptions and asynchronous tasks in %s.%s", - tag === ClassComponent - ? "the componentWillUnmount method" - : "a useEffect cleanup function", - getStackByFiberInDevAndProd(fiber) - ); + return family.current; } } +function isCompatibleFamilyForHotReloading(fiber, element) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return false; + } -var beginWork$1; - -{ - var dummyFiber = null; - - beginWork$1 = function(current, unitOfWork, expirationTime) { - // If a component throws an error, we replay it again in a synchronously - // dispatched event, so that the debugger will treat it as an uncaught - // error See ReactErrorUtils for more information. - // Before entering the begin phase, copy the work-in-progress onto a dummy - // fiber. If beginWork throws, we'll use this to reset the state. - var originalWorkInProgressCopy = assignFiberPropertiesInDEV( - dummyFiber, - unitOfWork - ); - - try { - return beginWork(current, unitOfWork, expirationTime); - } catch (originalError) { - if ( - originalError !== null && - typeof originalError === "object" && - typeof originalError.then === "function" - ) { - // Don't replay promises. Treat everything else like an error. - throw originalError; - } // Keep this code in sync with handleError; any changes here must have - // corresponding changes there. + var prevType = fiber.elementType; + var nextType = element.type; // If we got here, we know types aren't === equal. - resetContextDependencies(); - resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the - // same fiber again. - // Unwind the failed stack frame + var needsCompareFamilies = false; + var $$typeofNextType = + typeof nextType === "object" && nextType !== null + ? nextType.$$typeof + : null; - unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber. + switch (fiber.tag) { + case ClassComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } - assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); + break; + } - if (unitOfWork.mode & ProfileMode) { - // Reset the profiler timer. - startProfilerTimer(unitOfWork); - } // Run beginWork again. + case FunctionComponent: { + if (typeof nextType === "function") { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + // We don't know the inner type yet. + // We're going to assume that the lazy inner type is stable, + // and so it is sufficient to avoid reconciling it away. + // We're not going to unwrap or actually use the new lazy type. + needsCompareFamilies = true; + } - invokeGuardedCallback( - null, - beginWork, - null, - current, - unitOfWork, - expirationTime - ); + break; + } - if (hasCaughtError()) { - var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`. - // Rethrow this error instead of the original one. + case ForwardRef: { + if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } - throw replayError; - } else { - // This branch is reachable if the render phase is impure. - throw originalError; + break; } - } - }; -} -var didWarnAboutUpdateInRender = false; + case MemoComponent: + case SimpleMemoComponent: { + if ($$typeofNextType === REACT_MEMO_TYPE) { + // TODO: if it was but can no longer be simple, + // we shouldn't set this. + needsCompareFamilies = true; + } else if ($$typeofNextType === REACT_LAZY_TYPE) { + needsCompareFamilies = true; + } -function warnAboutRenderPhaseUpdatesInDEV(fiber) { - { - if ((executionContext & RenderContext) !== NoContext) { - switch (fiber.tag) { - case FunctionComponent: - case ForwardRef: - case SimpleMemoComponent: { - error( - "Cannot update a component from inside the function body of a " + - "different component." - ); + break; + } - break; - } + default: + return false; + } // Check if both types have a family and it's the same one. - case ClassComponent: { - if (isRendering && !didWarnAboutUpdateInRender) { - error( - "Cannot update during an existing state transition (such as " + - "within `render`). Render methods should be a pure " + - "function of props and state." - ); + if (needsCompareFamilies) { + // Note: memo() and forwardRef() we'll compare outer rather than inner type. + // This means both of them need to be registered to preserve state. + // If we unwrapped and compared the inner types for wrappers instead, + // then we would risk falsely saying two separate memo(Foo) + // calls are equivalent because they wrap the same Foo function. + var prevFamily = resolveFamily(prevType); - didWarnAboutUpdateInRender = true; - break; - } - } + if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { + return true; } } - } -} // a 'shared' variable that changes when act() opens/closes in tests. -var IsThisRendererActing = { - current: false -}; -function warnIfNotScopedWithMatchingAct(fiber) { - { - if ( - IsSomeRendererActing.current === true && - IsThisRendererActing.current !== true - ) { - error( - "It looks like you're using the wrong act() around your test interactions.\n" + - "Be sure to use the matching version of act() corresponding to your renderer:\n\n" + - "// for react-dom:\n" + // Break up imports to avoid accidentally parsing them as dependencies. - "import {act} fr" + - "om 'react-dom/test-utils';\n" + - "// ...\n" + - "act(() => ...);\n\n" + - "// for react-test-renderer:\n" + // Break up imports to avoid accidentally parsing them as dependencies. - "import TestRenderer fr" + - "om react-test-renderer';\n" + - "const {act} = TestRenderer;\n" + - "// ...\n" + - "act(() => ...);" + - "%s", - getStackByFiberInDevAndProd(fiber) - ); - } + return false; } } -function warnIfNotCurrentlyActingEffectsInDEV(fiber) { +function markFailedErrorBoundaryForHotReloading(fiber) { { - if ( - (fiber.mode & StrictMode) !== NoMode && - IsSomeRendererActing.current === false && - IsThisRendererActing.current === false - ) { - error( - "An update to %s ran an effect, but was not wrapped in act(...).\n\n" + - "When testing, code that causes React state updates should be " + - "wrapped into act(...):\n\n" + - "act(() => {\n" + - " /* fire events that update state */\n" + - "});\n" + - "/* assert on the output */\n\n" + - "This ensures that you're testing the behavior the user would see " + - "in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act" + - "%s", - getComponentName(fiber.type), - getStackByFiberInDevAndProd(fiber) - ); + if (resolveFamily === null) { + // Hot reloading is disabled. + return; } - } -} -function warnIfNotCurrentlyActingUpdatesInDEV(fiber) { - { - if ( - executionContext === NoContext && - IsSomeRendererActing.current === false && - IsThisRendererActing.current === false - ) { - error( - "An update to %s inside a test was not wrapped in act(...).\n\n" + - "When testing, code that causes React state updates should be " + - "wrapped into act(...):\n\n" + - "act(() => {\n" + - " /* fire events that update state */\n" + - "});\n" + - "/* assert on the output */\n\n" + - "This ensures that you're testing the behavior the user would see " + - "in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act" + - "%s", - getComponentName(fiber.type), - getStackByFiberInDevAndProd(fiber) - ); + if (typeof WeakSet !== "function") { + return; } + + if (failedBoundaries === null) { + failedBoundaries = new WeakSet(); + } + + failedBoundaries.add(fiber); } } +var scheduleRefresh = function(root, update) { + { + if (resolveFamily === null) { + // Hot reloading is disabled. + return; + } -var warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV; // In tests, we want to enforce a mocked scheduler. + var staleFamilies = update.staleFamilies, + updatedFamilies = update.updatedFamilies; + flushPassiveEffects(); + flushSync(function() { + scheduleFibersWithFamiliesRecursively( + root.current, + updatedFamilies, + staleFamilies + ); + }); + } +}; +var scheduleRoot = function(root, element) { + { + if (root.context !== emptyContextObject) { + // Super edge case: root has a legacy _renderSubtree context + // but we don't know the parentComponent so we can't pass it. + // Just ignore. We'll delete this with _renderSubtree code path later. + return; + } -var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked -// scheduler is the actual recommendation. The alternative could be a testing build, -// a new lib, or whatever; we dunno just yet. This message is for early adopters -// to get their tests right. + flushPassiveEffects(); + flushSync(function() { + updateContainer(element, root, null, null); + }); + } +}; -function warnIfUnmockedScheduler(fiber) { +function scheduleFibersWithFamiliesRecursively( + fiber, + updatedFamilies, + staleFamilies +) { { - if ( - didWarnAboutUnmockedScheduler === false && - Scheduler.unstable_flushAllWithoutAsserting === undefined - ) { - if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) { - didWarnAboutUnmockedScheduler = true; + var alternate = fiber.alternate, + child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; - error( - 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + - "to guarantee consistent behaviour across tests and browsers. " + - "For example, with jest: \n" + // Break up requires to avoid accidentally parsing them as dependencies. - "jest.mock('scheduler', () => require" + - "('scheduler/unstable_mock'));\n\n" + - "For more info, visit https://fb.me/react-mock-scheduler" - ); - } + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; + + case ForwardRef: + candidateType = type.render; + break; } - } -} -function computeThreadID(root, expirationTime) { - // Interaction threads are unique per root and expiration time. - return expirationTime * 1000 + root.interactionThreadID; -} + if (resolveFamily === null) { + throw new Error("Expected resolveFamily to be set during hot reload."); + } -function markSpawnedWork(expirationTime) { - if (spawnedWorkDuringRender === null) { - spawnedWorkDuringRender = [expirationTime]; - } else { - spawnedWorkDuringRender.push(expirationTime); - } -} + var needsRender = false; + var needsRemount = false; -function scheduleInteractions(root, expirationTime, interactions) { - if (interactions.size > 0) { - var pendingInteractionMap = root.pendingInteractionMap; - var pendingInteractions = pendingInteractionMap.get(expirationTime); + if (candidateType !== null) { + var family = resolveFamily(candidateType); - if (pendingInteractions != null) { - interactions.forEach(function(interaction) { - if (!pendingInteractions.has(interaction)) { - // Update the pending async work count for previously unscheduled interaction. - interaction.__count++; + if (family !== undefined) { + if (staleFamilies.has(family)) { + needsRemount = true; + } else if (updatedFamilies.has(family)) { + if (tag === ClassComponent) { + needsRemount = true; + } else { + needsRender = true; + } } + } + } - pendingInteractions.add(interaction); - }); - } else { - pendingInteractionMap.set(expirationTime, new Set(interactions)); // Update the pending async work count for the current interactions. + if (failedBoundaries !== null) { + if ( + failedBoundaries.has(fiber) || + (alternate !== null && failedBoundaries.has(alternate)) + ) { + needsRemount = true; + } + } - interactions.forEach(function(interaction) { - interaction.__count++; - }); + if (needsRemount) { + fiber._debugNeedsRemount = true; } - var subscriber = tracing.__subscriberRef.current; + if (needsRemount || needsRender) { + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } - if (subscriber !== null) { - var threadID = computeThreadID(root, expirationTime); - subscriber.onWorkScheduled(interactions, threadID); + if (child !== null && !needsRemount) { + scheduleFibersWithFamiliesRecursively( + child, + updatedFamilies, + staleFamilies + ); } - } -} -function schedulePendingInteractions(root, expirationTime) { - scheduleInteractions(root, expirationTime, tracing.__interactionsRef.current); + if (sibling !== null) { + scheduleFibersWithFamiliesRecursively( + sibling, + updatedFamilies, + staleFamilies + ); + } + } } -function startWorkOnPendingInteractions(root, expirationTime) { - // we can accurately attribute time spent working on it, And so that cascading - // work triggered during the render phase will be associated with it. +var findHostInstancesForRefresh = function(root, families) { + { + var hostInstances = new Set(); + var types = new Set( + families.map(function(family) { + return family.current; + }) + ); + findHostInstancesForMatchingFibersRecursively( + root.current, + types, + hostInstances + ); + return hostInstances; + } +}; - var interactions = new Set(); - root.pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - if (scheduledExpirationTime >= expirationTime) { - scheduledInteractions.forEach(function(interaction) { - return interactions.add(interaction); - }); - } - }); // Store the current set of interactions on the FiberRoot for a few reasons: - // We can re-use it in hot functions like performConcurrentWorkOnRoot() - // without having to recalculate it. We will also use it in commitWork() to - // pass to any Profiler onRender() hooks. This also provides DevTools with a - // way to access it when the onCommitRoot() hook is called. +function findHostInstancesForMatchingFibersRecursively( + fiber, + types, + hostInstances +) { + { + var child = fiber.child, + sibling = fiber.sibling, + tag = fiber.tag, + type = fiber.type; + var candidateType = null; - root.memoizedInteractions = interactions; + switch (tag) { + case FunctionComponent: + case SimpleMemoComponent: + case ClassComponent: + candidateType = type; + break; - if (interactions.size > 0) { - var subscriber = tracing.__subscriberRef.current; + case ForwardRef: + candidateType = type.render; + break; + } - if (subscriber !== null) { - var threadID = computeThreadID(root, expirationTime); + var didMatch = false; - try { - subscriber.onWorkStarted(interactions, threadID); - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); + if (candidateType !== null) { + if (types.has(candidateType)) { + didMatch = true; } } - } -} - -function finishPendingInteractions(root, committedExpirationTime) { - var earliestRemainingTimeAfterCommit = root.firstPendingTime; - var subscriber; - - try { - subscriber = tracing.__subscriberRef.current; - if (subscriber !== null && root.memoizedInteractions.size > 0) { - var threadID = computeThreadID(root, committedExpirationTime); - subscriber.onWorkStopped(root.memoizedInteractions, threadID); + if (didMatch) { + // We have a match. This only drills down to the closest host components. + // There's no need to search deeper because for the purpose of giving + // visual feedback, "flashing" outermost parent rectangles is sufficient. + findHostInstancesForFiberShallowly(fiber, hostInstances); + } else { + // If there's no match, maybe there will be one further down in the child tree. + if (child !== null) { + findHostInstancesForMatchingFibersRecursively( + child, + types, + hostInstances + ); + } } - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); - } finally { - // Clear completed interactions from the pending Map. - // Unless the render was suspended or cascading work was scheduled, - // In which case– leave pending interactions until the subsequent render. - var pendingInteractionMap = root.pendingInteractionMap; - pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - // Only decrement the pending interaction count if we're done. - // If there's still work at the current priority, - // That indicates that we are waiting for suspense data. - if (scheduledExpirationTime > earliestRemainingTimeAfterCommit) { - pendingInteractionMap.delete(scheduledExpirationTime); - scheduledInteractions.forEach(function(interaction) { - interaction.__count--; - if (subscriber !== null && interaction.__count === 0) { - try { - subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error) { - // If the subscriber throws, rethrow it in a separate task - scheduleCallback(ImmediatePriority, function() { - throw error; - }); - } - } - }); - } - }); + if (sibling !== null) { + findHostInstancesForMatchingFibersRecursively( + sibling, + types, + hostInstances + ); + } } } -var onScheduleFiberRoot = null; -var onCommitFiberRoot = null; -var onCommitFiberUnmount = null; -var hasLoggedError = false; -var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } +function findHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var foundHostInstances = findChildHostInstancesForFiberShallowly( + fiber, + hostInstances + ); - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (foundHostInstances) { + return; + } // If we didn't find any host children, fallback to closest host parent. - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } + var node = fiber; - if (!hook.supportsFiber) { - { - error( - "The installed version of React DevTools is too old and will not work " + - "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" - ); - } // DevTools exists, even though it doesn't support Fiber. + while (true) { + switch (node.tag) { + case HostComponent: + hostInstances.add(node.stateNode); + return; - return true; - } + case HostPortal: + hostInstances.add(node.stateNode.containerInfo); + return; - try { - var rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. + case HostRoot: + hostInstances.add(node.stateNode.containerInfo); + return; + } - if (true) { - // Only used by Fast Refresh - if (typeof hook.onScheduleFiberRoot === "function") { - onScheduleFiberRoot = function(root, children) { - try { - hook.onScheduleFiberRoot(rendererID, root, children); - } catch (err) { - if (true && !hasLoggedError) { - hasLoggedError = true; - - error("React instrumentation encountered an error: %s", err); - } - } - }; + if (node.return === null) { + throw new Error("Expected to reach root first."); } - } - onCommitFiberRoot = function(root, expirationTime) { - try { - var didError = (root.current.effectTag & DidCapture) === DidCapture; + node = node.return; + } + } +} - if (enableProfilerTimer) { - var currentTime = getCurrentTime(); - var priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - hook.onCommitFiberRoot(rendererID, root, priorityLevel, didError); - } else { - hook.onCommitFiberRoot(rendererID, root, undefined, didError); - } - } catch (err) { - if (true) { - if (!hasLoggedError) { - hasLoggedError = true; +function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { + { + var node = fiber; + var foundHostInstances = false; - error("React instrumentation encountered an error: %s", err); - } - } + while (true) { + if (node.tag === HostComponent) { + // We got a match. + foundHostInstances = true; + hostInstances.add(node.stateNode); // There may still be more, so keep searching. + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; } - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) { - if (true) { - if (!hasLoggedError) { - hasLoggedError = true; + if (node === fiber) { + return foundHostInstances; + } - error("React instrumentation encountered an error: %s", err); - } + while (node.sibling === null) { + if (node.return === null || node.return === fiber) { + return foundHostInstances; } + + node = node.return; } - }; - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - error("React instrumentation encountered an error: %s.", err); - } - } // DevTools exists - return true; -} -function onScheduleRoot(root, children) { - if (typeof onScheduleFiberRoot === "function") { - onScheduleFiberRoot(root, children); - } -} -function onCommitRoot(root, expirationTime) { - if (typeof onCommitFiberRoot === "function") { - onCommitFiberRoot(root, expirationTime); - } -} -function onCommitUnmount(fiber) { - if (typeof onCommitFiberUnmount === "function") { - onCommitFiberUnmount(fiber); + node.sibling.return = node.return; + node = node.sibling; + } } + + return false; } var hasBadMapPolyfill; @@ -19629,13 +20580,11 @@ var hasBadMapPolyfill; try { var nonExtensibleObject = Object.preventExtensions({}); - var testMap = new Map([[nonExtensibleObject, null]]); - var testSet = new Set([nonExtensibleObject]); // This is necessary for Rollup to not consider these unused. - // https://github.com/rollup/rollup/issues/1771 - // TODO: we can remove these if Rollup fixes the bug. + /* eslint-disable no-new */ - testMap.set(0, 0); - testSet.add(0); + new Map([[nonExtensibleObject, null]]); + new Set([nonExtensibleObject]); + /* eslint-enable no-new */ } catch (e) { // TODO: Consider warning about bad polyfills hasBadMapPolyfill = true; @@ -19664,12 +20613,12 @@ function FiberNode(tag, pendingProps, key, mode) { this.dependencies = null; this.mode = mode; // Effects - this.effectTag = NoEffect; + this.flags = NoFlags; this.nextEffect = null; this.firstEffect = null; this.lastEffect = null; - this.expirationTime = NoWork; - this.childExpirationTime = NoWork; + this.lanes = NoLanes; + this.childLanes = NoLanes; this.alternate = null; { @@ -19696,15 +20645,11 @@ function FiberNode(tag, pendingProps, key, mode) { this.actualStartTime = -1; this.selfBaseDuration = 0; this.treeBaseDuration = 0; - } // This is normally DEV-only except www when it adds listeners. - // TODO: remove the User Timing integration in favor of Root Events. - - { - this._debugID = debugCounter++; - this._debugIsCurrentlyTiming = false; } { + // This isn't directly used but is handy for debugging internals: + this._debugID = debugCounter++; this._debugSource = null; this._debugOwner = null; this._debugNeedsRemount = false; @@ -19784,10 +20729,7 @@ function createWorkInProgress(current, pendingProps) { { // DEV-only fields - { - workInProgress._debugID = current._debugID; - } - + workInProgress._debugID = current._debugID; workInProgress._debugSource = current._debugSource; workInProgress._debugOwner = current._debugOwner; workInProgress._debugHookTypes = current._debugHookTypes; @@ -19796,10 +20738,12 @@ function createWorkInProgress(current, pendingProps) { workInProgress.alternate = current; current.alternate = workInProgress; } else { - workInProgress.pendingProps = pendingProps; // We already have an alternate. + workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. + + workInProgress.type = current.type; // We already have an alternate. // Reset the effect tag. - workInProgress.effectTag = NoEffect; // The effect list is no longer valid. + workInProgress.flags = NoFlags; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -19815,8 +20759,8 @@ function createWorkInProgress(current, pendingProps) { } } - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -19828,9 +20772,8 @@ function createWorkInProgress(current, pendingProps) { currentDependencies === null ? null : { - expirationTime: currentDependencies.expirationTime, - firstContext: currentDependencies.firstContext, - responders: currentDependencies.responders + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext }; // These will be overridden during the parent's reconciliation workInProgress.sibling = current.sibling; @@ -19865,7 +20808,7 @@ function createWorkInProgress(current, pendingProps) { return workInProgress; } // Used to reuse a Fiber for a second pass. -function resetWorkInProgress(workInProgress, renderExpirationTime) { +function resetWorkInProgress(workInProgress, renderLanes) { // This resets the Fiber to what createFiber or createWorkInProgress would // have set the values to before during the first pass. Ideally this wouldn't // be necessary but unfortunately many code paths reads from the workInProgress @@ -19874,7 +20817,7 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { // avoid doing another reconciliation. // Reset the effect tag but keep any Placement tags, since that's something // that child fiber is setting, not the reconciliation. - workInProgress.effectTag &= Placement; // The effect list is no longer valid. + workInProgress.flags &= Placement; // The effect list is no longer valid. workInProgress.nextEffect = null; workInProgress.firstEffect = null; @@ -19883,13 +20826,14 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { if (current === null) { // Reset to createFiber's initial values. - workInProgress.childExpirationTime = NoWork; - workInProgress.expirationTime = renderExpirationTime; + workInProgress.childLanes = NoLanes; + workInProgress.lanes = renderLanes; workInProgress.child = null; workInProgress.memoizedProps = null; workInProgress.memoizedState = null; workInProgress.updateQueue = null; workInProgress.dependencies = null; + workInProgress.stateNode = null; { // Note: We don't reset the actualTime counts. It's useful to accumulate @@ -19899,12 +20843,14 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { } } else { // Reset to the cloned values that createWorkInProgress would've. - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so + workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. + + workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so // it cannot be shared with the current fiber. var currentDependencies = current.dependencies; @@ -19912,9 +20858,8 @@ function resetWorkInProgress(workInProgress, renderExpirationTime) { currentDependencies === null ? null : { - expirationTime: currentDependencies.expirationTime, - firstContext: currentDependencies.firstContext, - responders: currentDependencies.responders + lanes: currentDependencies.lanes, + firstContext: currentDependencies.firstContext }; { @@ -19953,9 +20898,8 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { - var fiber; var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. var resolvedType = type; @@ -19977,16 +20921,11 @@ function createFiberFromTypeAndProps( } else { getTag: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); + return createFiberFromFragment(pendingProps.children, mode, lanes, key); - case REACT_CONCURRENT_MODE_TYPE: + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = Mode; - mode |= ConcurrentMode | BlockingMode | StrictMode; + mode |= DebugTracingMode; break; case REACT_STRICT_MODE_TYPE: @@ -19995,18 +20934,23 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: - return createFiberFromProfiler(pendingProps, mode, expirationTime, key); + return createFiberFromProfiler(pendingProps, mode, lanes, key); case REACT_SUSPENSE_TYPE: - return createFiberFromSuspense(pendingProps, mode, expirationTime, key); + return createFiberFromSuspense(pendingProps, mode, lanes, key); case REACT_SUSPENSE_LIST_TYPE: - return createFiberFromSuspenseList( - pendingProps, - mode, - expirationTime, - key - ); + return createFiberFromSuspenseList(pendingProps, mode, lanes, key); + + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + + case REACT_LEGACY_HIDDEN_TYPE: + return createFiberFromLegacyHidden(pendingProps, mode, lanes, key); + + case REACT_SCOPE_TYPE: + + // eslint-disable-next-line no-fallthrough default: { if (typeof type === "object" && type !== null) { @@ -20037,10 +20981,6 @@ function createFiberFromTypeAndProps( fiberTag = LazyComponent; resolvedType = null; break getTag; - - case REACT_BLOCK_TYPE: - fiberTag = Block; - break getTag; } } @@ -20078,13 +21018,18 @@ function createFiberFromTypeAndProps( } } - fiber = createFiber(fiberTag, pendingProps, key, mode); + var fiber = createFiber(fiberTag, pendingProps, key, mode); fiber.elementType = type; fiber.type = resolvedType; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; + + { + fiber._debugOwner = owner; + } + return fiber; } -function createFiberFromElement(element, mode, expirationTime) { +function createFiberFromElement(element, mode, lanes) { var owner = null; { @@ -20100,7 +21045,7 @@ function createFiberFromElement(element, mode, expirationTime) { pendingProps, owner, mode, - expirationTime + lanes ); { @@ -20110,13 +21055,13 @@ function createFiberFromElement(element, mode, expirationTime) { return fiber; } -function createFiberFromFragment(elements, mode, expirationTime, key) { +function createFiberFromFragment(elements, mode, lanes, key) { var fiber = createFiber(Fragment, elements, key, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { +function createFiberFromProfiler(pendingProps, mode, lanes, key) { { if (typeof pendingProps.id !== "string") { error('Profiler must specify an "id" as a prop'); @@ -20127,7 +21072,7 @@ function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { fiber.elementType = REACT_PROFILER_TYPE; fiber.type = REACT_PROFILER_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; { fiber.stateNode = { @@ -20139,17 +21084,17 @@ function createFiberFromProfiler(pendingProps, mode, expirationTime, key) { return fiber; } -function createFiberFromSuspense(pendingProps, mode, expirationTime, key) { +function createFiberFromSuspense(pendingProps, mode, lanes, key) { var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); // TODO: The SuspenseComponent fiber shouldn't have a type. It has a tag. // This needs to be fixed in getComponentName so that it relies on the tag // instead. fiber.type = REACT_SUSPENSE_TYPE; fiber.elementType = REACT_SUSPENSE_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromSuspenseList(pendingProps, mode, expirationTime, key) { +function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); { @@ -20160,18 +21105,44 @@ function createFiberFromSuspenseList(pendingProps, mode, expirationTime, key) { } fiber.elementType = REACT_SUSPENSE_LIST_TYPE; - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); // TODO: The OffscreenComponent fiber shouldn't have a type. It has a tag. + // This needs to be fixed in getComponentName so that it relies on the tag + // instead. + + { + fiber.type = REACT_OFFSCREEN_TYPE; + } + + fiber.elementType = REACT_OFFSCREEN_TYPE; + fiber.lanes = lanes; + return fiber; +} +function createFiberFromLegacyHidden(pendingProps, mode, lanes, key) { + var fiber = createFiber(LegacyHiddenComponent, pendingProps, key, mode); // TODO: The LegacyHidden fiber shouldn't have a type. It has a tag. + // This needs to be fixed in getComponentName so that it relies on the tag + // instead. + + { + fiber.type = REACT_LEGACY_HIDDEN_TYPE; + } + + fiber.elementType = REACT_LEGACY_HIDDEN_TYPE; + fiber.lanes = lanes; return fiber; } -function createFiberFromText(content, mode, expirationTime) { +function createFiberFromText(content, mode, lanes) { var fiber = createFiber(HostText, content, null, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; return fiber; } -function createFiberFromPortal(portal, mode, expirationTime) { +function createFiberFromPortal(portal, mode, lanes) { var pendingProps = portal.children !== null ? portal.children : []; var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.expirationTime = expirationTime; + fiber.lanes = lanes; fiber.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -20208,12 +21179,12 @@ function assignFiberPropertiesInDEV(target, source) { target.memoizedState = source.memoizedState; target.dependencies = source.dependencies; target.mode = source.mode; - target.effectTag = source.effectTag; + target.flags = source.flags; target.nextEffect = source.nextEffect; target.firstEffect = source.firstEffect; target.lastEffect = source.lastEffect; - target.expirationTime = source.expirationTime; - target.childExpirationTime = source.childExpirationTime; + target.lanes = source.lanes; + target.childLanes = source.childLanes; target.alternate = source.alternate; { @@ -20223,11 +21194,7 @@ function assignFiberPropertiesInDEV(target, source) { target.treeBaseDuration = source.treeBaseDuration; } - { - target._debugID = source._debugID; - target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; - } - + target._debugID = source._debugID; target._debugSource = source._debugSource; target._debugOwner = source._debugOwner; target._debugNeedsRemount = source._debugNeedsRemount; @@ -20237,30 +21204,49 @@ function assignFiberPropertiesInDEV(target, source) { function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; this.pendingChildren = null; + this.current = null; this.pingCache = null; - this.finishedExpirationTime = NoWork; this.finishedWork = null; this.timeoutHandle = noTimeout; this.context = null; this.pendingContext = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = NoPriority; - this.firstPendingTime = NoWork; - this.firstSuspendedTime = NoWork; - this.lastSuspendedTime = NoWork; - this.nextKnownPendingLevel = NoWork; - this.lastPingedTime = NoWork; - this.lastExpiredTime = NoWork; + this.callbackPriority = NoLanePriority; + this.eventTimes = createLaneMap(NoLanes); + this.expirationTimes = createLaneMap(NoTimestamp); + this.pendingLanes = NoLanes; + this.suspendedLanes = NoLanes; + this.pingedLanes = NoLanes; + this.expiredLanes = NoLanes; + this.mutableReadLanes = NoLanes; + this.finishedLanes = NoLanes; + this.entangledLanes = NoLanes; + this.entanglements = createLaneMap(NoLanes); { this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); } + + { + switch (tag) { + case BlockingRoot: + this._debugRootType = "createBlockingRoot()"; + break; + + case ConcurrentRoot: + this._debugRootType = "createRoot()"; + break; + + case LegacyRoot: + this._debugRootType = "createLegacyRoot()"; + break; + } + } } function createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks) { @@ -20273,95 +21259,22 @@ function createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks) { initializeUpdateQueue(uninitializedFiber); return root; } -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - var lastSuspendedTime = root.lastSuspendedTime; - return ( - firstSuspendedTime !== NoWork && - firstSuspendedTime >= expirationTime && - lastSuspendedTime <= expirationTime - ); -} -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - var lastSuspendedTime = root.lastSuspendedTime; - - if (firstSuspendedTime < expirationTime) { - root.firstSuspendedTime = expirationTime; - } - - if (lastSuspendedTime > expirationTime || firstSuspendedTime === NoWork) { - root.lastSuspendedTime = expirationTime; - } - - if (expirationTime <= root.lastPingedTime) { - root.lastPingedTime = NoWork; - } - - if (expirationTime <= root.lastExpiredTime) { - root.lastExpiredTime = NoWork; - } -} -function markRootUpdatedAtTime(root, expirationTime) { - // Update the range of pending times - var firstPendingTime = root.firstPendingTime; - - if (expirationTime > firstPendingTime) { - root.firstPendingTime = expirationTime; - } // Update the range of suspended times. Treat everything lower priority or - // equal to this update as unsuspended. - var firstSuspendedTime = root.firstSuspendedTime; - - if (firstSuspendedTime !== NoWork) { - if (expirationTime >= firstSuspendedTime) { - // The entire suspended range is now unsuspended. - root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork; - } else if (expirationTime >= root.lastSuspendedTime) { - root.lastSuspendedTime = expirationTime + 1; - } // This is a pending level. Check if it's higher priority than the next - // known pending level. - - if (expirationTime > root.nextKnownPendingLevel) { - root.nextKnownPendingLevel = expirationTime; - } - } -} -function markRootFinishedAtTime( - root, - finishedExpirationTime, - remainingExpirationTime +function createPortal( + children, + containerInfo, // TODO: figure out the API for cross-renderer implementation. + implementation ) { - // Update the range of pending times - root.firstPendingTime = remainingExpirationTime; // Update the range of suspended times. Treat everything higher priority or - // equal to this update as unsuspended. - - if (finishedExpirationTime <= root.lastSuspendedTime) { - // The entire suspended range is now unsuspended. - root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork; - } else if (finishedExpirationTime <= root.firstSuspendedTime) { - // Part of the suspended range is now unsuspended. Narrow the range to - // include everything between the unsuspended time (non-inclusive) and the - // last suspended time. - root.firstSuspendedTime = finishedExpirationTime - 1; - } - - if (finishedExpirationTime <= root.lastPingedTime) { - // Clear the pinged time - root.lastPingedTime = NoWork; - } - - if (finishedExpirationTime <= root.lastExpiredTime) { - // Clear the expired time - root.lastExpiredTime = NoWork; - } -} -function markRootExpiredAtTime(root, expirationTime) { - var lastExpiredTime = root.lastExpiredTime; - - if (lastExpiredTime === NoWork || lastExpiredTime > expirationTime) { - root.lastExpiredTime = expirationTime; - } + var key = + arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } var didWarnAboutNestedUpdates; @@ -20421,31 +21334,42 @@ function findHostInstanceWithWarning(component, methodName) { if (!didWarnAboutFindNodeInStrictMode[componentName]) { didWarnAboutFindNodeInStrictMode[componentName] = true; + var previousFiber = current; - if (fiber.mode & StrictMode) { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which is inside StrictMode. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node%s", - methodName, - methodName, - componentName, - getStackByFiberInDevAndProd(hostFiber) - ); - } else { - error( - "%s is deprecated in StrictMode. " + - "%s was passed an instance of %s which renders StrictMode children. " + - "Instead, add a ref directly to the element you want to reference. " + - "Learn more about using refs safely here: " + - "https://fb.me/react-strict-mode-find-node%s", - methodName, - methodName, - componentName, - getStackByFiberInDevAndProd(hostFiber) - ); + try { + setCurrentFiber(hostFiber); + + if (fiber.mode & StrictMode) { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } else { + error( + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference. " + + "Learn more about using refs safely here: " + + "https://reactjs.org/link/strict-mode-find-node", + methodName, + methodName, + componentName + ); + } + } finally { + // Ideally this should reset to previous but this shouldn't be called in + // render and there's another warning for that anyway. + if (previousFiber) { + setCurrentFiber(previousFiber); + } else { + resetCurrentFiber(); + } } } } @@ -20463,7 +21387,7 @@ function updateContainer(element, container, parentComponent, callback) { } var current$1 = container.current; - var currentTime = requestCurrentTimeForUpdate(); + var eventTime = requestEventTime(); { // $FlowExpectedError - jest isn't a global, and isn't recognized outside of tests @@ -20473,12 +21397,8 @@ function updateContainer(element, container, parentComponent, callback) { } } - var suspenseConfig = requestCurrentSuspenseConfig(); - var expirationTime = computeExpirationForFiber( - currentTime, - current$1, - suspenseConfig - ); + var lane = requestUpdateLane(current$1); + var context = getContextForSubtree(parentComponent); if (container.context === null) { @@ -20501,7 +21421,7 @@ function updateContainer(element, container, parentComponent, callback) { } } - var update = createUpdate(expirationTime, suspenseConfig); // Caution: React DevTools currently depends on this property + var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property // being called "element". update.payload = { @@ -20524,8 +21444,8 @@ function updateContainer(element, container, parentComponent, callback) { } enqueueUpdate(current$1, update); - scheduleWork(current$1, expirationTime); - return expirationTime; + scheduleUpdateOnFiber(current$1, lane, eventTime); + return lane; } function getPublicRootInstance(container) { var containerFiber = container.current; @@ -20551,28 +21471,102 @@ function shouldSuspend(fiber) { return shouldSuspendImpl(fiber); } var overrideHookState = null; +var overrideHookStateDeletePath = null; +var overrideHookStateRenamePath = null; var overrideProps = null; +var overridePropsDeletePath = null; +var overridePropsRenamePath = null; var scheduleUpdate = null; var setSuspenseHandler = null; { - var copyWithSetImpl = function(obj, path, idx, value) { - if (idx >= path.length) { + var copyWithDeleteImpl = function(obj, path, index) { + var key = path[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === path.length) { + if (Array.isArray(updated)) { + updated.splice(key, 1); + } else { + delete updated[key]; + } + + return updated; + } // $FlowFixMe number or string is fine here + + updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); + return updated; + }; + + var copyWithDelete = function(obj, path) { + return copyWithDeleteImpl(obj, path, 0); + }; + + var copyWithRenameImpl = function(obj, oldPath, newPath, index) { + var oldKey = oldPath[index]; + var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); + + if (index + 1 === oldPath.length) { + var newKey = newPath[index]; // $FlowFixMe number or string is fine here + + updated[newKey] = updated[oldKey]; + + if (Array.isArray(updated)) { + updated.splice(oldKey, 1); + } else { + delete updated[oldKey]; + } + } else { + // $FlowFixMe number or string is fine here + updated[oldKey] = copyWithRenameImpl( + // $FlowFixMe number or string is fine here + obj[oldKey], + oldPath, + newPath, + index + 1 + ); + } + + return updated; + }; + + var copyWithRename = function(obj, oldPath, newPath) { + if (oldPath.length !== newPath.length) { + warn("copyWithRename() expects paths of the same length"); + + return; + } else { + for (var i = 0; i < newPath.length - 1; i++) { + if (oldPath[i] !== newPath[i]) { + warn( + "copyWithRename() expects paths to be the same except for the deepest key" + ); + + return; + } + } + } + + return copyWithRenameImpl(obj, oldPath, newPath, 0); + }; + + var copyWithSetImpl = function(obj, path, index, value) { + if (index >= path.length) { return value; } - var key = path[idx]; + var key = path[index]; var updated = Array.isArray(obj) ? obj.slice() : Object.assign({}, obj); // $FlowFixMe number or string is fine here - updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); + updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); return updated; }; var copyWithSet = function(obj, path, value) { return copyWithSetImpl(obj, path, 0, value); - }; // Support DevTools editable values for useState and useReducer. + }; - overrideHookState = function(fiber, id, path, value) { + var findHook = function(fiber, id) { // For now, the "id" of stateful hooks is just the stateful hook index. // This may change in the future with e.g. nested hooks. var currentHook = fiber.memoizedState; @@ -20582,17 +21576,57 @@ var setSuspenseHandler = null; id--; } - if (currentHook !== null) { - var newState = copyWithSet(currentHook.memoizedState, path, value); - currentHook.memoizedState = newState; - currentHook.baseState = newState; // We aren't actually adding an update to the queue, + return currentHook; + }; // Support DevTools editable values for useState and useReducer. + + overrideHookState = function(fiber, id, path, value) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithSet(hook.memoizedState, path, value); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateDeletePath = function(fiber, id, path) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithDelete(hook.memoizedState, path); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, + // because there is no update we can add for useReducer hooks that won't trigger an error. + // (There's no appropriate action type for DevTools overrides.) + // As a result though, React will see the scheduled update as a noop and bailout. + // Shallow cloning props works as a workaround for now to bypass the bailout check. + + fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + } + }; + + overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) { + var hook = findHook(fiber, id); + + if (hook !== null) { + var newState = copyWithRename(hook.memoizedState, oldPath, newPath); + hook.memoizedState = newState; + hook.baseState = newState; // We aren't actually adding an update to the queue, // because there is no update we can add for useReducer hooks that won't trigger an error. // (There's no appropriate action type for DevTools overrides.) // As a result though, React will see the scheduled update as a noop and bailout. // Shallow cloning props works as a workaround for now to bypass the bailout check. fiber.memoizedProps = Object.assign({}, fiber.memoizedProps); - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); } }; // Support DevTools props for function components, forwardRef, memo, host components, etc. @@ -20603,11 +21637,31 @@ var setSuspenseHandler = null; fiber.alternate.pendingProps = fiber.pendingProps; } - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsDeletePath = function(fiber, path) { + fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); + }; + + overridePropsRenamePath = function(fiber, oldPath, newPath) { + fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); + + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; scheduleUpdate = function(fiber) { - scheduleWork(fiber, Sync); + scheduleUpdateOnFiber(fiber, SyncLane, NoTimestamp); }; setSuspenseHandler = function(newShouldSuspendImpl) { @@ -20615,6 +21669,24 @@ var setSuspenseHandler = null; }; } +function findHostInstanceByFiber(fiber) { + var hostFiber = findCurrentHostFiber(fiber); + + if (hostFiber === null) { + return null; + } + + return hostFiber.stateNode; +} + +function emptyFindFiberByHostInstance(instance) { + return null; +} + +function getCurrentFiberForDevTools() { + return current; +} + function injectIntoDevTools(devToolsConfig) { var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; @@ -20624,59 +21696,26 @@ function injectIntoDevTools(devToolsConfig) { rendererPackageName: devToolsConfig.rendererPackageName, rendererConfig: devToolsConfig.rendererConfig, overrideHookState: overrideHookState, + overrideHookStateDeletePath: overrideHookStateDeletePath, + overrideHookStateRenamePath: overrideHookStateRenamePath, overrideProps: overrideProps, + overridePropsDeletePath: overridePropsDeletePath, + overridePropsRenamePath: overridePropsRenamePath, setSuspenseHandler: setSuspenseHandler, scheduleUpdate: scheduleUpdate, currentDispatcherRef: ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - var hostFiber = findCurrentHostFiber(fiber); - - if (hostFiber === null) { - return null; - } - - return hostFiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - if (!findFiberByHostInstance) { - // Might not be implemented by the renderer. - return null; - } - - return findFiberByHostInstance(instance); - }, + findHostInstanceByFiber: findHostInstanceByFiber, + findFiberByHostInstance: + findFiberByHostInstance || emptyFindFiberByHostInstance, // React Refresh findHostInstancesForRefresh: findHostInstancesForRefresh, scheduleRefresh: scheduleRefresh, scheduleRoot: scheduleRoot, setRefreshHandler: setRefreshHandler, // Enables DevTools to append owner stacks to error messages in DEV mode. - getCurrentFiber: function() { - return current; - } + getCurrentFiber: getCurrentFiberForDevTools }); } -var IsSomeRendererActing$1 = ReactSharedInternals.IsSomeRendererActing; - -function createPortal( - children, - containerInfo, // TODO: figure out the API for cross-renderer implementation. - implementation -) { - var key = - arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - return { - // This tag allow us to uniquely identify this as a React Portal - $$typeof: REACT_PORTAL_TYPE, - key: key == null ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; -} - -// TODO: this is special because it gets imported during build. -var ReactVersion = "16.13.0"; var emptyObject$1 = {}; @@ -20907,7 +21946,7 @@ var getInspectorDataForViewAtPoint; ); } else { error( - "getInspectorDataForViewAtPoint expects to receieve a host component" + "getInspectorDataForViewAtPoint expects to receive a host component" ); return; diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js index 53bb58b0fe5575..ccced617800599 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js @@ -919,7 +919,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_228 = { +var injectedNamesToPlugins$jscomp$inline_222 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -954,34 +954,34 @@ var injectedNamesToPlugins$jscomp$inline_228 = { } } }, - isOrderingDirty$jscomp$inline_229 = !1, - pluginName$jscomp$inline_230; -for (pluginName$jscomp$inline_230 in injectedNamesToPlugins$jscomp$inline_228) + isOrderingDirty$jscomp$inline_223 = !1, + pluginName$jscomp$inline_224; +for (pluginName$jscomp$inline_224 in injectedNamesToPlugins$jscomp$inline_222) if ( - injectedNamesToPlugins$jscomp$inline_228.hasOwnProperty( - pluginName$jscomp$inline_230 + injectedNamesToPlugins$jscomp$inline_222.hasOwnProperty( + pluginName$jscomp$inline_224 ) ) { - var pluginModule$jscomp$inline_231 = - injectedNamesToPlugins$jscomp$inline_228[pluginName$jscomp$inline_230]; + var pluginModule$jscomp$inline_225 = + injectedNamesToPlugins$jscomp$inline_222[pluginName$jscomp$inline_224]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_230) || - namesToPlugins[pluginName$jscomp$inline_230] !== - pluginModule$jscomp$inline_231 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_224) || + namesToPlugins[pluginName$jscomp$inline_224] !== + pluginModule$jscomp$inline_225 ) { - if (namesToPlugins[pluginName$jscomp$inline_230]) + if (namesToPlugins[pluginName$jscomp$inline_224]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_230 + + pluginName$jscomp$inline_224 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_230 - ] = pluginModule$jscomp$inline_231; - isOrderingDirty$jscomp$inline_229 = !0; + pluginName$jscomp$inline_224 + ] = pluginModule$jscomp$inline_225; + isOrderingDirty$jscomp$inline_223 = !0; } } -isOrderingDirty$jscomp$inline_229 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_223 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1137,7 +1137,6 @@ var ReactSharedInternals = REACT_SUSPENSE_LIST_TYPE = 60120, REACT_MEMO_TYPE = 60115, REACT_LAZY_TYPE = 60116, - REACT_BLOCK_TYPE = 60121, REACT_DEBUG_TRACING_MODE_TYPE = 60129, REACT_OFFSCREEN_TYPE = 60130, REACT_LEGACY_HIDDEN_TYPE = 60131; @@ -1155,7 +1154,6 @@ if ("function" === typeof Symbol && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); symbolFor("react.scope"); REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); @@ -1202,8 +1200,6 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); case REACT_LAZY_TYPE: innerType = type._payload; type = type._init; @@ -1221,7 +1217,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1738,7 +1734,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1773,28 +1769,24 @@ var rendererID = null, injectedHook = null, Scheduler_now = Scheduler.unstable_now; Scheduler_now(); -var return_highestLanePriority = 10; +var return_highestLanePriority = 8; function getHighestPriorityLanes(lanes) { - if (0 !== (1 & lanes)) return (return_highestLanePriority = 17), 1; - if (0 !== (2 & lanes)) return (return_highestLanePriority = 16), 2; - if (0 !== (4 & lanes)) return (return_highestLanePriority = 15), 4; + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; var inputDiscreteLanes = 24 & lanes; - if (0 !== inputDiscreteLanes) - return (return_highestLanePriority = 14), inputDiscreteLanes; - if (0 !== (lanes & 32)) return (return_highestLanePriority = 13), 32; - inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 12), inputDiscreteLanes; - if (0 !== (lanes & 256)) return (return_highestLanePriority = 11), 256; - inputDiscreteLanes = 3584 & lanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 10), inputDiscreteLanes; - if (0 !== (lanes & 4096)) return (return_highestLanePriority = 9), 4096; - inputDiscreteLanes = 122880 & lanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 8), inputDiscreteLanes; - if (0 !== (lanes & 131072)) return (return_highestLanePriority = 7), 131072; - inputDiscreteLanes = 3932160 & lanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 6), inputDiscreteLanes; inputDiscreteLanes = 62914560 & lanes; @@ -1808,18 +1800,18 @@ function getHighestPriorityLanes(lanes) { return (return_highestLanePriority = 2), inputDiscreteLanes; if (0 !== (1073741824 & lanes)) return (return_highestLanePriority = 1), 1073741824; - return_highestLanePriority = 10; + return_highestLanePriority = 8; return lanes; } function schedulerPriorityToLanePriority(schedulerPriorityLevel) { switch (schedulerPriorityLevel) { case 99: - return 17; + return 15; case 98: - return 12; + return 10; case 97: case 96: - return 10; + return 8; case 95: return 2; default: @@ -1828,16 +1820,14 @@ function schedulerPriorityToLanePriority(schedulerPriorityLevel) { } function lanePriorityToSchedulerPriority(lanePriority) { switch (lanePriority) { - case 17: - case 16: - return 99; case 15: case 14: + return 99; case 13: case 12: - return 98; case 11: case 10: + return 98; case 9: case 8: case 7: @@ -1867,7 +1857,7 @@ function getNextLanes(root, wipLanes) { pingedLanes = root.pingedLanes; if (0 !== expiredLanes) (nextLanes = expiredLanes), - (nextLanePriority = return_highestLanePriority = 17); + (nextLanePriority = return_highestLanePriority = 15); else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; 0 !== nonIdleUnblockedLanes @@ -1906,42 +1896,31 @@ function getNextLanes(root, wipLanes) { (wipLanes &= ~nextLanePriority); return nextLanes; } -function getMostRecentEventTime(root, lanes) { - root = root.eventTimes; - for (var mostRecentEventTime = -1; 0 < lanes; ) { - var index$6 = 31 - clz32(lanes), - lane = 1 << index$6; - index$6 = root[index$6]; - index$6 > mostRecentEventTime && (mostRecentEventTime = index$6); - lanes &= ~lane; - } - return mostRecentEventTime; -} function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } function findUpdateLane(lanePriority, wipLanes) { switch (lanePriority) { - case 17: + case 15: return 1; - case 16: - return 2; case 14: + return 2; + case 12: return ( (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(12, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority ); - case 12: + case 10: return ( (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority ); - case 10: + case 8: return ( (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), 0 === lanePriority && - ((lanePriority = getHighestPriorityLane(4055040 & ~wipLanes)), + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), 0 === lanePriority && (lanePriority = 512)), lanePriority ); @@ -1959,8 +1938,9 @@ function findUpdateLane(lanePriority, wipLanes) { function getHighestPriorityLane(lanes) { return lanes & -lanes; } -function pickArbitraryLane(lanes) { - return lanes & -lanes; +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; @@ -2077,6 +2057,32 @@ function flushSyncCallbackQueueImpl() { } } } +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +function is(x, y) { + return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); +} +var objectIs = "function" === typeof Object.is ? Object.is : is, + hasOwnProperty = Object.prototype.hasOwnProperty; +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) return !0; + if ( + "object" !== typeof objA || + null === objA || + "object" !== typeof objB || + null === objB + ) + return !1; + var keysA = Object.keys(objA), + keysB = Object.keys(objB); + if (keysA.length !== keysB.length) return !1; + for (keysB = 0; keysB < keysA.length; keysB++) + if ( + !hasOwnProperty.call(objB, keysA[keysB]) || + !objectIs(objA[keysA[keysB]], objB[keysA[keysB]]) + ) + return !1; + return !0; +} function describeFiber(fiber) { switch (fiber.tag) { case 5: @@ -2093,8 +2099,6 @@ function describeFiber(fiber) { return describeFunctionComponentFrame(fiber.type, null); case 11: return describeFunctionComponentFrame(fiber.type.render, null); - case 22: - return describeFunctionComponentFrame(fiber.type._render, null); case 1: return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; default: @@ -2113,31 +2117,6 @@ function getStackByFiberInDevAndProd(workInProgress) { return "\nError generating stack: " + x.message + "\n" + x.stack; } } -function is(x, y) { - return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); -} -var objectIs = "function" === typeof Object.is ? Object.is : is, - hasOwnProperty = Object.prototype.hasOwnProperty; -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) return !0; - if ( - "object" !== typeof objA || - null === objA || - "object" !== typeof objB || - null === objB - ) - return !1; - var keysA = Object.keys(objA), - keysB = Object.keys(objB); - if (keysA.length !== keysB.length) return !1; - for (keysB = 0; keysB < keysA.length; keysB++) - if ( - !hasOwnProperty.call(objB, keysA[keysB]) || - !objectIs(objA[keysA[keysB]], objB[keysA[keysB]]) - ) - return !1; - return !0; -} function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { baseProps = Object.assign({}, baseProps); @@ -2231,11 +2210,10 @@ function cloneUpdateQueue(current, workInProgress) { effects: current.effects }); } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { return { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: 0, payload: null, callback: null, @@ -2268,7 +2246,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: queue.eventTime, lane: queue.lane, - suspenseConfig: queue.suspenseConfig, tag: queue.tag, payload: queue.payload, callback: queue.callback, @@ -2342,16 +2319,11 @@ function processUpdateQueue( (current = current.next = { eventTime: updateEventTime, lane: 0, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, next: null }); - markRenderEventTimeAndConfig( - updateEventTime, - firstBaseUpdate.suspenseConfig - ); a: { var workInProgress = workInProgress$jscomp$0, update = firstBaseUpdate; @@ -2371,8 +2343,7 @@ function processUpdateQueue( currentLastBaseUpdate = workInProgress; break a; case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; + workInProgress.flags = (workInProgress.flags & -8193) | 64; case 0: workInProgress = update.payload; pendingQueue = @@ -2395,7 +2366,7 @@ function processUpdateQueue( } } null !== firstBaseUpdate.callback && - ((workInProgress$jscomp$0.effectTag |= 32), + ((workInProgress$jscomp$0.flags |= 32), (pendingQueue = queue.effects), null === pendingQueue ? (queue.effects = [firstBaseUpdate]) @@ -2404,7 +2375,6 @@ function processUpdateQueue( (updateEventTime = { eventTime: updateEventTime, lane: pendingQueue, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, @@ -2456,8 +2426,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2483,41 +2452,32 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); } }; @@ -2610,7 +2570,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2625,7 +2585,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2659,7 +2619,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2683,7 +2643,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2715,16 +2675,16 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -3259,11 +3219,12 @@ function ChildReconciler(shouldTrackSideEffects) { switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3323,7 +3284,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim() || shim())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3355,7 +3316,7 @@ var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3480,40 +3441,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var suspenseConfig = update.suspenseConfig, - updateLane = update.lane, - updateEventTime = update.eventTime; - (renderLanes & updateLane) === updateLane - ? (null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - eventTime: updateEventTime, - lane: 0, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }), - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig), - (current = - update.eagerReducer === reducer - ? update.eagerState - : reducer(current, update.action))) - : ((suspenseConfig = { - eventTime: updateEventTime, - lane: updateLane, - suspenseConfig: suspenseConfig, + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) + null !== newBaseQueueLast && + (newBaseQueueLast = newBaseQueueLast.next = { + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = suspenseConfig), - (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = suspenseConfig), - (currentlyRenderingFiber$1.lanes |= updateLane), - (workInProgressRootSkippedLanes |= updateLane)); + (current = + update.eagerReducer === reducer + ? update.eagerState + : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3598,10 +3553,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { maybeNewVersion = getSnapshot(source._source); objectIs(snapshot, maybeNewVersion) || (setSnapshot(maybeNewVersion), - (maybeNewVersion = requestUpdateLane( - fiber, - ReactCurrentBatchConfig.suspense - )), + (maybeNewVersion = requestUpdateLane(fiber)), (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); maybeNewVersion = root.mutableReadLanes; root.entangledLanes |= maybeNewVersion; @@ -3610,9 +3562,9 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { 0 < lanes; ) { - var index$14 = 31 - clz32(lanes), - lane = 1 << index$14; - entanglements[index$14] |= maybeNewVersion; + var index$13 = 31 - clz32(lanes), + lane = 1 << index$13; + entanglements[index$13] |= maybeNewVersion; lanes &= ~lane; } } @@ -3626,7 +3578,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { latestSetSnapshot = refs.setSnapshot; try { latestSetSnapshot(latestGetSnapshot(source._source)); - var lane = requestUpdateLane(fiber, ReactCurrentBatchConfig.suspense); + var lane = requestUpdateLane(fiber); root.mutableReadLanes |= lane & root.pendingLanes; } catch (error) { latestSetSnapshot(function() { @@ -3697,17 +3649,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3715,12 +3667,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3759,13 +3711,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3793,39 +3738,36 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(fiber, suspenseConfig); - suspenseConfig = { - eventTime: eventTime, - lane: lane, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || @@ -3841,8 +3783,8 @@ function dispatchAction(fiber, queue, action) { try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { @@ -3870,7 +3812,13 @@ var ContextOnlyDispatcher = { }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3916,36 +3864,30 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; }, useMutableSource: function(source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -3975,36 +3917,27 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4026,36 +3959,27 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4097,11 +4021,11 @@ function updateForwardRef( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } @@ -4138,7 +4062,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -4155,7 +4079,7 @@ function updateMemoComponent( Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -4175,7 +4099,7 @@ function updateSimpleMemoComponent( current.ref === workInProgress.ref ) if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) - 0 !== (current.effectTag & 16384) && (didReceiveUpdate = !0); + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); else return ( (workInProgress.lanes = current.lanes), @@ -4230,7 +4154,7 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, @@ -4255,11 +4179,11 @@ function updateFunctionComponent( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } @@ -4279,7 +4203,7 @@ function updateClassComponent( null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -4345,9 +4269,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4355,7 +4279,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4428,17 +4352,17 @@ function updateClassComponent( oldContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) + (workInProgress.flags |= 256)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4448,11 +4372,11 @@ function updateClassComponent( : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (nextProps = !1)); } return finishClassComponent( @@ -4473,7 +4397,7 @@ function finishClassComponent( renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), @@ -4485,7 +4409,7 @@ function finishClassComponent( didCaptureError && "function" !== typeof Component.getDerivedStateFromError ? null : shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( workInProgress, @@ -4522,50 +4446,48 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = suspenseStackCursor.current, showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((showFallback = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { + current = nextProps.children; + suspenseContext = nextProps.fallback; if (showFallback) return ( - (current = nextProps.fallback), - (suspenseContext = workInProgress.mode), - (showFallback = workInProgress.child), - (nextProps = { mode: "hidden", children: nextProps.children }), - 0 === (suspenseContext & 2) && null !== showFallback - ? ((showFallback.childLanes = 0), - (showFallback.pendingProps = nextProps)) - : (showFallback = createFiberFromOffscreen( - nextProps, - suspenseContext, - 0, - null - )), - (current = createFiberFromFragment( + (current = mountSuspenseFallbackChildren( + workInProgress, current, suspenseContext, - renderLanes, - null + renderLanes )), - (showFallback.return = workInProgress), - (current.return = workInProgress), - (showFallback.sibling = current), - (workInProgress.child = showFallback), (workInProgress.child.memoizedState = { baseLanes: renderLanes }), (workInProgress.memoizedState = SUSPENDED_MARKER), current ); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + current + ); renderLanes = createFiberFromOffscreen( - { mode: "visible", children: nextProps.children }, + { mode: "visible", children: current }, workInProgress.mode, renderLanes, null @@ -4583,13 +4505,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4611,13 +4533,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4630,6 +4552,36 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { workInProgress.memoizedState = null; return renderLanes; } +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren)) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} function updateSuspensePrimaryChildren( current, workInProgress, @@ -4647,7 +4599,7 @@ function updateSuspensePrimaryChildren( primaryChildren.sibling = null; null !== current && ((current.nextEffect = null), - (current.effectTag = 8), + (current.flags = 8), (workInProgress.firstEffect = workInProgress.lastEffect = current)); return (workInProgress.child = primaryChildren); } @@ -4684,7 +4636,7 @@ function updateSuspenseFallbackChildren( renderLanes, null )), - (fallbackChildren.effectTag |= 2)); + (fallbackChildren.flags |= 2)); fallbackChildren.return = workInProgress; primaryChildren.return = workInProgress; primaryChildren.sibling = fallbackChildren; @@ -4713,7 +4665,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4722,7 +4673,6 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } @@ -4733,9 +4683,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && @@ -4870,10 +4820,10 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { current.memoizedProps !== newProps && (requiredContext(contextStackCursor$1.current), (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); }; updateHostText$1 = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.effectTag |= 4); + oldText !== newText && (workInProgress.flags |= 4); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { @@ -4927,7 +4877,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.pendingContext = null)), (null !== current && null !== current.child) || newProps.hydrate || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4945,8 +4895,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -4980,8 +4929,8 @@ function completeWork(current, workInProgress, renderLanes) { appendAllChildren(rootContainerInstance, workInProgress, !1, !1); workInProgress.stateNode = rootContainerInstance; finalizeInitialChildren(rootContainerInstance) && - (workInProgress.effectTag |= 4); - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -5016,7 +4965,7 @@ function completeWork(current, workInProgress, renderLanes) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return (workInProgress.lanes = renderLanes), workInProgress; newProps = null !== newProps; rootContainerInstance = !1; @@ -5044,7 +4993,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderLanes ); } - if (newProps || rootContainerInstance) workInProgress.effectTag |= 4; + if (newProps || rootContainerInstance) workInProgress.flags |= 4; return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -5056,24 +5005,24 @@ function completeWork(current, workInProgress, renderLanes) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.effectTag & 64)) + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; @@ -5081,7 +5030,7 @@ function completeWork(current, workInProgress, renderLanes) { for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (renderLanes = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), @@ -5123,6 +5072,12 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432)); } else { if (!rootContainerInstance) @@ -5130,12 +5085,12 @@ function completeWork(current, workInProgress, renderLanes) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -5148,12 +5103,13 @@ function completeWork(current, workInProgress, renderLanes) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.lanes = renderLanes)); + (workInProgress.lanes = 33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5164,9 +5120,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -5181,15 +5135,15 @@ function completeWork(current, workInProgress, renderLanes) { ), current) : null; + case 22: case 23: - case 24: return ( popRenderLanes(), null !== current && (null !== current.memoizedState) !== (null !== workInProgress.memoizedState) && "unstable-defer-without-hiding" !== newProps.mode && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), null ); } @@ -5203,32 +5157,30 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); resetWorkInProgressVersions(); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null ); case 19: @@ -5237,8 +5189,8 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: case 23: - case 24: return popRenderLanes(), null; default: return null; @@ -5275,7 +5227,7 @@ function logCapturedError(boundary, errorInfo) { } var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; @@ -5286,7 +5238,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { return lane; } function createClassErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { @@ -5329,10 +5281,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5362,7 +5313,6 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 0: case 11: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5393,7 +5343,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { return; case 1: finishedRoot = finishedWork.stateNode; - finishedWork.effectTag & 4 && + finishedWork.flags & 4 && (null === current ? finishedRoot.componentDidMount() : ((create$81 = @@ -5441,8 +5391,8 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: case 23: - case 24: return; } throw Error( @@ -5488,7 +5438,7 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) { } else { if (6 === node.tag) throw Error("Not yet implemented."); if ( - ((23 !== node.tag && 24 !== node.tag) || + ((22 !== node.tag && 23 !== node.tag) || null === node.memoizedState || node === finishedWork) && null !== node.child @@ -5517,7 +5467,6 @@ function commitUnmount(finishedRoot, current) { case 11: case 14: case 15: - case 22: finishedRoot = current.updateQueue; if ( null !== finishedRoot && @@ -5606,7 +5555,7 @@ function commitPlacement(finishedWork) { "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." ); } - parentFiber.effectTag & 16 && (parentFiber.effectTag &= -17); + parentFiber.flags & 16 && (parentFiber.flags &= -17); a: b: for (parentFiber = finishedWork; ; ) { for (; null === parentFiber.sibling; ) { if (null === parentFiber.return || isHostParent(parentFiber.return)) { @@ -5621,13 +5570,13 @@ function commitPlacement(finishedWork) { 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { - if (parentFiber.effectTag & 2) continue b; + if (parentFiber.flags & 2) continue b; if (null === parentFiber.child || 4 === parentFiber.tag) continue b; else (parentFiber.child.return = parentFiber), (parentFiber = parentFiber.child); } - if (!(parentFiber.effectTag & 2)) { + if (!(parentFiber.flags & 2)) { parentFiber = parentFiber.stateNode; break a; } @@ -5836,7 +5785,6 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: var updateQueue = finishedWork.updateQueue; updateQueue = null !== updateQueue ? updateQueue.lastEffect : null; if (null !== updateQueue) { @@ -5902,8 +5850,8 @@ function commitWork(current, finishedWork) { return; case 17: return; + case 22: case 23: - case 24: hideOrUnhideAllChildren( finishedWork, null !== finishedWork.memoizedState @@ -5947,14 +5895,13 @@ var ceil = Math.ceil, subtreeRenderLanesCursor = createCursor(0), workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestSuspenseTimeout = -1, - workInProgressRootCanSuspendUsingConfig = null, workInProgressRootIncludedLanes = 0, workInProgressRootSkippedLanes = 0, workInProgressRootUpdatedLanes = 0, workInProgressRootPingedLanes = 0, mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5979,46 +5926,33 @@ function requestEventTime() { ? currentEventTime : (currentEventTime = now()); } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; if (0 === (fiber & 2)) return 1; if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; 0 === currentEventWipLanes && (currentEventWipLanes = workInProgressRootIncludedLanes); - if (null !== suspenseConfig) { - suspenseConfig = suspenseConfig.timeoutMs; - fiber = void 0 === suspenseConfig || 1e4 > (suspenseConfig | 0) ? 8 : 6; + if (0 !== ReactCurrentBatchConfig.transition) { 0 !== currentEventPendingLanes && (currentEventPendingLanes = null !== mostRecentlyUpdatedRoot ? mostRecentlyUpdatedRoot.pendingLanes : 0); - suspenseConfig = currentEventWipLanes; - var pendingLanes = currentEventPendingLanes; - if (8 === fiber) - (fiber = pickArbitraryLane(122880 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(122880 & ~suspenseConfig)), - 0 === fiber && (fiber = 8192)), - (suspenseConfig = fiber); - else if (6 === fiber) - (fiber = pickArbitraryLane(3932160 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(3932160 & ~suspenseConfig)), - 0 === fiber && (fiber = 262144)), - (suspenseConfig = fiber); - else - throw Error( - "Invalid transition priority: " + fiber + ". This is a bug in React." - ); - return suspenseConfig; + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; } - suspenseConfig = getCurrentPriorityLevel(); - 0 !== (executionContext & 4) && 98 === suspenseConfig - ? (suspenseConfig = findUpdateLane(14, currentEventWipLanes)) - : ((suspenseConfig = schedulerPriorityToLanePriority(suspenseConfig)), - (suspenseConfig = findUpdateLane(suspenseConfig, currentEventWipLanes))); - return suspenseConfig; + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; } function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) @@ -6039,7 +5973,9 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) ? performSyncWorkOnRoot(fiber) : (ensureRootIsScheduled(fiber, eventTime), - 0 === executionContext && flushSyncCallbackQueue()) + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) : (0 === (executionContext & 4) || (98 !== priorityLevel && 99 !== priorityLevel) || (null === rootsWithPendingDiscreteUpdates @@ -6080,8 +6016,8 @@ function ensureRootIsScheduled(root, currentTime) { getHighestPriorityLanes(lane); var priority = return_highestLanePriority; expirationTimes[index$7] = - 12 <= priority - ? expirationTime + 1e3 + 10 <= priority + ? expirationTime + 250 : 6 <= priority ? expirationTime + 5e3 : -1; @@ -6106,7 +6042,7 @@ function ensureRootIsScheduled(root, currentTime) { existingCallbackNode !== fakeCallbackNode && Scheduler_cancelCallback(existingCallbackNode); } - 17 === currentTime + 15 === currentTime ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), null === syncQueue ? ((syncQueue = [existingCallbackNode]), @@ -6116,7 +6052,7 @@ function ensureRootIsScheduled(root, currentTime) { ))) : syncQueue.push(existingCallbackNode), (existingCallbackNode = fakeCallbackNode)) - : 16 === currentTime + : 14 === currentTime ? (existingCallbackNode = scheduleCallback( 99, performSyncWorkOnRoot.bind(null, root) @@ -6130,7 +6066,7 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { currentEventTime = -1; currentEventPendingLanes = currentEventWipLanes = 0; if (0 !== (executionContext & 48)) @@ -6143,19 +6079,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - if (didTimeout) - return ( - (root.expiredLanes |= lanes & root.pendingLanes), - ensureRootIsScheduled(root, now()), - null - ); - didTimeout = lanes; + var exitStatus = lanes; var prevExecutionContext = executionContext; executionContext |= 16; var prevDispatcher = pushDispatcher(); - (workInProgressRoot === root && - workInProgressRootRenderLanes === didTimeout) || - prepareFreshStack(root, didTimeout); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== exitStatus + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, exitStatus); do try { workLoopConcurrent(); @@ -6168,19 +6101,19 @@ function performConcurrentWorkOnRoot(root, didTimeout) { ReactCurrentDispatcher$2.current = prevDispatcher; executionContext = prevExecutionContext; null !== workInProgress - ? (didTimeout = 0) + ? (exitStatus = 0) : ((workInProgressRoot = null), (workInProgressRootRenderLanes = 0), - (didTimeout = workInProgressRootExitStatus)); + (exitStatus = workInProgressRootExitStatus)); if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) prepareFreshStack(root, 0); - else if (0 !== didTimeout) { - 2 === didTimeout && + else if (0 !== exitStatus) { + 2 === exitStatus && ((executionContext |= 64), root.hydrate && (root.hydrate = !1), (lanes = getLanesToRetrySynchronouslyOnError(root)), - 0 !== lanes && (didTimeout = renderRootSync(root, lanes))); - if (1 === didTimeout) + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), markRootSuspended$1(root, lanes), @@ -6188,7 +6121,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); @@ -6199,8 +6132,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ( (lanes & 62914560) === lanes && - ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; prevExecutionContext = root.suspendedLanes; @@ -6211,7 +6144,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - didTimeout + exitStatus ); break; } @@ -6219,33 +6152,31 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; case 4: markRootSuspended$1(root, lanes); - if (0 !== getNextLanes(root, 0)) break; - didTimeout = root.suspendedLanes; - if ((didTimeout & lanes) !== lanes) { - requestEventTime(); - root.pingedLanes |= root.suspendedLanes & didTimeout; - break; + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevExecutionContext = -1; 0 < lanes; ) { + var index$6 = 31 - clz32(lanes); + prevDispatcher = 1 << index$6; + index$6 = exitStatus[index$6]; + index$6 > prevExecutionContext && (prevExecutionContext = index$6); + lanes &= ~prevDispatcher; } - lanes = getMostRecentEventTime(root, lanes); - -1 !== workInProgressRootLatestSuspenseTimeout - ? (lanes = workInProgressRootLatestSuspenseTimeout - now()) - : -1 === lanes - ? (lanes = 0) - : ((lanes = now() - lanes), - (lanes = - (120 > lanes - ? 120 - : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes)); + lanes = prevExecutionContext; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), @@ -6256,30 +6187,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { commitRoot(root); break; case 5: - prevDispatcher = getMostRecentEventTime(root, lanes); - if ( - -1 !== prevDispatcher && - null !== workInProgressRootCanSuspendUsingConfig && - ((didTimeout = - workInProgressRootCanSuspendUsingConfig.busyMinDurationMs | 0), - 0 >= didTimeout - ? (didTimeout = 0) - : ((prevExecutionContext = - workInProgressRootCanSuspendUsingConfig.busyDelayMs | 0), - (prevDispatcher = now() - prevDispatcher), - (didTimeout = - prevDispatcher <= prevExecutionContext - ? 0 - : prevExecutionContext + didTimeout - prevDispatcher)), - 10 < didTimeout) - ) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - didTimeout - ); - break; - } commitRoot(root); break; default: @@ -6297,9 +6204,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$12 = 31 - clz32(suspendedLanes), - lane = 1 << index$12; - root[index$12] = -1; + var index$11 = 31 - clz32(suspendedLanes), + lane = 1 << index$11; + root[index$11] = -1; suspendedLanes &= ~lane; } } @@ -6382,8 +6289,8 @@ function prepareFreshStack(root, lanes) { case 10: popProvider(interruptedWork); break; + case 22: case 23: - case 24: popRenderLanes(); } timeoutHandle = timeoutHandle.return; @@ -6393,8 +6300,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = -1; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; } function handleError(root$jscomp$0, thrownValue) { @@ -6431,7 +6336,7 @@ function handleError(root$jscomp$0, thrownValue) { sourceFiber = erroredWork, value = thrownValue; thrownValue = workInProgressRootRenderLanes; - sourceFiber.effectTag |= 2048; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && @@ -6477,13 +6382,13 @@ function handleError(root$jscomp$0, thrownValue) { workInProgress$76.updateQueue = updateQueue; } else wakeables.add(wakeable); if (0 === (workInProgress$76.mode & 2)) { - workInProgress$76.effectTag |= 64; - sourceFiber.effectTag |= 16384; - sourceFiber.effectTag &= -2981; + workInProgress$76.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(-1, 1, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } @@ -6510,7 +6415,7 @@ function handleError(root$jscomp$0, thrownValue) { ); wakeable.then(ping, ping); } - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; workInProgress$76.lanes = thrownValue; break a; } @@ -6529,7 +6434,7 @@ function handleError(root$jscomp$0, thrownValue) { switch (workInProgress$76.tag) { case 3: root = value; - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; thrownValue &= -thrownValue; workInProgress$76.lanes |= thrownValue; var update$77 = createRootErrorUpdate( @@ -6544,14 +6449,14 @@ function handleError(root$jscomp$0, thrownValue) { var ctor = workInProgress$76.type, instance = workInProgress$76.stateNode; if ( - 0 === (workInProgress$76.effectTag & 64) && + 0 === (workInProgress$76.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - workInProgress$76.effectTag |= 4096; + workInProgress$76.flags |= 8192; thrownValue &= -thrownValue; workInProgress$76.lanes |= thrownValue; var update$80 = createClassErrorUpdate( @@ -6582,13 +6487,6 @@ function pushDispatcher() { ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - null !== suspenseConfig && - ((eventTime += suspenseConfig.timeoutMs | 0 || 5e3), - eventTime > workInProgressRootLatestSuspenseTimeout && - ((workInProgressRootLatestSuspenseTimeout = eventTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig))); -} function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 16; @@ -6632,7 +6530,7 @@ function completeUnitOfWork(unitOfWork) { do { var current = completedWork.alternate; unitOfWork = completedWork.return; - if (0 === (completedWork.effectTag & 2048)) { + if (0 === (completedWork.flags & 4096)) { current = completeWork(current, completedWork, subtreeRenderLanes); if (null !== current) { workInProgress = current; @@ -6640,7 +6538,7 @@ function completeUnitOfWork(unitOfWork) { } current = completedWork; if ( - (24 !== current.tag && 23 !== current.tag) || + (23 !== current.tag && 22 !== current.tag) || null === current.memoizedState || 0 !== (subtreeRenderLanes & 1073741824) || 0 === (current.mode & 4) @@ -6651,14 +6549,14 @@ function completeUnitOfWork(unitOfWork) { current.childLanes = newChildLanes; } null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && (unitOfWork.firstEffect = completedWork.firstEffect), null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), (unitOfWork.lastEffect = completedWork.lastEffect)), - 1 < completedWork.effectTag && + 1 < completedWork.flags && (null !== unitOfWork.lastEffect ? (unitOfWork.lastEffect.nextEffect = completedWork) : (unitOfWork.firstEffect = completedWork), @@ -6666,13 +6564,13 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(completedWork); if (null !== current) { - current.effectTag &= 2047; + current.flags &= 4095; workInProgress = current; return; } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } completedWork = completedWork.sibling; if (null !== completedWork) { @@ -6717,11 +6615,11 @@ function commitRootImpl(root, renderPriorityLevel) { 0 < noLongerPendingLanes; ) { - var index$13 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$13; - remainingLanes$jscomp$0[index$13] = 0; - eventTimes[index$13] = -1; - expirationTimes[index$13] = -1; + var index$12 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$12; + remainingLanes$jscomp$0[index$12] = 0; + eventTimes[index$12] = -1; + expirationTimes[index$12] = -1; noLongerPendingLanes &= ~lane; } null !== rootsWithPendingDiscreteUpdates && @@ -6731,7 +6629,7 @@ function commitRootImpl(root, renderPriorityLevel) { root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - 1 < finishedWork.effectTag + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), (remainingLanes = finishedWork.firstEffect)) @@ -6757,8 +6655,8 @@ function commitRootImpl(root, renderPriorityLevel) { do try { for (eventTimes = root; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6768,21 +6666,21 @@ function commitRootImpl(root, renderPriorityLevel) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: @@ -6797,9 +6695,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$93) { + } catch (error$88) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$93); + captureCommitPhaseError(nextEffect, error$88); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6807,11 +6705,11 @@ function commitRootImpl(root, renderPriorityLevel) { nextEffect = remainingLanes; do try { - for (effectTag = root; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6830,9 +6728,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$94) { + } catch (error$89) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$94); + captureCommitPhaseError(nextEffect, error$89); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6848,10 +6746,10 @@ function commitRootImpl(root, renderPriorityLevel) { for (nextEffect = remainingLanes; null !== nextEffect; ) (renderPriorityLevel = nextEffect.nextEffect), (nextEffect.nextEffect = null), - nextEffect.effectTag & 8 && - ((effectTag$jscomp$0 = nextEffect), - (effectTag$jscomp$0.sibling = null), - (effectTag$jscomp$0.stateNode = null)), + nextEffect.flags & 8 && + ((flags$jscomp$0 = nextEffect), + (flags$jscomp$0.sibling = null), + (flags$jscomp$0.stateNode = null)), (nextEffect = renderPriorityLevel); remainingLanes = root.pendingLanes; 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); @@ -6867,7 +6765,7 @@ function commitRootImpl(root, renderPriorityLevel) { rendererID, finishedWork, void 0, - 64 === (finishedWork.current.effectTag & 64) + 64 === (finishedWork.current.flags & 64) ); } catch (err) {} ensureRootIsScheduled(root, now()); @@ -6885,17 +6783,16 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; shouldFireAfterActiveInstanceBlur || null === focusedInstanceHandle || - (0 !== (nextEffect.effectTag & 8) + (0 !== (nextEffect.flags & 8) ? doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0) : 13 === nextEffect.tag && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0)); - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(current, nextEffect); - 0 === (effectTag & 512) || + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6912,7 +6809,6 @@ function flushPassiveEffects() { ? 97 : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = 90; - schedulerPriorityToLanePriority(priorityLevel); return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } return !1; @@ -6946,10 +6842,10 @@ function flushPassiveEffectsImpl() { var unmountEffects = pendingPassiveHookEffectsUnmount; pendingPassiveHookEffectsUnmount = []; for (var i = 0; i < unmountEffects.length; i += 2) { - var effect$99 = unmountEffects[i], + var effect$94 = unmountEffects[i], fiber = unmountEffects[i + 1], - destroy = effect$99.destroy; - effect$99.destroy = void 0; + destroy = effect$94.destroy; + effect$94.destroy = void 0; if ("function" === typeof destroy) try { destroy(); @@ -6961,22 +6857,22 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsMount; pendingPassiveHookEffectsMount = []; for (i = 0; i < unmountEffects.length; i += 2) { - effect$99 = unmountEffects[i]; + effect$94 = unmountEffects[i]; fiber = unmountEffects[i + 1]; try { - var create$103 = effect$99.create; - effect$99.destroy = create$103(); - } catch (error$104) { + var create$98 = effect$94.create; + effect$94.destroy = create$98(); + } catch (error$99) { if (null === fiber) throw Error("Should be working on an effect."); - captureCommitPhaseError(fiber, error$104); + captureCommitPhaseError(fiber, error$99); } } - for (create$103 = root.current.firstEffect; null !== create$103; ) - (root = create$103.nextEffect), - (create$103.nextEffect = null), - create$103.effectTag & 8 && - ((create$103.sibling = null), (create$103.stateNode = null)), - (create$103 = root); + for (create$98 = root.current.firstEffect; null !== create$98; ) + (root = create$98.nextEffect), + (create$98.nextEffect = null), + create$98.flags & 8 && + ((create$98.sibling = null), (create$98.stateNode = null)), + (create$98 = root); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; @@ -7008,13 +6904,21 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1); - enqueueUpdate(fiber, sourceFiber); - sourceFiber = requestEventTime(); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); fiber = markUpdateLaneFromFiberToRoot(fiber, 1); - null !== fiber && - (markRootUpdated(fiber, 1, sourceFiber), - ensureRootIsScheduled(fiber, sourceFiber)); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } @@ -7067,7 +6971,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ) didReceiveUpdate = !0; else if (0 !== (renderLanes & updateLanes)) - didReceiveUpdate = 0 !== (current.effectTag & 16384) ? !0 : !1; + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { didReceiveUpdate = !1; switch (workInProgress.tag) { @@ -7113,14 +7017,14 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 19: updateLanes = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.effectTag & 64)) { + if (0 !== (current.flags & 64)) { if (updateLanes) return updateSuspenseListComponent( current, workInProgress, renderLanes ); - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; } context = workInProgress.memoizedState; null !== context && @@ -7130,8 +7034,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { push(suspenseStackCursor, suspenseStackCursor.current); if (updateLanes) break; else return null; + case 22: case 23: - case 24: return ( (workInProgress.lanes = 0), updateOffscreenComponent(current, workInProgress, renderLanes) @@ -7147,7 +7051,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); prepareToReadContext(workInProgress, renderLanes); @@ -7159,7 +7063,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context, renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -7209,7 +7113,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; hasContext = context._init; context = hasContext(context._payload); @@ -7452,8 +7356,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { 1 === context$jscomp$0.tag && ((dependency = createUpdate( -1, - renderLanes & -renderLanes, - null + renderLanes & -renderLanes )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); @@ -7515,7 +7418,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), (updateLanes = updateLanes(context)), - (workInProgress.effectTag |= 1), + (workInProgress.flags |= 1), reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); @@ -7556,7 +7459,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) @@ -7575,9 +7478,9 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 19: return updateSuspenseListComponent(current, workInProgress, renderLanes); - case 23: + case 22: return updateOffscreenComponent(current, workInProgress, renderLanes); - case 24: + case 23: return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( @@ -7595,7 +7498,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; this.childLanes = this.lanes = 0; this.alternate = null; @@ -7633,7 +7536,7 @@ function createWorkInProgress(current, pendingProps) { (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), (workInProgress.type = current.type), - (workInProgress.effectTag = 0), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null)); @@ -7704,7 +7607,7 @@ function createFiberFromTypeAndProps( return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: return ( - (type = createFiber(24, pendingProps, key, mode)), + (type = createFiber(23, pendingProps, key, mode)), (type.elementType = REACT_LEGACY_HIDDEN_TYPE), (type.lanes = lanes), type @@ -7728,9 +7631,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7750,7 +7650,7 @@ function createFiberFromFragment(elements, mode, lanes, key) { return elements; } function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps = createFiber(22, pendingProps, key, mode); pendingProps.elementType = REACT_OFFSCREEN_TYPE; pendingProps.lanes = lanes; return pendingProps; @@ -7784,10 +7684,10 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.hydrate = hydrate; this.callbackNode = null; this.callbackPriority = 0; - this.eventTimes = Array(31).fill(0); - this.expirationTimes = Array(31).fill(-1); + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; - this.entanglements = Array(31).fill(0); + this.entanglements = createLaneMap(0); } function createPortal(children, containerInfo, implementation) { var key = @@ -7816,8 +7716,7 @@ function findHostInstance(component) { function updateContainer(element, container, parentComponent, callback) { var current = container.current, eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(current, suspenseConfig); + lane = requestUpdateLane(current); a: if (parentComponent) { parentComponent = parentComponent._reactInternals; b: { @@ -7865,7 +7764,7 @@ function updateContainer(element, container, parentComponent, callback) { null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(eventTime, lane, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); @@ -7903,14 +7802,16 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - 0 === executionContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; var roots = new Map(), - devToolsConfig$jscomp$inline_934 = { + devToolsConfig$jscomp$inline_908 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "17.0.0-alpha.0", + version: "17.0.1-454c2211c", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -7925,13 +7826,17 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1135 = { - bundleType: devToolsConfig$jscomp$inline_934.bundleType, - version: devToolsConfig$jscomp$inline_934.version, - rendererPackageName: devToolsConfig$jscomp$inline_934.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_934.rendererConfig, +var internals$jscomp$inline_1115 = { + bundleType: devToolsConfig$jscomp$inline_908.bundleType, + version: devToolsConfig$jscomp$inline_908.version, + rendererPackageName: devToolsConfig$jscomp$inline_908.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_908.rendererConfig, overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, @@ -7940,7 +7845,7 @@ var internals$jscomp$inline_1135 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_934.findFiberByHostInstance || + devToolsConfig$jscomp$inline_908.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, @@ -7949,16 +7854,16 @@ var internals$jscomp$inline_1135 = { getCurrentFiber: null }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1136 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1116 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1136.isDisabled && - hook$jscomp$inline_1136.supportsFiber + !hook$jscomp$inline_1116.isDisabled && + hook$jscomp$inline_1116.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1136.inject( - internals$jscomp$inline_1135 + (rendererID = hook$jscomp$inline_1116.inject( + internals$jscomp$inline_1115 )), - (injectedHook = hook$jscomp$inline_1136); + (injectedHook = hook$jscomp$inline_1116); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -8025,6 +7930,18 @@ exports.render = function(element, containerTag, callback) { else element = null; return element; }; +exports.sendAccessibilityEvent = function(handle, eventType) { + null != handle._nativeTag && + (handle._internalInstanceHandle + ? nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ) + : ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + )); +}; exports.unmountComponentAtNode = unmountComponentAtNode; exports.unmountComponentAtNodeAndRemoveContainer = function(containerTag) { unmountComponentAtNode(containerTag); diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js index 31b089c41bfee8..f5ba497464b7eb 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js @@ -16,16 +16,6 @@ require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore"); var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface"), React = require("react"), Scheduler = require("scheduler"); -function getParent(inst) { - do inst = inst.return; - while (inst && 5 !== inst.tag); - return inst ? inst : null; -} -function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); - for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); -} function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -96,109 +86,6 @@ function executeDirectDispatch(event) { event._dispatchInstances = null; return dispatchListener; } -function getListener(inst, registrationName) { - var listener = inst.stateNode; - if (!listener) return null; - var props = getFiberCurrentPropsFromNode(listener); - if (!props) return null; - listener = props[registrationName]; - a: switch (registrationName) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - (props = !props.disabled) || - ((inst = inst.type), - (props = !( - "button" === inst || - "input" === inst || - "select" === inst || - "textarea" === inst - ))); - inst = !props; - break a; - default: - inst = !1; - } - if (inst) return null; - if (listener && "function" !== typeof listener) - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - return listener; -} -function accumulateInto(current, next) { - if (null == next) - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - if (null == current) return next; - if (Array.isArray(current)) { - if (Array.isArray(next)) return current.push.apply(current, next), current; - current.push(next); - return current; - } - return Array.isArray(next) ? [current].concat(next) : [current, next]; -} -function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); -} -function accumulateDirectionalDispatches(inst, phase, event) { - if ( - (phase = getListener( - inst, - event.dispatchConfig.phasedRegistrationNames[phase] - )) - ) - (event._dispatchListeners = accumulateInto( - event._dispatchListeners, - phase - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - )); -} -function accumulateTwoPhaseDispatchesSingle(event) { - event && - event.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); -} -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - targetInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); - } -} -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - var inst = event._targetInst; - if (inst && event && event.dispatchConfig.registrationName) { - var listener = getListener(inst, event.dispatchConfig.registrationName); - listener && - ((event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); - } - } -} function functionThatReturnsTrue() { return !0; } @@ -214,6 +101,7 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchInstances = this._dispatchListeners = null; dispatchConfig = this.constructor.Interface; for (var propName in dispatchConfig) dispatchConfig.hasOwnProperty(propName) && @@ -293,7 +181,12 @@ SyntheticEvent.extend = function(Interface) { return Class; }; addEventPoolingTo(SyntheticEvent); -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { if (this.eventPool.length) { var instance = this.eventPool.pop(); this.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); @@ -310,8 +203,8 @@ function releasePooledEvent(event) { 10 > this.eventPool.length && this.eventPool.push(event); } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ @@ -439,6 +332,22 @@ function accumulate(current, next) { ? [current].concat(next) : [current, next]; } +function accumulateInto(current, next) { + if (null == next) + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + if (null == current) return next; + if (Array.isArray(current)) { + if (Array.isArray(next)) return current.push.apply(current, next), current; + current.push(next); + return current; + } + return Array.isArray(next) ? [current].concat(next) : [current, next]; +} +function forEachAccumulated(arr, cb, scope) { + Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); +} var responderInst = null, trackedTouchCount = 0; function changeResponder(nextResponderInst, blockHostResponder) { @@ -452,65 +361,132 @@ function changeResponder(nextResponderInst, blockHostResponder) { ); } var eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: ["topScroll"] - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: ["topSelectionChange"] - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies - }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies + dependencies: startDependencies + }, + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] + dependencies: ["topScroll"] + }, + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" }, - responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] + dependencies: ["topSelectionChange"] + }, + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } + dependencies: moveDependencies + }, + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies }, - ResponderEventPlugin = { + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies + }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, + responderReject: { registrationName: "onResponderReject", dependencies: [] }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } +}; +function getParent(inst) { + do inst = inst.return; + while (inst && 5 !== inst.tag); + return inst ? inst : null; +} +function traverseTwoPhase(inst, fn, arg) { + for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); +} +function getListener(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +function accumulateDirectionalDispatches(inst, phase, event) { + if ( + (phase = getListener( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + targetInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); + } +} +function accumulateTwoPhaseDispatchesSingle(event) { + event && + event.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); +} +var ResponderEventPlugin = { _getResponder: function() { return responderInst; }, @@ -571,68 +547,70 @@ var eventTypes = { JSCompiler_temp = null; } else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp === responderInst; - JSCompiler_temp = ResponderSyntheticEvent.getPooled( + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( shouldSetEventType, - JSCompiler_temp, + targetInst, nativeEvent, nativeEventTarget ); - JSCompiler_temp.touchHistory = ResponderTouchHistoryStore.touchHistory; - targetInst + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp ? forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingleSkipTarget ) : forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingle ); b: { - shouldSetEventType = JSCompiler_temp._dispatchListeners; - targetInst = JSCompiler_temp._dispatchInstances; - if (Array.isArray(shouldSetEventType)) + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (Array.isArray(JSCompiler_temp)) for ( depthA = 0; - depthA < shouldSetEventType.length && - !JSCompiler_temp.isPropagationStopped(); + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); depthA++ ) { if ( - shouldSetEventType[depthA](JSCompiler_temp, targetInst[depthA]) + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - shouldSetEventType = targetInst[depthA]; + JSCompiler_temp = targetInst[depthA]; break b; } } else if ( - shouldSetEventType && - shouldSetEventType(JSCompiler_temp, targetInst) + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) ) { - shouldSetEventType = targetInst; + JSCompiler_temp = targetInst; break b; } - shouldSetEventType = null; + JSCompiler_temp = null; } - JSCompiler_temp._dispatchInstances = null; - JSCompiler_temp._dispatchListeners = null; - JSCompiler_temp.isPersistent() || - JSCompiler_temp.constructor.release(JSCompiler_temp); - if (shouldSetEventType && shouldSetEventType !== responderInst) + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) if ( - ((JSCompiler_temp = ResponderSyntheticEvent.getPooled( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderGrant, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), - (JSCompiler_temp.touchHistory = + (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateDirectDispatchesSingle ), - (targetInst = !0 === executeDirectDispatch(JSCompiler_temp)), + (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) ) if ( @@ -659,13 +637,13 @@ var eventTypes = { forEachAccumulated(depthA, accumulateDirectDispatchesSingle); var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - [JSCompiler_temp, depthA] + [shouldSetEventType, depthA] ); - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); } else (shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderReject, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), @@ -682,9 +660,9 @@ var eventTypes = { else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - JSCompiler_temp + shouldSetEventType )), - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); else JSCompiler_temp$jscomp$0 = null; } else JSCompiler_temp$jscomp$0 = null; shouldSetEventType = responderInst && isStartish(topLevelType); @@ -812,7 +790,6 @@ function recomputePluginOrdering() { for (var eventName in pluginIndex) { var JSCompiler_inline_result = void 0; var dispatchConfig = pluginIndex[eventName], - pluginModule$jscomp$0 = pluginModule, eventName$jscomp$0 = eventName; if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( @@ -829,7 +806,7 @@ function recomputePluginOrdering() { ) && publishRegistrationName( phasedRegistrationNames[JSCompiler_inline_result], - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ); JSCompiler_inline_result = !0; @@ -837,7 +814,7 @@ function recomputePluginOrdering() { dispatchConfig.registrationName ? (publishRegistrationName( dispatchConfig.registrationName, - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ), (JSCompiler_inline_result = !0)) @@ -865,13 +842,75 @@ function publishRegistrationName(registrationName, pluginModule) { } var plugins = [], eventNameDispatchConfigs = {}, - registrationNameModules = {}, - customBubblingEventTypes = + registrationNameModules = {}; +function getListener$1(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; +function accumulateDirectionalDispatches$1(inst, phase, event) { + if ( + (phase = getListener$1( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + for (var inst = event._targetInst, path = []; inst; ) { + path.push(inst); + do inst = inst.return; + while (inst && 5 !== inst.tag); + inst = inst ? inst : null; + } + for (inst = path.length; 0 < inst--; ) + accumulateDirectionalDispatches$1(path[inst], "captured", event); + for (inst = 0; inst < path.length; inst++) + accumulateDirectionalDispatches$1(path[inst], "bubbled", event); + } +} +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener$1(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} if (eventPluginOrder) throw Error( "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React." @@ -881,7 +920,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_94 = { +var injectedNamesToPlugins$jscomp$inline_222 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -905,42 +944,45 @@ var injectedNamesToPlugins$jscomp$inline_94 = { nativeEventTarget ); if (bubbleDispatchConfig) - forEachAccumulated(topLevelType, accumulateTwoPhaseDispatchesSingle); + forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle); + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); else return null; return topLevelType; } } }, - isOrderingDirty$jscomp$inline_95 = !1, - pluginName$jscomp$inline_96; -for (pluginName$jscomp$inline_96 in injectedNamesToPlugins$jscomp$inline_94) + isOrderingDirty$jscomp$inline_223 = !1, + pluginName$jscomp$inline_224; +for (pluginName$jscomp$inline_224 in injectedNamesToPlugins$jscomp$inline_222) if ( - injectedNamesToPlugins$jscomp$inline_94.hasOwnProperty( - pluginName$jscomp$inline_96 + injectedNamesToPlugins$jscomp$inline_222.hasOwnProperty( + pluginName$jscomp$inline_224 ) ) { - var pluginModule$jscomp$inline_97 = - injectedNamesToPlugins$jscomp$inline_94[pluginName$jscomp$inline_96]; + var pluginModule$jscomp$inline_225 = + injectedNamesToPlugins$jscomp$inline_222[pluginName$jscomp$inline_224]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_96) || - namesToPlugins[pluginName$jscomp$inline_96] !== - pluginModule$jscomp$inline_97 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_224) || + namesToPlugins[pluginName$jscomp$inline_224] !== + pluginModule$jscomp$inline_225 ) { - if (namesToPlugins[pluginName$jscomp$inline_96]) + if (namesToPlugins[pluginName$jscomp$inline_224]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_96 + + pluginName$jscomp$inline_224 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_96 - ] = pluginModule$jscomp$inline_97; - isOrderingDirty$jscomp$inline_95 = !0; + pluginName$jscomp$inline_224 + ] = pluginModule$jscomp$inline_225; + isOrderingDirty$jscomp$inline_223 = !0; } } -isOrderingDirty$jscomp$inline_95 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_223 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -986,34 +1028,41 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { target = null; null != inst && (target = inst.stateNode); batchedUpdates(function() { - var events = target; - for (var events$jscomp$0 = null, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; + var JSCompiler_inline_result = target; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; possiblePlugin && (possiblePlugin = possiblePlugin.extractEvents( topLevelType, inst, nativeEvent, - events, - 1 + JSCompiler_inline_result )) && - (events$jscomp$0 = accumulateInto(events$jscomp$0, possiblePlugin)); + (events = accumulateInto(events, possiblePlugin)); } - events = events$jscomp$0; - null !== events && (eventQueue = accumulateInto(eventQueue, events)); - events = eventQueue; + JSCompiler_inline_result = events; + null !== JSCompiler_inline_result && + (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); + JSCompiler_inline_result = eventQueue; eventQueue = null; - if (events) { - forEachAccumulated(events, executeDispatchesAndReleaseTopLevel); + if (JSCompiler_inline_result) { + forEachAccumulated( + JSCompiler_inline_result, + executeDispatchesAndReleaseTopLevel + ); if (eventQueue) throw Error( "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." ); if (hasRethrowError) - throw ((events = rethrowError), + throw ((JSCompiler_inline_result = rethrowError), (hasRethrowError = !1), (rethrowError = null), - events); + JSCompiler_inline_result); } }); } @@ -1028,13 +1077,13 @@ ReactNativePrivateInterface.RCTEventEmitter.register({ ) { var JSCompiler_temp = []; for (var i = 0; i < changedIndices.length; i++) { - var index = changedIndices[i]; - JSCompiler_temp.push(touches[index]); - touches[index] = null; + var index$0 = changedIndices[i]; + JSCompiler_temp.push(touches[index$0]); + touches[index$0] = null; } for (i = changedIndices = 0; i < touches.length; i++) - (index = touches[i]), - null !== index && (touches[changedIndices++] = index); + (index$0 = touches[i]), + null !== index$0 && (touches[changedIndices++] = index$0); touches.length = changedIndices; } else for (JSCompiler_temp = [], i = 0; i < changedIndices.length; i++) @@ -1047,10 +1096,10 @@ ReactNativePrivateInterface.RCTEventEmitter.register({ i = JSCompiler_temp[changedIndices]; i.changedTouches = JSCompiler_temp; i.touches = touches; - index = null; + index$0 = null; var target = i.target; - null === target || void 0 === target || 1 > target || (index = target); - _receiveRootNodeIDEvent(index, eventTopLevelType, i); + null === target || void 0 === target || 1 > target || (index$0 = target); + _receiveRootNodeIDEvent(index$0, eventTopLevelType, i); } } }); @@ -1076,31 +1125,42 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler({ } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher") || - (ReactSharedInternals.ReactCurrentDispatcher = { current: null }); -ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig") || - (ReactSharedInternals.ReactCurrentBatchConfig = { suspense: null }); -var hasSymbol = "function" === typeof Symbol && Symbol.for, - REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, - REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, - REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, - REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, - REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, - REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, - REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 60111, - REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, - REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 60120, - REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115, - REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116, - REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121, - MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + REACT_ELEMENT_TYPE = 60103, + REACT_PORTAL_TYPE = 60106, + REACT_FRAGMENT_TYPE = 60107, + REACT_STRICT_MODE_TYPE = 60108, + REACT_PROFILER_TYPE = 60114, + REACT_PROVIDER_TYPE = 60109, + REACT_CONTEXT_TYPE = 60110, + REACT_FORWARD_REF_TYPE = 60112, + REACT_SUSPENSE_TYPE = 60113, + REACT_SUSPENSE_LIST_TYPE = 60120, + REACT_MEMO_TYPE = 60115, + REACT_LAZY_TYPE = 60116, + REACT_DEBUG_TRACING_MODE_TYPE = 60129, + REACT_OFFSCREEN_TYPE = 60130, + REACT_LEGACY_HIDDEN_TYPE = 60131; +if ("function" === typeof Symbol && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + symbolFor("react.scope"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} +var MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "object" !== typeof maybeIterable) return null; maybeIterable = @@ -1108,27 +1168,6 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } -function initializeLazyComponentType(lazyComponent) { - if (-1 === lazyComponent._status) { - var ctor = lazyComponent._result; - ctor || (ctor = lazyComponent._ctor); - ctor = ctor(); - lazyComponent._status = 0; - lazyComponent._result = ctor; - ctor.then( - function(moduleObject) { - 0 === lazyComponent._status && - ((moduleObject = moduleObject.default), - (lazyComponent._status = 1), - (lazyComponent._result = moduleObject)); - }, - function(error) { - 0 === lazyComponent._status && - ((lazyComponent._status = 2), (lazyComponent._result = error)); - } - ); - } -} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1162,11 +1201,12 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); case REACT_LAZY_TYPE: - if ((type = 1 === type._status ? type._result : null)) - return getComponentName(type); + innerType = type._payload; + type = type._init; + try { + return getComponentName(type(innerType)); + } catch (x) {} } return null; } @@ -1178,7 +1218,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1218,36 +1258,36 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { + for (var didFindChild = !1, child$1 = parentA.child; child$1; ) { + if (child$1 === a) { didFindChild = !0; a = parentA; b = parentB; break; } - if (_child === b) { + if (child$1 === b) { didFindChild = !0; b = parentA; a = parentB; break; } - _child = _child.sibling; + child$1 = child$1.sibling; } if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { + for (child$1 = parentB.child; child$1; ) { + if (child$1 === a) { didFindChild = !0; a = parentB; b = parentA; break; } - if (_child === b) { + if (child$1 === b) { didFindChild = !0; b = parentB; a = parentA; break; } - _child = _child.sibling; + child$1 = child$1.sibling; } if (!didFindChild) throw Error( @@ -1282,6 +1322,18 @@ function findCurrentHostFiber(parent) { } return null; } +function doesFiberContain(parentFiber, childFiber) { + for ( + var parentFiberAlternate = parentFiber.alternate; + null !== childFiber; + + ) { + if (childFiber === parentFiber || childFiber === parentFiberAlternate) + return !0; + childFiber = childFiber.return; + } + return !1; +} var emptyObject = {}, removedKeys = null, removedKeyCount = 0, @@ -1486,19 +1538,19 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ), (removedKeys = null)); } - for (var _propKey in prevProps) - void 0 === nextProps[_propKey] && - (!(attributeConfig = validAttributes[_propKey]) || - (updatePayload && void 0 !== updatePayload[_propKey]) || - ((prevProp = prevProps[_propKey]), + for (var propKey$3 in prevProps) + void 0 === nextProps[propKey$3] && + (!(attributeConfig = validAttributes[propKey$3]) || + (updatePayload && void 0 !== updatePayload[propKey$3]) || + ((prevProp = prevProps[propKey$3]), void 0 !== prevProp && ("object" !== typeof attributeConfig || "function" === typeof attributeConfig.diff || "function" === typeof attributeConfig.process - ? (((updatePayload || (updatePayload = {}))[_propKey] = null), + ? (((updatePayload || (updatePayload = {}))[propKey$3] = null), removedKeys || (removedKeys = {}), - removedKeys[_propKey] || - ((removedKeys[_propKey] = !0), removedKeyCount++)) + removedKeys[propKey$3] || + ((removedKeys[propKey$3] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( updatePayload, prevProp, @@ -1607,9 +1659,22 @@ function finalizeInitialChildren(parentInstance) { return !1; } var scheduleTimeout = setTimeout, - cancelTimeout = clearTimeout, - valueStack = [], + cancelTimeout = clearTimeout; +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; +} +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; +} +var valueStack = [], index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} function pop(cursor) { 0 > index || ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); @@ -1620,8 +1685,8 @@ function push(cursor, value) { cursor.current = value; } var emptyContextObject = {}, - contextStackCursor = { current: emptyContextObject }, - didPerformWorkStackCursor = { current: !1 }, + contextStackCursor = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyContextObject; function getMaskedContext(workInProgress, unmaskedContext) { var contextTypes = workInProgress.type.contextTypes; @@ -1670,7 +1735,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1701,11 +1766,204 @@ function invalidateContextProvider(workInProgress, type, didChange) { : pop(didPerformWorkStackCursor); push(didPerformWorkStackCursor, didChange); } +var rendererID = null, + injectedHook = null, + Scheduler_now = Scheduler.unstable_now; +Scheduler_now(); +var return_highestLanePriority = 8; +function getHighestPriorityLanes(lanes) { + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; + var inputDiscreteLanes = 24 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 12), inputDiscreteLanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 10), inputDiscreteLanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 8), inputDiscreteLanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 6), inputDiscreteLanes; + inputDiscreteLanes = 62914560 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 5), inputDiscreteLanes; + if (lanes & 67108864) return (return_highestLanePriority = 4), 67108864; + if (0 !== (lanes & 134217728)) + return (return_highestLanePriority = 3), 134217728; + inputDiscreteLanes = 805306368 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 2), inputDiscreteLanes; + if (0 !== (1073741824 & lanes)) + return (return_highestLanePriority = 1), 1073741824; + return_highestLanePriority = 8; + return lanes; +} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case 99: + return 15; + case 98: + return 10; + case 97: + case 96: + return 8; + case 95: + return 2; + default: + return 0; + } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case 15: + case 14: + return 99; + case 13: + case 12: + case 11: + case 10: + return 98; + case 9: + case 8: + case 7: + case 6: + case 4: + case 5: + return 97; + case 3: + case 2: + case 1: + return 95; + case 0: + return 90; + default: + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} +function getNextLanes(root, wipLanes) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return (return_highestLanePriority = 0); + var nextLanes = 0, + nextLanePriority = 0, + expiredLanes = root.expiredLanes, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes; + if (0 !== expiredLanes) + (nextLanes = expiredLanes), + (nextLanePriority = return_highestLanePriority = 15); + else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { + var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; + 0 !== nonIdleUnblockedLanes + ? ((nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)), + (nextLanePriority = return_highestLanePriority)) + : ((pingedLanes &= expiredLanes), + 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority))); + } else + (expiredLanes = pendingLanes & ~suspendedLanes), + 0 !== expiredLanes + ? ((nextLanes = getHighestPriorityLanes(expiredLanes)), + (nextLanePriority = return_highestLanePriority)) + : 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority)); + if (0 === nextLanes) return 0; + nextLanes = 31 - clz32(nextLanes); + nextLanes = pendingLanes & (((0 > nextLanes ? 0 : 1 << nextLanes) << 1) - 1); + if ( + 0 !== wipLanes && + wipLanes !== nextLanes && + 0 === (wipLanes & suspendedLanes) + ) { + getHighestPriorityLanes(wipLanes); + if (nextLanePriority <= return_highestLanePriority) return wipLanes; + return_highestLanePriority = nextLanePriority; + } + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (nextLanePriority = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~nextLanePriority); + return nextLanes; +} +function getLanesToRetrySynchronouslyOnError(root) { + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; +} +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case 15: + return 1; + case 14: + return 2; + case 12: + return ( + (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + ); + case 10: + return ( + (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority + ); + case 8: + return ( + (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), + 0 === lanePriority && + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), + 0 === lanePriority && (lanePriority = 512)), + lanePriority + ); + case 2: + return ( + (wipLanes = getHighestPriorityLane(805306368 & ~wipLanes)), + 0 === wipLanes && (wipLanes = 268435456), + wipLanes + ); + } + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); +} +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + var higherPriorityLanes = updateLane - 1; + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, + log = Math.log, + LN2 = Math.LN2; +function clz32Fallback(lanes) { + return 0 === lanes ? 32 : (31 - ((log(lanes) / LN2) | 0)) | 0; +} var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, + Scheduler_shouldYield = Scheduler.unstable_shouldYield, Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, + Scheduler_now$1 = Scheduler.unstable_now, Scheduler_getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel, Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, @@ -1714,18 +1972,17 @@ var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_LowPriority = Scheduler.unstable_LowPriority, Scheduler_IdlePriority = Scheduler.unstable_IdlePriority, fakeCallbackNode = {}, - shouldYield = Scheduler.unstable_shouldYield, requestPaint = void 0 !== Scheduler_requestPaint ? Scheduler_requestPaint : function() {}, syncQueue = null, immediateQueueCallbackNode = null, isFlushingSyncQueue = !1, - initialTimeMs = Scheduler_now(), + initialTimeMs$1 = Scheduler_now$1(), now = - 1e4 > initialTimeMs - ? Scheduler_now + 1e4 > initialTimeMs$1 + ? Scheduler_now$1 : function() { - return Scheduler_now() - initialTimeMs; + return Scheduler_now$1() - initialTimeMs$1; }; function getCurrentPriorityLevel() { switch (Scheduler_getCurrentPriorityLevel()) { @@ -1767,16 +2024,6 @@ function scheduleCallback(reactPriorityLevel, callback, options) { reactPriorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); return Scheduler_scheduleCallback(reactPriorityLevel, callback, options); } -function scheduleSyncCallback(callback) { - null === syncQueue - ? ((syncQueue = [callback]), - (immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ))) - : syncQueue.push(callback); - return fakeCallbackNode; -} function flushSyncCallbackQueue() { if (null !== immediateQueueCallbackNode) { var node = immediateQueueCallbackNode; @@ -1811,6 +2058,7 @@ function flushSyncCallbackQueueImpl() { } } } +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -1836,42 +2084,39 @@ function shallowEqual(objA, objB) { return !1; return !0; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } +} function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 3: - case 4: - case 6: - case 7: - case 10: - case 9: - var JSCompiler_inline_result = ""; - break a; - default: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource, - name = getComponentName(workInProgress.type); - JSCompiler_inline_result = null; - owner && (JSCompiler_inline_result = getComponentName(owner.type)); - owner = name; - name = ""; - source - ? (name = - " (at " + - source.fileName.replace(BEFORE_SLASH_RE, "") + - ":" + - source.lineNumber + - ")") - : JSCompiler_inline_result && - (name = " (created by " + JSCompiler_inline_result + ")"); - JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress.return; - } while (workInProgress); - return info; + try { + var info = ""; + do + (info += describeFiber(workInProgress)), + (workInProgress = workInProgress.return); + while (workInProgress); + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } } function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { @@ -1880,10 +2125,11 @@ function resolveDefaultProps(Component, baseProps) { for (var propName in Component) void 0 === baseProps[propName] && (baseProps[propName] = Component[propName]); + return baseProps; } return baseProps; } -var valueCursor = { current: null }, +var valueCursor = createCursor(null), currentlyRenderingFiber = null, lastContextDependency = null, lastContextWithAllBitsObserved = null; @@ -1895,31 +2141,29 @@ function popProvider(providerFiber) { pop(valueCursor); providerFiber.type._context._currentValue = currentValue; } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { +function scheduleWorkOnParentPath(parent, renderLanes) { for (; null !== parent; ) { var alternate = parent.alternate; - if (parent.childExpirationTime < renderExpirationTime) - (parent.childExpirationTime = renderExpirationTime), - null !== alternate && - alternate.childExpirationTime < renderExpirationTime && - (alternate.childExpirationTime = renderExpirationTime); - else if ( - null !== alternate && - alternate.childExpirationTime < renderExpirationTime - ) - alternate.childExpirationTime = renderExpirationTime; - else break; + if ((parent.childLanes & renderLanes) === renderLanes) + if ( + null === alternate || + (alternate.childLanes & renderLanes) === renderLanes + ) + break; + else alternate.childLanes |= renderLanes; + else + (parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes); parent = parent.return; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextWithAllBitsObserved = lastContextDependency = null; workInProgress = workInProgress.dependencies; null !== workInProgress && null !== workInProgress.firstContext && - (workInProgress.expirationTime >= renderExpirationTime && - (didReceiveUpdate = !0), + (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), (workInProgress.firstContext = null)); } function readContext(context, observedBits) { @@ -1938,7 +2182,7 @@ function readContext(context, observedBits) { ); lastContextDependency = observedBits; currentlyRenderingFiber.dependencies = { - expirationTime: 0, + lanes: 0, firstContext: observedBits, responders: null }; @@ -1950,7 +2194,8 @@ var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, effects: null }; @@ -1960,21 +2205,21 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue === current && (workInProgress.updateQueue = { baseState: current.baseState, - baseQueue: current.baseQueue, + firstBaseUpdate: current.firstBaseUpdate, + lastBaseUpdate: current.lastBaseUpdate, shared: current.shared, effects: current.effects }); } -function createUpdate(expirationTime, suspenseConfig) { - expirationTime = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, +function createUpdate(eventTime, lane) { + return { + eventTime: eventTime, + lane: lane, tag: 0, payload: null, callback: null, next: null }; - return (expirationTime.next = expirationTime); } function enqueueUpdate(fiber, update) { fiber = fiber.updateQueue; @@ -1987,132 +2232,177 @@ function enqueueUpdate(fiber, update) { fiber.pending = update; } } -function enqueueCapturedUpdate(workInProgress, update) { - var current = workInProgress.alternate; - null !== current && cloneUpdateQueue(current, workInProgress); - workInProgress = workInProgress.updateQueue; - current = workInProgress.baseQueue; - null === current - ? ((workInProgress.baseQueue = update.next = update), - (update.next = update)) - : ((update.next = current.next), (current.next = update)); +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + var queue = workInProgress.updateQueue, + current = workInProgress.alternate; + if ( + null !== current && + ((current = current.updateQueue), queue === current) + ) { + var newFirst = null, + newLast = null; + queue = queue.firstBaseUpdate; + if (null !== queue) { + do { + var clone = { + eventTime: queue.eventTime, + lane: queue.lane, + tag: queue.tag, + payload: queue.payload, + callback: queue.callback, + next: null + }; + null === newLast + ? (newFirst = newLast = clone) + : (newLast = newLast.next = clone); + queue = queue.next; + } while (null !== queue); + null === newLast + ? (newFirst = newLast = capturedUpdate) + : (newLast = newLast.next = capturedUpdate); + } else newFirst = newLast = capturedUpdate; + queue = { + baseState: current.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: current.shared, + effects: current.effects + }; + workInProgress.updateQueue = queue; + return; + } + workInProgress = queue.lastBaseUpdate; + null === workInProgress + ? (queue.firstBaseUpdate = capturedUpdate) + : (workInProgress.next = capturedUpdate); + queue.lastBaseUpdate = capturedUpdate; } function processUpdateQueue( workInProgress$jscomp$0, props, instance, - renderExpirationTime + renderLanes ) { var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; - var baseQueue = queue.baseQueue, + var firstBaseUpdate = queue.firstBaseUpdate, + lastBaseUpdate = queue.lastBaseUpdate, pendingQueue = queue.shared.pending; if (null !== pendingQueue) { - if (null !== baseQueue) { - var baseFirst = baseQueue.next; - baseQueue.next = pendingQueue.next; - pendingQueue.next = baseFirst; - } - baseQueue = pendingQueue; queue.shared.pending = null; - baseFirst = workInProgress$jscomp$0.alternate; - null !== baseFirst && - ((baseFirst = baseFirst.updateQueue), - null !== baseFirst && (baseFirst.baseQueue = pendingQueue)); + var lastPendingUpdate = pendingQueue, + firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; + null === lastBaseUpdate + ? (firstBaseUpdate = firstPendingUpdate) + : (lastBaseUpdate.next = firstPendingUpdate); + lastBaseUpdate = lastPendingUpdate; + var current = workInProgress$jscomp$0.alternate; + if (null !== current) { + current = current.updateQueue; + var currentLastBaseUpdate = current.lastBaseUpdate; + currentLastBaseUpdate !== lastBaseUpdate && + (null === currentLastBaseUpdate + ? (current.firstBaseUpdate = firstPendingUpdate) + : (currentLastBaseUpdate.next = firstPendingUpdate), + (current.lastBaseUpdate = lastPendingUpdate)); + } } - if (null !== baseQueue) { - baseFirst = baseQueue.next; - var newState = queue.baseState, - newExpirationTime = 0, - newBaseState = null, - newBaseQueueFirst = null, - newBaseQueueLast = null; - if (null !== baseFirst) { - var update = baseFirst; - do { - pendingQueue = update.expirationTime; - if (pendingQueue < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, + if (null !== firstBaseUpdate) { + currentLastBaseUpdate = queue.baseState; + lastBaseUpdate = 0; + current = firstPendingUpdate = lastPendingUpdate = null; + do { + pendingQueue = firstBaseUpdate.lane; + var updateEventTime = firstBaseUpdate.eventTime; + if ((renderLanes & pendingQueue) === pendingQueue) { + null !== current && + (current = current.next = { + eventTime: updateEventTime, + lane: 0, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, next: null - }; - null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone), - (newBaseState = newState)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - pendingQueue > newExpirationTime && - (newExpirationTime = pendingQueue); - } else { - null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }); - markRenderEventTimeAndConfig(pendingQueue, update.suspenseConfig); - a: { - var workInProgress = workInProgress$jscomp$0, - update$jscomp$0 = update; - pendingQueue = props; - clone = instance; - switch (update$jscomp$0.tag) { - case 1: - workInProgress = update$jscomp$0.payload; - if ("function" === typeof workInProgress) { - newState = workInProgress.call(clone, newState, pendingQueue); - break a; - } - newState = workInProgress; - break a; - case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; - case 0: - workInProgress = update$jscomp$0.payload; - pendingQueue = - "function" === typeof workInProgress - ? workInProgress.call(clone, newState, pendingQueue) - : workInProgress; - if (null === pendingQueue || void 0 === pendingQueue) break a; - newState = Object.assign({}, newState, pendingQueue); + }); + a: { + var workInProgress = workInProgress$jscomp$0, + update = firstBaseUpdate; + pendingQueue = props; + updateEventTime = instance; + switch (update.tag) { + case 1: + workInProgress = update.payload; + if ("function" === typeof workInProgress) { + currentLastBaseUpdate = workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ); break a; - case 2: - hasForceUpdate = !0; - } + } + currentLastBaseUpdate = workInProgress; + break a; + case 3: + workInProgress.flags = (workInProgress.flags & -8193) | 64; + case 0: + workInProgress = update.payload; + pendingQueue = + "function" === typeof workInProgress + ? workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ) + : workInProgress; + if (null === pendingQueue || void 0 === pendingQueue) break a; + currentLastBaseUpdate = Object.assign( + {}, + currentLastBaseUpdate, + pendingQueue + ); + break a; + case 2: + hasForceUpdate = !0; } - null !== update.callback && - ((workInProgress$jscomp$0.effectTag |= 32), - (pendingQueue = queue.effects), - null === pendingQueue - ? (queue.effects = [update]) - : pendingQueue.push(update)); } - update = update.next; - if (null === update || update === baseFirst) - if (((pendingQueue = queue.shared.pending), null === pendingQueue)) - break; - else - (update = baseQueue.next = pendingQueue.next), - (pendingQueue.next = baseFirst), - (queue.baseQueue = baseQueue = pendingQueue), - (queue.shared.pending = null); - } while (1); - } - null === newBaseQueueLast - ? (newBaseState = newState) - : (newBaseQueueLast.next = newBaseQueueFirst); - queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; - markUnprocessedUpdateTime(newExpirationTime); - workInProgress$jscomp$0.expirationTime = newExpirationTime; - workInProgress$jscomp$0.memoizedState = newState; + null !== firstBaseUpdate.callback && + ((workInProgress$jscomp$0.flags |= 32), + (pendingQueue = queue.effects), + null === pendingQueue + ? (queue.effects = [firstBaseUpdate]) + : pendingQueue.push(firstBaseUpdate)); + } else + (updateEventTime = { + eventTime: updateEventTime, + lane: pendingQueue, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, + next: null + }), + null === current + ? ((firstPendingUpdate = current = updateEventTime), + (lastPendingUpdate = currentLastBaseUpdate)) + : (current = current.next = updateEventTime), + (lastBaseUpdate |= pendingQueue); + firstBaseUpdate = firstBaseUpdate.next; + if (null === firstBaseUpdate) + if (((pendingQueue = queue.shared.pending), null === pendingQueue)) + break; + else + (firstBaseUpdate = pendingQueue.next), + (pendingQueue.next = null), + (queue.lastBaseUpdate = pendingQueue), + (queue.shared.pending = null); + } while (1); + null === current && (lastPendingUpdate = currentLastBaseUpdate); + queue.baseState = lastPendingUpdate; + queue.firstBaseUpdate = firstPendingUpdate; + queue.lastBaseUpdate = current; + workInProgressRootSkippedLanes |= lastBaseUpdate; + workInProgress$jscomp$0.lanes = lastBaseUpdate; + workInProgress$jscomp$0.memoizedState = currentLastBaseUpdate; } } function commitUpdateQueue(finishedWork, finishedQueue, instance) { @@ -2137,8 +2427,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2152,54 +2441,45 @@ function applyDerivedStateFromProps( ? ctor : Object.assign({}, ctor, getDerivedStateFromProps); workInProgress.memoizedState = getDerivedStateFromProps; - 0 === workInProgress.expirationTime && + 0 === workInProgress.lanes && (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { isMounted: function(component) { - return (component = component._reactInternalFiber) + return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, enqueueSetState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); } }; function checkShouldComponentUpdate( @@ -2237,7 +2517,7 @@ function constructClassInstance(workInProgress, ctor, props) { null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; ctor.updater = classComponentUpdater; workInProgress.stateNode = ctor; - ctor._reactInternalFiber = workInProgress; + ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), @@ -2258,12 +2538,7 @@ function callComponentWillReceiveProps( instance.state !== workInProgress && classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; instance.props = newProps; instance.state = workInProgress.memoizedState; @@ -2276,7 +2551,7 @@ function mountClassInstance( ? previousContext : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && @@ -2293,15 +2568,10 @@ function mountClassInstance( instance.UNSAFE_componentWillMount(), ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ), + processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2316,7 +2586,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2350,7 +2620,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2362,7 +2632,7 @@ function throwOnInvalidObjectType(returnFiber, newChild) { ("[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + "). If you meant to render a collection of children, use an array instead." ); } function ChildReconciler(shouldTrackSideEffects) { @@ -2374,7 +2644,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2406,26 +2676,22 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (null === current || 6 !== current.tag) return ( - (current = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromText(textContent, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2433,27 +2699,27 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (null !== current && current.elementType === element.type) return ( - (expirationTime = useFiber(current, element.props)), - (expirationTime.ref = coerceRef(returnFiber, current, element)), - (expirationTime.return = returnFiber), - expirationTime + (lanes = useFiber(current, element.props)), + (lanes.ref = coerceRef(returnFiber, current, element)), + (lanes.return = returnFiber), + lanes ); - expirationTime = createFiberFromTypeAndProps( + lanes = createFiberFromTypeAndProps( element.type, element.key, element.props, null, returnFiber.mode, - expirationTime + lanes ); - expirationTime.ref = coerceRef(returnFiber, current, element); - expirationTime.return = returnFiber; - return expirationTime; + lanes.ref = coerceRef(returnFiber, current, element); + lanes.return = returnFiber; + return lanes; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( null === current || 4 !== current.tag || @@ -2461,11 +2727,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) return ( - (current = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromPortal(portal, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2473,13 +2735,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (null === current || 7 !== current.tag) return ( (current = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key )), (current.return = returnFiber), @@ -2489,13 +2751,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (newChild = createFiberFromText( "" + newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2504,24 +2766,24 @@ function ChildReconciler(shouldTrackSideEffects) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: return ( - (expirationTime = createFiberFromTypeAndProps( + (lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef(returnFiber, null, newChild)), - (expirationTime.return = returnFiber), - expirationTime + (lanes.ref = coerceRef(returnFiber, null, newChild)), + (lanes.return = returnFiber), + lanes ); case REACT_PORTAL_TYPE: return ( (newChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2532,7 +2794,7 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null )), (newChild.return = returnFiber), @@ -2542,12 +2804,12 @@ function ChildReconciler(shouldTrackSideEffects) { } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { var key = null !== oldFiber ? oldFiber.key : null; if ("string" === typeof newChild || "number" === typeof newChild) return null !== key ? null - : updateTextNode(returnFiber, oldFiber, "" + newChild, expirationTime); + : updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: @@ -2557,26 +2819,20 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ) - : updateElement(returnFiber, oldFiber, newChild, expirationTime) + : updateElement(returnFiber, oldFiber, newChild, lanes) : null; case REACT_PORTAL_TYPE: return newChild.key === key - ? updatePortal(returnFiber, oldFiber, newChild, expirationTime) + ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; } if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null - : updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + : updateFragment(returnFiber, oldFiber, newChild, lanes, null); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2586,17 +2842,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateTextNode( - returnFiber, - existingChildren, - "" + newChild, - expirationTime - ) + updateTextNode(returnFiber, existingChildren, "" + newChild, lanes) ); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { @@ -2611,15 +2862,10 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, existingChildren, newChild.props.children, - expirationTime, + lanes, newChild.key ) - : updateElement( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + : updateElement(returnFiber, existingChildren, newChild, lanes) ); case REACT_PORTAL_TYPE: return ( @@ -2627,24 +2873,13 @@ function ChildReconciler(shouldTrackSideEffects) { existingChildren.get( null === newChild.key ? newIdx : newChild.key ) || null), - updatePortal( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + updatePortal(returnFiber, existingChildren, newChild, lanes) ); } if (isArray(newChild) || getIteratorFn(newChild)) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateFragment( - returnFiber, - existingChildren, - newChild, - expirationTime, - null - ) + updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); throwOnInvalidObjectType(returnFiber, newChild); } @@ -2654,7 +2889,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { for ( var resultingFirstChild = null, @@ -2672,7 +2907,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); @@ -2695,11 +2930,7 @@ function ChildReconciler(shouldTrackSideEffects) { ); if (null === oldFiber) { for (; newIdx < newChildren.length; newIdx++) - (oldFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - )), + (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && ((currentFirstChild = placeChild( oldFiber, @@ -2722,7 +2953,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes )), null !== nextOldFiber && (shouldTrackSideEffects && @@ -2749,7 +2980,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { var iteratorFn = getIteratorFn(newChildrenIterable); if ("function" !== typeof iteratorFn) @@ -2771,12 +3002,7 @@ function ChildReconciler(shouldTrackSideEffects) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) : (nextOldFiber = oldFiber.sibling); - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); break; @@ -2796,7 +3022,7 @@ function ChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) - (step = createChild(returnFiber, step.value, expirationTime)), + (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber @@ -2810,13 +3036,7 @@ function ChildReconciler(shouldTrackSideEffects) { !step.done; newIdx++, step = newChildrenIterable.next() ) - (step = updateFromMap( - oldFiber, - returnFiber, - newIdx, - step.value, - expirationTime - )), + (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && (shouldTrackSideEffects && null !== step.alternate && @@ -2832,7 +3052,7 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, expirationTime) { + return function(returnFiber, currentFirstChild, newChild, lanes) { var isUnkeyedTopLevelFragment = "object" === typeof newChild && null !== newChild && @@ -2898,26 +3118,26 @@ function ChildReconciler(shouldTrackSideEffects) { ? ((currentFirstChild = createFiberFromFragment( newChild.props.children, returnFiber.mode, - expirationTime, + lanes, newChild.key )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) - : ((expirationTime = createFiberFromTypeAndProps( + : ((lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef( + (lanes.ref = coerceRef( returnFiber, currentFirstChild, newChild )), - (expirationTime.return = returnFiber), - (returnFiber = expirationTime)); + (lanes.return = returnFiber), + (returnFiber = lanes)); } return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: @@ -2956,7 +3176,7 @@ function ChildReconciler(shouldTrackSideEffects) { currentFirstChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); currentFirstChild.return = returnFiber; returnFiber = currentFirstChild; @@ -2975,7 +3195,7 @@ function ChildReconciler(shouldTrackSideEffects) { (currentFirstChild = createFiberFromText( newChild, returnFiber.mode, - expirationTime + lanes )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)), @@ -2986,25 +3206,26 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); if (getIteratorFn(newChild)) return reconcileChildrenIterator( returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); isObject && throwOnInvalidObjectType(returnFiber, newChild); if ("undefined" === typeof newChild && !isUnkeyedTopLevelFragment) switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3012,9 +3233,9 @@ function ChildReconciler(shouldTrackSideEffects) { var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), NO_CONTEXT = {}, - contextStackCursor$1 = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + contextStackCursor$1 = createCursor(NO_CONTEXT), + contextFiberStackCursor = createCursor(NO_CONTEXT), + rootInstanceStackCursor = createCursor(NO_CONTEXT); function requiredContext(c) { if (c === NO_CONTEXT) throw Error( @@ -3037,26 +3258,26 @@ function popHostContainer() { function pushHostContext(fiber) { requiredContext(rootInstanceStackCursor.current); var context = requiredContext(contextStackCursor$1.current); - var nextContext = fiber.type; - nextContext = - "AndroidTextInput" === nextContext || - "RCTMultilineTextInputView" === nextContext || - "RCTSinglelineTextInputView" === nextContext || - "RCTText" === nextContext || - "RCTVirtualText" === nextContext; - nextContext = - context.isInAParentText !== nextContext - ? { isInAParentText: nextContext } + var JSCompiler_inline_result = fiber.type; + JSCompiler_inline_result = + "AndroidTextInput" === JSCompiler_inline_result || + "RCTMultilineTextInputView" === JSCompiler_inline_result || + "RCTSinglelineTextInputView" === JSCompiler_inline_result || + "RCTText" === JSCompiler_inline_result || + "RCTVirtualText" === JSCompiler_inline_result; + JSCompiler_inline_result = + context.isInAParentText !== JSCompiler_inline_result + ? { isInAParentText: JSCompiler_inline_result } : context; - context !== nextContext && + context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, nextContext)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && (pop(contextStackCursor$1), pop(contextFiberStackCursor)); } -var suspenseStackCursor = { current: 0 }; +var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { for (var node = row; null !== node; ) { if (13 === node.tag) { @@ -3064,7 +3285,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim() || shim())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3080,19 +3301,23 @@ function findFirstSuspended(row) { } return null; } -function createDeprecatedResponderListener(responder, props) { - return { responder: responder, props: props }; +var workInProgressSources = []; +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) + workInProgressSources[i]._workInProgressVersionPrimary = null; + workInProgressSources.length = 0; } -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig, - renderExpirationTime = 0, + renderLanes = 0, currentlyRenderingFiber$1 = null, currentHook = null, workInProgressHook = null, - didScheduleRenderPhaseUpdate = !1; + didScheduleRenderPhaseUpdate = !1, + didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3107,36 +3332,36 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = 0; - ReactCurrentDispatcher.current = + workInProgress.lanes = 0; + ReactCurrentDispatcher$1.current = null === current || null === current.memoizedState ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; current = Component(props, secondArg); - if (workInProgress.expirationTime === renderExpirationTime) { - nextRenderExpirationTime = 0; + if (didScheduleRenderPhaseUpdateDuringThisPass) { + nextRenderLanes = 0; do { - workInProgress.expirationTime = 0; - if (!(25 > nextRenderExpirationTime)) + didScheduleRenderPhaseUpdateDuringThisPass = !1; + if (!(25 > nextRenderLanes)) throw Error( "Too many re-renders. React limits the number of renders to prevent an infinite loop." ); - nextRenderExpirationTime += 1; + nextRenderLanes += 1; workInProgressHook = currentHook = null; workInProgress.updateQueue = null; - ReactCurrentDispatcher.current = HooksDispatcherOnRerender; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerender; current = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; workInProgress = null !== currentHook && null !== currentHook.next; - renderExpirationTime = 0; + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; didScheduleRenderPhaseUpdate = !1; if (workInProgress) @@ -3217,40 +3442,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var updateExpirationTime = update.expirationTime; - if (updateExpirationTime < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }; - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - updateExpirationTime > currentlyRenderingFiber$1.expirationTime && - ((currentlyRenderingFiber$1.expirationTime = updateExpirationTime), - markUnprocessedUpdateTime(updateExpirationTime)); - } else + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) null !== newBaseQueueLast && (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ), (current = update.eagerReducer === reducer ? update.eagerState : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3287,6 +3506,114 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + var getVersion = source._getVersion; + getVersion = getVersion(source._source); + var JSCompiler_inline_result = source._workInProgressVersionPrimary; + if (null !== JSCompiler_inline_result) + root = JSCompiler_inline_result === getVersion; + else if ( + ((root = root.mutableReadLanes), (root = (renderLanes & root) === root)) + ) + (source._workInProgressVersionPrimary = getVersion), + workInProgressSources.push(source); + if (root) return getSnapshot(source._source); + workInProgressSources.push(source); + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); +} +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + var getVersion = source._getVersion, + version = getVersion(source._source), + dispatcher = ReactCurrentDispatcher$1.current, + _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + setSnapshot = _dispatcher$useState[1], + snapshot = _dispatcher$useState[0]; + _dispatcher$useState = workInProgressHook; + var memoizedState = hook.memoizedState, + refs = memoizedState.refs, + prevGetSnapshot = refs.getSnapshot, + prevSource = memoizedState.source; + memoizedState = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { refs: refs, source: source, subscribe: subscribe }; + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; + refs.setSnapshot = setSnapshot; + var maybeNewVersion = getVersion(source._source); + if (!objectIs(version, maybeNewVersion)) { + maybeNewVersion = getSnapshot(source._source); + objectIs(snapshot, maybeNewVersion) || + (setSnapshot(maybeNewVersion), + (maybeNewVersion = requestUpdateLane(fiber)), + (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); + maybeNewVersion = root.mutableReadLanes; + root.entangledLanes |= maybeNewVersion; + for ( + var entanglements = root.entanglements, lanes = maybeNewVersion; + 0 < lanes; + + ) { + var index$13 = 31 - clz32(lanes), + lane = 1 << index$13; + entanglements[index$13] |= maybeNewVersion; + lanes &= ~lane; + } + } + }, + [getSnapshot, source, subscribe] + ); + dispatcher.useEffect( + function() { + return subscribe(source._source, function() { + var latestGetSnapshot = refs.getSnapshot, + latestSetSnapshot = refs.setSnapshot; + try { + latestSetSnapshot(latestGetSnapshot(source._source)); + var lane = requestUpdateLane(fiber); + root.mutableReadLanes |= lane & root.pendingLanes; + } catch (error) { + latestSetSnapshot(function() { + throw error; + }); + } + }); + }, + [source, subscribe] + ); + (objectIs(prevGetSnapshot, getSnapshot) && + objectIs(prevSource, source) && + objectIs(memoizedState, subscribe)) || + ((hook = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }), + (hook.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + hook + )), + (_dispatcher$useState.queue = hook), + (_dispatcher$useState.baseQueue = null), + (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); + return snapshot; +} +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} function mountState(initialState) { var hook = mountWorkInProgressHook(); "function" === typeof initialState && (initialState = initialState()); @@ -3323,17 +3650,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3341,12 +3668,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3385,13 +3712,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3419,65 +3739,60 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, fiber, suspenseConfig); - suspenseConfig = { - expirationTime: currentTime, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + var eventTime = requestEventTime(), + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || (null !== pending && pending === currentlyRenderingFiber$1) ) - (didScheduleRenderPhaseUpdate = !0), - (suspenseConfig.expirationTime = renderExpirationTime), - (currentlyRenderingFiber$1.expirationTime = renderExpirationTime); + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = !0; else { if ( - 0 === fiber.expirationTime && - (null === pending || 0 === pending.expirationTime) && + 0 === fiber.lanes && + (null === pending || 0 === pending.lanes) && ((pending = queue.lastRenderedReducer), null !== pending) ) try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { } - scheduleWork(fiber, currentTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function updateEventListener() {} var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -3490,14 +3805,21 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: !1 }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3543,39 +3865,44 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; + }, + useMutableSource: function(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { getSnapshot: getSnapshot, setSnapshot: null }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); }, - useEvent: function() {} + useOpaqueIdentifier: function() { + throw Error("Not yet implemented"); + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnUpdate = { readContext: readContext, @@ -3591,39 +3918,33 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return updateReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnRerender = { readContext: readContext, @@ -3639,61 +3960,45 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return rerenderReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { workInProgress.child = null === current - ? mountChildFibers( - workInProgress, - null, - nextChildren, - renderExpirationTime - ) + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } function updateForwardRef( @@ -3701,33 +4006,28 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { Component = Component.render; var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, nextProps, ref, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, nextProps, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } function updateMemoComponent( @@ -3735,8 +4035,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (null === current) { var type = Component.type; @@ -3755,17 +4055,17 @@ function updateMemoComponent( workInProgress, type, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); current = createFiberFromTypeAndProps( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3773,19 +4073,14 @@ function updateMemoComponent( } type = current.child; if ( - updateExpirationTime < renderExpirationTime && - ((updateExpirationTime = type.memoizedProps), + 0 === (updateLanes & renderLanes) && + ((updateLanes = type.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps) && - current.ref === workInProgress.ref) + Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3796,26 +4091,63 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { - return null !== current && + if ( + null !== current && shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref && - ((didReceiveUpdate = !1), updateExpirationTime < renderExpirationTime) - ? ((workInProgress.expirationTime = current.expirationTime), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - )) - : updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderExpirationTime + current.ref === workInProgress.ref + ) + if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, + nextChildren = nextProps.children, + prevState = null !== current ? current.memoizedState : null; + if ( + "hidden" === nextProps.mode || + "unstable-defer-without-hiding" === nextProps.mode + ) + if (0 === (workInProgress.mode & 4)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes(workInProgress, renderLanes); + else if (0 !== (renderLanes & 1073741824)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes( + workInProgress, + null !== prevState ? prevState.baseLanes : renderLanes + ); + else + return ( + (current = + null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), + (workInProgress.lanes = workInProgress.childLanes = 1073741824), + (workInProgress.memoizedState = { baseLanes: current }), + pushRenderLanes(workInProgress, current), + null + ); + else + null !== prevState + ? ((nextProps = prevState.baseLanes | renderLanes), + (workInProgress.memoizedState = null)) + : (nextProps = renderLanes), + pushRenderLanes(workInProgress, nextProps); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } function markRef(current, workInProgress) { var ref = workInProgress.ref; @@ -3823,42 +4155,37 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { var context = isContextProvider(Component) ? previousContext : contextStackCursor.current; context = getMaskedContext(workInProgress, context); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); Component = renderWithHooks( current, workInProgress, Component, nextProps, context, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, Component, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } function updateClassComponent( @@ -3866,25 +4193,20 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (isContextProvider(Component)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ), + mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); else if (null === current) { var instance = workInProgress.stateNode, @@ -3915,12 +4237,7 @@ function updateClassComponent( hasForceUpdate = !1; var oldState = workInProgress.memoizedState; instance.state = oldState; - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -3953,9 +4270,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -3963,119 +4280,113 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); - } else - (instance = workInProgress.stateNode), - cloneUpdateQueue(current, workInProgress), - (oldProps = workInProgress.memoizedProps), - (instance.props = - workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps)), - (oldContext = instance.context), - (contextType = Component.contextType), - "object" === typeof contextType && null !== contextType - ? (contextType = readContext(contextType)) - : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), - (contextType = getMaskedContext(workInProgress, contextType))), - (getDerivedStateFromProps = Component.getDerivedStateFromProps), - (hasNewLifecycles = - "function" === typeof getDerivedStateFromProps || - "function" === typeof instance.getSnapshotBeforeUpdate) || - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || - ((oldProps !== nextProps || oldContext !== contextType) && - callComponentWillReceiveProps( + } else { + instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + oldProps = workInProgress.memoizedProps; + contextType = + workInProgress.type === workInProgress.elementType + ? oldProps + : resolveDefaultProps(workInProgress.type, oldProps); + instance.props = contextType; + hasNewLifecycles = workInProgress.pendingProps; + oldState = instance.context; + oldContext = Component.contextType; + "object" === typeof oldContext && null !== oldContext + ? (oldContext = readContext(oldContext)) + : ((oldContext = isContextProvider(Component) + ? previousContext + : contextStackCursor.current), + (oldContext = getMaskedContext(workInProgress, oldContext))); + var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; + (getDerivedStateFromProps = + "function" === typeof getDerivedStateFromProps$jscomp$0 || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || + ((oldProps !== hasNewLifecycles || oldState !== oldContext) && + callComponentWillReceiveProps( + workInProgress, + instance, + nextProps, + oldContext + )); + hasForceUpdate = !1; + oldState = workInProgress.memoizedState; + instance.state = oldState; + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + var newState = workInProgress.memoizedState; + oldProps !== hasNewLifecycles || + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate + ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && + (applyDerivedStateFromProps( workInProgress, - instance, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), + (newState = workInProgress.memoizedState)), + (contextType = + hasForceUpdate || + checkShouldComponentUpdate( + workInProgress, + Component, + contextType, nextProps, - contextType - )), - (hasForceUpdate = !1), - (oldContext = workInProgress.memoizedState), - (instance.state = oldContext), - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ), - (oldState = workInProgress.memoizedState), - oldProps !== nextProps || - oldContext !== oldState || - didPerformWorkStackCursor.current || - hasForceUpdate - ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), - (oldState = workInProgress.memoizedState)), - (getDerivedStateFromProps = - hasForceUpdate || - checkShouldComponentUpdate( - workInProgress, - Component, - oldProps, - nextProps, - oldContext, - oldState, - contextType - )) - ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - nextProps, - oldState, - contextType - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - oldState, - contextType - )), - "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), - "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (workInProgress.memoizedProps = nextProps), - (workInProgress.memoizedState = oldState)), - (instance.props = nextProps), - (instance.state = oldState), - (instance.context = contextType), - (nextProps = getDerivedStateFromProps)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (nextProps = !1)); + oldState, + newState, + oldContext + )) + ? (getDerivedStateFromProps || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), + "function" === typeof instance.UNSAFE_componentWillUpdate && + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), + "function" === typeof instance.componentDidUpdate && + (workInProgress.flags |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.flags |= 256)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (workInProgress.memoizedProps = nextProps), + (workInProgress.memoizedState = newState)), + (instance.props = nextProps), + (instance.state = newState), + (instance.context = oldContext), + (nextProps = contextType)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (nextProps = !1)); + } return finishClassComponent( current, workInProgress, Component, nextProps, hasContext, - renderExpirationTime + renderLanes ); } function finishClassComponent( @@ -4084,18 +4395,14 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); shouldUpdate = workInProgress.stateNode; ReactCurrentOwner$1.current = workInProgress; @@ -4103,26 +4410,21 @@ function finishClassComponent( didCaptureError && "function" !== typeof Component.getDerivedStateFromError ? null : shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((workInProgress.child = reconcileChildFibers( workInProgress, current.child, null, - renderExpirationTime + renderLanes )), (workInProgress.child = reconcileChildFibers( workInProgress, null, nextChildren, - renderExpirationTime + renderLanes ))) - : reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + : reconcileChildren(current, workInProgress, nextChildren, renderLanes); workInProgress.memoizedState = shouldUpdate.state; hasContext && invalidateContextProvider(workInProgress, Component, !0); return workInProgress.child; @@ -4139,155 +4441,214 @@ function pushHostRootContext(workInProgress) { pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } -var SUSPENDED_MARKER = { dehydrated: null, retryTime: 0 }; -function updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime -) { - var mode = workInProgress.mode, - nextProps = workInProgress.pendingProps, +var SUSPENDED_MARKER = { dehydrated: null, retryLane: 0 }; +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, - nextDidTimeout = !1, + showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = - 0 !== (suspenseContext & 2) && - (null === current || null !== current.memoizedState)); + null !== current && null === current.memoizedState + ? !1 + : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((nextDidTimeout = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + current = nextProps.children; + suspenseContext = nextProps.fallback; + if (showFallback) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - mode = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( - workInProgress, - null, - mode, - renderExpirationTime - )); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + current + ); + renderLanes = createFiberFromOffscreen( + { mode: "visible", children: current }, + workInProgress.mode, + renderLanes, + null + ); + renderLanes.return = workInProgress; + return (workInProgress.child = renderLanes); } if (null !== current.memoizedState) { - current = current.child; - mode = current.sibling; - if (nextDidTimeout) { - nextProps = nextProps.fallback; - renderExpirationTime = createWorkInProgress( - current, - current.pendingProps + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - if ( - 0 === (workInProgress.mode & 2) && - ((nextDidTimeout = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child), - nextDidTimeout !== current.child) - ) - for ( - renderExpirationTime.child = nextDidTimeout; - null !== nextDidTimeout; - - ) - (nextDidTimeout.return = renderExpirationTime), - (nextDidTimeout = nextDidTimeout.sibling); - mode = createWorkInProgress(mode, nextProps); - mode.return = workInProgress; - renderExpirationTime.sibling = mode; - renderExpirationTime.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = renderExpirationTime; - return mode; - } - renderExpirationTime = reconcileChildFibers( + renderLanes = updateSuspensePrimaryChildren( + current, workInProgress, - current.child, nextProps.children, - renderExpirationTime + renderLanes ); workInProgress.memoizedState = null; - return (workInProgress.child = renderExpirationTime); + return renderLanes; } - current = current.child; - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - nextProps.child = current; - null !== current && (current.return = nextProps); - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - renderExpirationTime.effectTag |= 2; - nextProps.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - workInProgress.memoizedState = null; - return (workInProgress.child = reconcileChildFibers( - workInProgress, + renderLanes = updateSuspensePrimaryChildren( current, + workInProgress, nextProps.children, - renderExpirationTime - )); + renderLanes + ); + workInProgress.memoizedState = null; + return renderLanes; } -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - fiber.expirationTime < renderExpirationTime && - (fiber.expirationTime = renderExpirationTime); +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren)) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + mode: "visible", + children: primaryChildren + }); + 0 === (workInProgress.mode & 2) && (primaryChildren.lanes = renderLanes); + primaryChildren.return = workInProgress; + primaryChildren.sibling = null; + null !== current && + ((current.nextEffect = null), + (current.flags = 8), + (workInProgress.firstEffect = workInProgress.lastEffect = current)); + return (workInProgress.child = primaryChildren); +} +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + var primaryChildProps = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && workInProgress.child !== currentPrimaryChildFragment + ? ((primaryChildren = workInProgress.child), + (primaryChildren.childLanes = 0), + (primaryChildren.pendingProps = primaryChildProps), + (currentPrimaryChildFragment = primaryChildren.lastEffect), + null !== currentPrimaryChildFragment + ? ((workInProgress.firstEffect = primaryChildren.firstEffect), + (workInProgress.lastEffect = currentPrimaryChildFragment), + (currentPrimaryChildFragment.nextEffect = null)) + : (workInProgress.firstEffect = workInProgress.lastEffect = null)) + : (primaryChildren = createWorkInProgress( + currentPrimaryChildFragment, + primaryChildProps + )); + null !== current + ? (fallbackChildren = createWorkInProgress(current, fallbackChildren)) + : ((fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + )), + (fallbackChildren.flags |= 2)); + fallbackChildren.return = workInProgress; + primaryChildren.return = workInProgress; + primaryChildren.sibling = fallbackChildren; + workInProgress.child = primaryChildren; + return fallbackChildren; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes |= renderLanes; var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < renderExpirationTime && - (alternate.expirationTime = renderExpirationTime); - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + null !== alternate && (alternate.lanes |= renderLanes); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function initSuspenseListRenderState( workInProgress, @@ -4305,7 +4666,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4314,35 +4674,24 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, revealOrder = nextProps.revealOrder, tailMode = nextProps.tail; - reconcileChildren( - current, - workInProgress, - nextProps.children, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderExpirationTime); - else if (19 === current.tag) - scheduleWorkOnFiber(current, renderExpirationTime); + scheduleWorkOnFiber(current, renderLanes); + else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -4364,30 +4713,29 @@ function updateSuspenseListComponent( else switch (revealOrder) { case "forwards": - renderExpirationTime = workInProgress.child; - for (revealOrder = null; null !== renderExpirationTime; ) - (current = renderExpirationTime.alternate), + renderLanes = workInProgress.child; + for (revealOrder = null; null !== renderLanes; ) + (current = renderLanes.alternate), null !== current && null === findFirstSuspended(current) && - (revealOrder = renderExpirationTime), - (renderExpirationTime = renderExpirationTime.sibling); - renderExpirationTime = revealOrder; - null === renderExpirationTime + (revealOrder = renderLanes), + (renderLanes = renderLanes.sibling); + renderLanes = revealOrder; + null === renderLanes ? ((revealOrder = workInProgress.child), (workInProgress.child = null)) - : ((revealOrder = renderExpirationTime.sibling), - (renderExpirationTime.sibling = null)); + : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); initSuspenseListRenderState( workInProgress, !1, revealOrder, - renderExpirationTime, + renderLanes, tailMode, workInProgress.lastEffect ); break; case "backwards": - renderExpirationTime = null; + renderLanes = null; revealOrder = workInProgress.child; for (workInProgress.child = null; null !== revealOrder; ) { current = revealOrder.alternate; @@ -4396,14 +4744,14 @@ function updateSuspenseListComponent( break; } current = revealOrder.sibling; - revealOrder.sibling = renderExpirationTime; - renderExpirationTime = revealOrder; + revealOrder.sibling = renderLanes; + renderLanes = revealOrder; revealOrder = current; } initSuspenseListRenderState( workInProgress, !0, - renderExpirationTime, + renderLanes, null, tailMode, workInProgress.lastEffect @@ -4424,35 +4772,28 @@ function updateSuspenseListComponent( } return workInProgress.child; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); - var updateExpirationTime = workInProgress.expirationTime; - 0 !== updateExpirationTime && markUnprocessedUpdateTime(updateExpirationTime); - if (workInProgress.childExpirationTime < renderExpirationTime) return null; - if (null !== current && workInProgress.child !== current.child) - throw Error("Resuming work not yet implemented."); - if (null !== workInProgress.child) { - current = workInProgress.child; - renderExpirationTime = createWorkInProgress(current, current.pendingProps); - workInProgress.child = renderExpirationTime; - for ( - renderExpirationTime.return = workInProgress; - null !== current.sibling; - - ) - (current = current.sibling), - (renderExpirationTime = renderExpirationTime.sibling = createWorkInProgress( - current, - current.pendingProps - )), - (renderExpirationTime.return = workInProgress); - renderExpirationTime.sibling = null; + workInProgressRootSkippedLanes |= workInProgress.lanes; + if (0 !== (renderLanes & workInProgress.childLanes)) { + if (null !== current && workInProgress.child !== current.child) + throw Error("Resuming work not yet implemented."); + if (null !== workInProgress.child) { + current = workInProgress.child; + renderLanes = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes; + for (renderLanes.return = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (renderLanes = renderLanes.sibling = createWorkInProgress( + current, + current.pendingProps + )), + (renderLanes.return = workInProgress); + renderLanes.sibling = null; + } + return workInProgress.child; } - return workInProgress.child; + return null; } var appendAllChildren, updateHostContainer, @@ -4480,10 +4821,10 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { current.memoizedProps !== newProps && (requiredContext(contextStackCursor$1.current), (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); }; updateHostText$1 = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.effectTag |= 4); + oldText !== newText && (workInProgress.flags |= 4); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { @@ -4499,17 +4840,17 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var _lastTailNode = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (_lastTailNode = lastTailNode), + for (var lastTailNode$64 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$64 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === _lastTailNode + null === lastTailNode$64 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (_lastTailNode.sibling = null); + : (lastTailNode$64.sibling = null); } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { case 2: @@ -4530,10 +4871,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { popHostContainer(), pop(didPerformWorkStackCursor), pop(contextStackCursor), - (current = workInProgress.stateNode), - current.pendingContext && - ((current.context = current.pendingContext), - (current.pendingContext = null)), + resetWorkInProgressVersions(), + (newProps = workInProgress.stateNode), + newProps.pendingContext && + ((newProps.context = newProps.pendingContext), + (newProps.pendingContext = null)), + (null !== current && null !== current.child) || + newProps.hydrate || + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4542,17 +4887,16 @@ function completeWork(current, workInProgress, renderExpirationTime) { var rootContainerInstance = requiredContext( rootInstanceStackCursor.current ); - renderExpirationTime = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) updateHostComponent$1( current, workInProgress, - renderExpirationTime, + renderLanes, newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -4563,22 +4907,22 @@ function completeWork(current, workInProgress, renderExpirationTime) { } requiredContext(contextStackCursor$1.current); current = allocateTag(); - renderExpirationTime = getViewConfigForType(renderExpirationTime); + renderLanes = getViewConfigForType(renderLanes); var updatePayload = diffProperties( null, emptyObject, newProps, - renderExpirationTime.validAttributes + renderLanes.validAttributes ); ReactNativePrivateInterface.UIManager.createView( current, - renderExpirationTime.uiViewClassName, + renderLanes.uiViewClassName, rootContainerInstance, updatePayload ); rootContainerInstance = new ReactNativeFiberHostComponent( current, - renderExpirationTime, + renderLanes, workInProgress ); instanceCache.set(current, workInProgress); @@ -4586,8 +4930,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { appendAllChildren(rootContainerInstance, workInProgress, !1, !1); workInProgress.stateNode = rootContainerInstance; finalizeInitialChildren(rootContainerInstance) && - (workInProgress.effectTag |= 4); - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -4622,52 +4966,35 @@ function completeWork(current, workInProgress, renderExpirationTime) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) - return ( - (workInProgress.expirationTime = renderExpirationTime), workInProgress - ); + if (0 !== (workInProgress.flags & 64)) + return (workInProgress.lanes = renderLanes), workInProgress; newProps = null !== newProps; rootContainerInstance = !1; null !== current && - ((renderExpirationTime = current.memoizedState), - (rootContainerInstance = null !== renderExpirationTime), - newProps || - null === renderExpirationTime || - ((renderExpirationTime = current.child.sibling), - null !== renderExpirationTime && - ((updatePayload = workInProgress.firstEffect), - null !== updatePayload - ? ((workInProgress.firstEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = updatePayload)) - : ((workInProgress.firstEffect = workInProgress.lastEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = null)), - (renderExpirationTime.effectTag = 8)))); + (rootContainerInstance = null !== current.memoizedState); if (newProps && !rootContainerInstance && 0 !== (workInProgress.mode & 2)) if ( (null === current && !0 !== workInProgress.memoizedProps.unstable_avoidThisFallback) || 0 !== (suspenseStackCursor.current & 1) ) - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootSuspended); + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3); else { if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended + 0 === workInProgressRootExitStatus || + 3 === workInProgressRootExitStatus ) - workInProgressRootExitStatus = RootSuspendedWithDelay; - 0 !== workInProgressRootNextUnprocessedUpdateTime && - null !== workInProgressRoot && - (markRootSuspendedAtTime( + workInProgressRootExitStatus = 4; + null === workInProgressRoot || + (0 === (workInProgressRootSkippedLanes & 134217727) && + 0 === (workInProgressRootUpdatedLanes & 134217727)) || + markRootSuspended$1( workInProgressRoot, - renderExpirationTime$1 - ), - markRootUpdatedAtTime( - workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime - )); + workInProgressRootRenderLanes + ); } - if (newProps || rootContainerInstance) workInProgress.effectTag |= 4; + if (newProps || rootContainerInstance) workInProgress.flags |= 4; return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -4679,48 +5006,48 @@ function completeWork(current, workInProgress, renderExpirationTime) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( - workInProgressRootExitStatus !== RootIncomplete || - (null !== current && 0 !== (current.effectTag & 64)) + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; - current = renderExpirationTime; + current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), - (renderExpirationTime = current), - (rootContainerInstance.effectTag &= 2), + (renderLanes = current), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), (updatePayload = rootContainerInstance.alternate), null === updatePayload - ? ((rootContainerInstance.childExpirationTime = 0), - (rootContainerInstance.expirationTime = renderExpirationTime), + ? ((rootContainerInstance.childLanes = 0), + (rootContainerInstance.lanes = renderLanes), (rootContainerInstance.child = null), (rootContainerInstance.memoizedProps = null), (rootContainerInstance.memoizedState = null), (rootContainerInstance.updateQueue = null), - (rootContainerInstance.dependencies = null)) - : ((rootContainerInstance.childExpirationTime = - updatePayload.childExpirationTime), - (rootContainerInstance.expirationTime = - updatePayload.expirationTime), + (rootContainerInstance.dependencies = null), + (rootContainerInstance.stateNode = null)) + : ((rootContainerInstance.childLanes = + updatePayload.childLanes), + (rootContainerInstance.lanes = updatePayload.lanes), (rootContainerInstance.child = updatePayload.child), (rootContainerInstance.memoizedProps = updatePayload.memoizedProps), @@ -4728,15 +5055,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { updatePayload.memoizedState), (rootContainerInstance.updateQueue = updatePayload.updateQueue), - (renderExpirationTime = updatePayload.dependencies), + (rootContainerInstance.type = updatePayload.type), + (renderLanes = updatePayload.dependencies), (rootContainerInstance.dependencies = - null === renderExpirationTime + null === renderLanes ? null : { - expirationTime: - renderExpirationTime.expirationTime, - firstContext: renderExpirationTime.firstContext, - responders: renderExpirationTime.responders + lanes: renderLanes.lanes, + firstContext: renderLanes.firstContext })), (newProps = newProps.sibling); push( @@ -4747,6 +5073,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432)); } else { if (!rootContainerInstance) @@ -4754,12 +5086,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -4772,13 +5104,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && - 1 < renderExpirationTime && - ((workInProgress.effectTag |= 64), + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.expirationTime = workInProgress.childExpirationTime = - renderExpirationTime - 1)); + (workInProgress.lanes = 33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -4789,9 +5121,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -4806,6 +5136,17 @@ function completeWork(current, workInProgress, renderExpirationTime) { ), current) : null; + case 22: + case 23: + return ( + popRenderLanes(), + null !== current && + (null !== current.memoizedState) !== + (null !== workInProgress.memoizedState) && + "unstable-defer-without-hiding" !== newProps.mode && + (workInProgress.flags |= 4), + null + ); } throw Error( "Unknown unit of work tag (" + @@ -4817,31 +5158,30 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + resetWorkInProgressVersions(); + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), - workInProgress) + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), workInProgress) : null ); case 19: @@ -4850,6 +5190,9 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: + case 23: + return popRenderLanes(), null; default: return null; } @@ -4868,51 +5211,61 @@ if ( throw Error( "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); -function logCapturedError(capturedError) { - !1 !== - ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ) && console.error(capturedError.error); -} -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source, - stack = errorInfo.stack; - null === stack && - null !== source && - (stack = getStackByFiberInDevAndProd(source)); - errorInfo = { - componentName: null !== source ? getComponentName(source.type) : null, - componentStack: null !== stack ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: !1, - willRetry: !1 - }; - null !== boundary && - 1 === boundary.tag && - ((errorInfo.errorBoundary = boundary.stateNode), - (errorInfo.errorBoundaryName = getComponentName(boundary.type)), - (errorInfo.errorBoundaryFound = !0), - (errorInfo.willRetry = !0)); +function logCapturedError(boundary, errorInfo) { try { - logCapturedError(errorInfo); + !1 !== + ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog({ + componentStack: null !== errorInfo.stack ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + null !== boundary && 1 === boundary.tag ? boundary.stateNode : null + }) && console.error(errorInfo.value); } catch (e) { setTimeout(function() { throw e; }); } } -function safelyCallComponentWillUnmount(current, instance) { - try { - (instance.props = current.memoizedProps), - (instance.state = current.memoizedState), - instance.componentWillUnmount(); - } catch (unmountError) { - captureCommitPhaseError(current, unmountError); +var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; +function createRootErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + lane.payload = { element: null }; + var error = errorInfo.value; + lane.callback = function() { + hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); + logCapturedError(fiber, errorInfo); + }; + return lane; +} +function createClassErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if ("function" === typeof getDerivedStateFromError) { + var error = errorInfo.value; + lane.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error); + }; } + var inst = fiber.stateNode; + null !== inst && + "function" === typeof inst.componentDidCatch && + (lane.callback = function() { + "function" !== typeof getDerivedStateFromError && + (null === legacyErrorBoundariesThatAlreadyFailed + ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) + : legacyErrorBoundariesThatAlreadyFailed.add(this), + logCapturedError(fiber, errorInfo)); + var stack = errorInfo.stack; + this.componentDidCatch(errorInfo.value, { + componentStack: null !== stack ? stack : "" + }); + }); + return lane; } +var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; function safelyDetachRef(current) { var ref = current.ref; if (null !== ref) @@ -4929,10 +5282,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -4946,6 +5298,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } return; case 3: + return; case 5: case 6: case 4: @@ -4956,58 +5309,56 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitHookEffectListUnmount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var destroy = effect.destroy; - effect.destroy = void 0; - void 0 !== destroy && destroy(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} -function commitHookEffectListMount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var create = effect.create; - effect.destroy = create(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} function commitLifeCycles(finishedRoot, current, finishedWork) { switch (finishedWork.tag) { case 0: case 11: case 15: - case 22: - commitHookEffectListMount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + if (3 === (finishedRoot.tag & 3)) { + var create$81 = finishedRoot.create; + finishedRoot.destroy = create$81(); + } + finishedRoot = finishedRoot.next; + } while (finishedRoot !== current); + } + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + var _effect = finishedRoot; + create$81 = _effect.next; + _effect = _effect.tag; + 0 !== (_effect & 4) && + 0 !== (_effect & 1) && + (enqueuePendingPassiveHookEffectUnmount(finishedWork, finishedRoot), + enqueuePendingPassiveHookEffectMount(finishedWork, finishedRoot)); + finishedRoot = create$81; + } while (finishedRoot !== current); + } return; case 1: finishedRoot = finishedWork.stateNode; - if (finishedWork.effectTag & 4) - if (null === current) finishedRoot.componentDidMount(); - else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - finishedRoot.componentDidUpdate( - prevProps, - current.memoizedState, - finishedRoot.__reactInternalSnapshotBeforeUpdate - ); - } + finishedWork.flags & 4 && + (null === current + ? finishedRoot.componentDidMount() + : ((create$81 = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps( + finishedWork.type, + current.memoizedProps + )), + finishedRoot.componentDidUpdate( + create$81, + current.memoizedState, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ))); current = finishedWork.updateQueue; null !== current && commitUpdateQueue(finishedWork, current, finishedRoot); @@ -5041,78 +5392,137 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: + case 23: return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitUnmount(finishedRoot, current$jscomp$0, renderPriorityLevel) { - "function" === typeof onCommitFiberUnmount && - onCommitFiberUnmount(current$jscomp$0); - switch (current$jscomp$0.tag) { +function hideOrUnhideAllChildren(finishedWork, isHidden) { + for (var node = finishedWork; ; ) { + if (5 === node.tag) { + var instance = node.stateNode; + if (isHidden) { + var viewConfig = instance.viewConfig; + var updatePayload = diffProperties( + null, + emptyObject, + { style: { display: "none" } }, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } else { + instance = node.stateNode; + updatePayload = node.memoizedProps; + viewConfig = instance.viewConfig; + var prevProps = Object.assign({}, updatePayload, { + style: [updatePayload.style, { display: "none" }] + }); + updatePayload = diffProperties( + null, + prevProps, + updatePayload, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + } else { + if (6 === node.tag) throw Error("Not yet implemented."); + if ( + ((22 !== node.tag && 23 !== node.tag) || + null === node.memoizedState || + node === finishedWork) && + null !== node.child + ) { + node.child.return = node; + node = node.child; + continue; + } + } + if (node === finishedWork) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === finishedWork) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +} +function commitUnmount(finishedRoot, current) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, current); + } catch (err) {} + switch (current.tag) { case 0: case 11: case 14: case 15: - case 22: - finishedRoot = current$jscomp$0.updateQueue; + finishedRoot = current.updateQueue; if ( null !== finishedRoot && ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) ) { - var firstEffect = finishedRoot.next; - runWithPriority( - 97 < renderPriorityLevel ? 97 : renderPriorityLevel, - function() { - var effect = firstEffect; - do { - var _destroy = effect.destroy; - if (void 0 !== _destroy) { - var current = current$jscomp$0; - try { - _destroy(); - } catch (error) { - captureCommitPhaseError(current, error); - } + var effect = (finishedRoot = finishedRoot.next); + do { + var _effect2 = effect, + destroy = _effect2.destroy; + _effect2 = _effect2.tag; + if (void 0 !== destroy) + if (0 !== (_effect2 & 4)) + enqueuePendingPassiveHookEffectUnmount(current, effect); + else { + _effect2 = current; + try { + destroy(); + } catch (error) { + captureCommitPhaseError(_effect2, error); } - effect = effect.next; - } while (effect !== firstEffect); - } - ); + } + effect = effect.next; + } while (effect !== finishedRoot); } break; case 1: - safelyDetachRef(current$jscomp$0); - renderPriorityLevel = current$jscomp$0.stateNode; - "function" === typeof renderPriorityLevel.componentWillUnmount && - safelyCallComponentWillUnmount(current$jscomp$0, renderPriorityLevel); + safelyDetachRef(current); + finishedRoot = current.stateNode; + if ("function" === typeof finishedRoot.componentWillUnmount) + try { + (finishedRoot.props = current.memoizedProps), + (finishedRoot.state = current.memoizedState), + finishedRoot.componentWillUnmount(); + } catch (unmountError) { + captureCommitPhaseError(current, unmountError); + } break; case 5: - safelyDetachRef(current$jscomp$0); + safelyDetachRef(current); break; case 4: - unmountHostComponents( - finishedRoot, - current$jscomp$0, - renderPriorityLevel - ); + unmountHostComponents(finishedRoot, current); } } -function detachFiber(current) { - var alternate = current.alternate; - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - null !== alternate && detachFiber(alternate); +function detachFiberMutation(fiber) { + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; } function isHostParent(fiber) { return 5 === fiber.tag || 3 === fiber.tag || 4 === fiber.tag; @@ -5120,16 +5530,14 @@ function isHostParent(fiber) { function commitPlacement(finishedWork) { a: { for (var parent = finishedWork.return; null !== parent; ) { - if (isHostParent(parent)) { - var parentFiber = parent; - break a; - } + if (isHostParent(parent)) break a; parent = parent.return; } throw Error( "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." ); } + var parentFiber = parent; parent = parentFiber.stateNode; switch (parentFiber.tag) { case 5: @@ -5148,7 +5556,7 @@ function commitPlacement(finishedWork) { "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." ); } - parentFiber.effectTag & 16 && (parentFiber.effectTag &= -17); + parentFiber.flags & 16 && (parentFiber.flags &= -17); a: b: for (parentFiber = finishedWork; ; ) { for (; null === parentFiber.sibling; ) { if (null === parentFiber.return || isHostParent(parentFiber.return)) { @@ -5163,13 +5571,13 @@ function commitPlacement(finishedWork) { 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { - if (parentFiber.effectTag & 2) continue b; + if (parentFiber.flags & 2) continue b; if (null === parentFiber.child || 4 === parentFiber.tag) continue b; else (parentFiber.child.return = parentFiber), (parentFiber = parentFiber.child); } - if (!(parentFiber.effectTag & 2)) { + if (!(parentFiber.flags & 2)) { parentFiber = parentFiber.stateNode; break a; } @@ -5264,11 +5672,7 @@ function insertOrAppendPlacementNode(node, before, parent) { ) insertOrAppendPlacementNode(node, before, parent), (node = node.sibling); } -function unmountHostComponents( - finishedRoot$jscomp$0, - current, - renderPriorityLevel$jscomp$0 -) { +function unmountHostComponents(finishedRoot$jscomp$0, current) { for ( var node = current, currentParentIsValid = !1, @@ -5306,13 +5710,12 @@ function unmountHostComponents( a: for ( var finishedRoot = finishedRoot$jscomp$0, root = node, - renderPriorityLevel = renderPriorityLevel$jscomp$0, node$jscomp$0 = root; ; ) if ( - (commitUnmount(finishedRoot, node$jscomp$0, renderPriorityLevel), + (commitUnmount(finishedRoot, node$jscomp$0), null !== node$jscomp$0.child && 4 !== node$jscomp$0.tag) ) (node$jscomp$0.child.return = node$jscomp$0), @@ -5339,18 +5742,18 @@ function unmountHostComponents( [0] )) : ((finishedRoot = currentParent), - (renderPriorityLevel = node.stateNode), - recursivelyUncacheFiberNode(renderPriorityLevel), + (node$jscomp$0 = node.stateNode), + recursivelyUncacheFiberNode(node$jscomp$0), (root = finishedRoot._children), - (renderPriorityLevel = root.indexOf(renderPriorityLevel)), - root.splice(renderPriorityLevel, 1), + (node$jscomp$0 = root.indexOf(node$jscomp$0)), + root.splice(node$jscomp$0, 1), ReactNativePrivateInterface.UIManager.manageChildren( finishedRoot._nativeTag, [], [], [], [], - [renderPriorityLevel] + [node$jscomp$0] )); } else if (4 === node.tag) { if (null !== node.child) { @@ -5361,8 +5764,7 @@ function unmountHostComponents( continue; } } else if ( - (commitUnmount(finishedRoot$jscomp$0, node, renderPriorityLevel$jscomp$0), - null !== node.child) + (commitUnmount(finishedRoot$jscomp$0, node), null !== node.child) ) { node.child.return = node; node = node.child; @@ -5384,32 +5786,42 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: - commitHookEffectListUnmount(3, finishedWork); + var updateQueue = finishedWork.updateQueue; + updateQueue = null !== updateQueue ? updateQueue.lastEffect : null; + if (null !== updateQueue) { + var effect = (updateQueue = updateQueue.next); + do + 3 === (effect.tag & 3) && + ((finishedWork = effect.destroy), + (effect.destroy = void 0), + void 0 !== finishedWork && finishedWork()), + (effect = effect.next); + while (effect !== updateQueue); + } return; case 1: return; case 5: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps; - current = null !== current ? current.memoizedProps : newProps; + updateQueue = finishedWork.stateNode; + if (null != updateQueue) { + effect = finishedWork.memoizedProps; + current = null !== current ? current.memoizedProps : effect; var updatePayload = finishedWork.updateQueue; finishedWork.updateQueue = null; null !== updatePayload && - ((finishedWork = instance.viewConfig), - instanceProps.set(instance._nativeTag, newProps), - (newProps = diffProperties( + ((finishedWork = updateQueue.viewConfig), + instanceProps.set(updateQueue._nativeTag, effect), + (effect = diffProperties( null, current, - newProps, + effect, finishedWork.validAttributes )), - null != newProps && + null != effect && ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, + updateQueue._nativeTag, finishedWork.uiViewClassName, - newProps + effect )); } return; @@ -5429,72 +5841,9 @@ function commitWork(current, finishedWork) { case 12: return; case 13: - instance = finishedWork; - null === finishedWork.memoizedState - ? (newProps = !1) - : ((newProps = !0), - (instance = finishedWork.child), - (globalMostRecentFallbackTime = now())); - if (null !== instance) - a: for (current = instance; ; ) { - if (5 === current.tag) - if (((updatePayload = current.stateNode), newProps)) { - var viewConfig = updatePayload.viewConfig; - var updatePayload$jscomp$0 = diffProperties( - null, - emptyObject, - { style: { display: "none" } }, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - updatePayload._nativeTag, - viewConfig.uiViewClassName, - updatePayload$jscomp$0 - ); - } else { - updatePayload = current.stateNode; - updatePayload$jscomp$0 = current.memoizedProps; - viewConfig = updatePayload.viewConfig; - var prevProps = Object.assign({}, updatePayload$jscomp$0, { - style: [updatePayload$jscomp$0.style, { display: "none" }] - }); - updatePayload$jscomp$0 = diffProperties( - null, - prevProps, - updatePayload$jscomp$0, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - updatePayload._nativeTag, - viewConfig.uiViewClassName, - updatePayload$jscomp$0 - ); - } - else { - if (6 === current.tag) throw Error("Not yet implemented."); - if ( - 13 === current.tag && - null !== current.memoizedState && - null === current.memoizedState.dehydrated - ) { - updatePayload = current.child.sibling; - updatePayload.return = current; - current = updatePayload; - continue; - } else if (null !== current.child) { - current.child.return = current; - current = current.child; - continue; - } - } - if (current === instance) break; - for (; null === current.sibling; ) { - if (null === current.return || current.return === instance) break a; - current = current.return; - } - current.sibling.return = current.return; - current = current.sibling; - } + null !== finishedWork.memoizedState && + ((globalMostRecentFallbackTime = now()), + hideOrUnhideAllChildren(finishedWork.child, !0)); attachSuspenseRetryListeners(finishedWork); return; case 19: @@ -5502,90 +5851,58 @@ function commitWork(current, finishedWork) { return; case 17: return; + case 22: + case 23: + hideOrUnhideAllChildren( + finishedWork, + null !== finishedWork.memoizedState + ); + return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } function attachSuspenseRetryListeners(finishedWork) { - var thenables = finishedWork.updateQueue; - if (null !== thenables) { + var wakeables = finishedWork.updateQueue; + if (null !== wakeables) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - thenables.forEach(function(thenable) { - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); - retryCache.has(thenable) || - (retryCache.add(thenable), thenable.then(retry, retry)); + wakeables.forEach(function(wakeable) { + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + retryCache.has(wakeable) || + (retryCache.add(wakeable), wakeable.then(retry, retry)); }); } } -var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - expirationTime.payload = { element: null }; - var error = errorInfo.value; - expirationTime.callback = function() { - hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); - logError(fiber, errorInfo); - }; - return expirationTime; -} -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - if ("function" === typeof getDerivedStateFromError) { - var error = errorInfo.value; - expirationTime.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error); - }; - } - var inst = fiber.stateNode; - null !== inst && - "function" === typeof inst.componentDidCatch && - (expirationTime.callback = function() { - "function" !== typeof getDerivedStateFromError && - (null === legacyErrorBoundariesThatAlreadyFailed - ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) - : legacyErrorBoundariesThatAlreadyFailed.add(this), - logError(fiber, errorInfo)); - var stack = errorInfo.stack; - this.componentDidCatch(errorInfo.value, { - componentStack: null !== stack ? stack : "" - }); - }); - return expirationTime; +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + return null !== current && + ((current = current.memoizedState), + null === current || null !== current.dehydrated) + ? ((finishedWork = finishedWork.memoizedState), + null !== finishedWork && null === finishedWork.dehydrated) + : !1; } var ceil = Math.ceil, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - NoContext = 0, - LegacyUnbatchedContext = 8, - RenderContext = 16, - CommitContext = 32, - RootIncomplete = 0, - RootFatalErrored = 1, - RootErrored = 2, - RootSuspended = 3, - RootSuspendedWithDelay = 4, - RootCompleted = 5, - executionContext = NoContext, + executionContext = 0, workInProgressRoot = null, workInProgress = null, - renderExpirationTime$1 = 0, - workInProgressRootExitStatus = RootIncomplete, + workInProgressRootRenderLanes = 0, + subtreeRenderLanes = 0, + subtreeRenderLanesCursor = createCursor(0), + workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestProcessedExpirationTime = 1073741823, - workInProgressRootLatestSuspenseTimeout = 1073741823, - workInProgressRootCanSuspendUsingConfig = null, - workInProgressRootNextUnprocessedUpdateTime = 0, - workInProgressRootHasPendingPing = !1, + workInProgressRootIncludedLanes = 0, + workInProgressRootSkippedLanes = 0, + workInProgressRootUpdatedLanes = 0, + workInProgressRootPingedLanes = 0, + mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, - FALLBACK_THROTTLE_MS = 500, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5593,205 +5910,186 @@ var ceil = Math.ceil, rootDoesHavePassiveEffects = !1, rootWithPendingPassiveEffects = null, pendingPassiveEffectsRenderPriority = 90, + pendingPassiveHookEffectsMount = [], + pendingPassiveHookEffectsUnmount = [], rootsWithPendingDiscreteUpdates = null, nestedUpdateCount = 0, rootWithNestedUpdates = null, - currentEventTime = 0; -function requestCurrentTimeForUpdate() { - return (executionContext & (RenderContext | CommitContext)) !== NoContext - ? 1073741821 - ((now() / 10) | 0) - : 0 !== currentEventTime + currentEventTime = -1, + currentEventWipLanes = 0, + currentEventPendingLanes = 0, + focusedInstanceHandle = null, + shouldFireAfterActiveInstanceBlur = !1; +function requestEventTime() { + return 0 !== (executionContext & 48) + ? now() + : -1 !== currentEventTime ? currentEventTime - : (currentEventTime = 1073741821 - ((now() / 10) | 0)); + : (currentEventTime = now()); } -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; - if (0 === (fiber & 2)) return 1073741823; - var priorityLevel = getCurrentPriorityLevel(); - if (0 === (fiber & 4)) return 99 === priorityLevel ? 1073741823 : 1073741822; - if ((executionContext & RenderContext) !== NoContext) - return renderExpirationTime$1; - if (null !== suspenseConfig) - currentTime = - 1073741821 - - 25 * - ((((1073741821 - - currentTime + - (suspenseConfig.timeoutMs | 0 || 5e3) / 10) / - 25) | - 0) + - 1); - else - switch (priorityLevel) { - case 99: - currentTime = 1073741823; - break; - case 98: - currentTime = - 1073741821 - 10 * ((((1073741821 - currentTime + 15) / 10) | 0) + 1); - break; - case 97: - case 96: - currentTime = - 1073741821 - 25 * ((((1073741821 - currentTime + 500) / 25) | 0) + 1); - break; - case 95: - currentTime = 2; - break; - default: - throw Error("Expected a valid priority level"); - } - null !== workInProgressRoot && - currentTime === renderExpirationTime$1 && - --currentTime; - return currentTime; -} -function scheduleWork(fiber, expirationTime) { + if (0 === (fiber & 2)) return 1; + if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; + 0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes); + if (0 !== ReactCurrentBatchConfig.transition) { + 0 !== currentEventPendingLanes && + (currentEventPendingLanes = + null !== mostRecentlyUpdatedRoot + ? mostRecentlyUpdatedRoot.pendingLanes + : 0); + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; + } + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; +} +function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), (rootWithNestedUpdates = null), - Error( - "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." - )); - fiber = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - if (null !== fiber) { - var priorityLevel = getCurrentPriorityLevel(); - 1073741823 === expirationTime - ? (executionContext & LegacyUnbatchedContext) !== NoContext && - (executionContext & (RenderContext | CommitContext)) === NoContext - ? performSyncWorkOnRoot(fiber) - : (ensureRootIsScheduled(fiber), - executionContext === NoContext && flushSyncCallbackQueue()) - : ensureRootIsScheduled(fiber); - (executionContext & 4) === NoContext || - (98 !== priorityLevel && 99 !== priorityLevel) || - (null === rootsWithPendingDiscreteUpdates - ? (rootsWithPendingDiscreteUpdates = new Map([[fiber, expirationTime]])) - : ((priorityLevel = rootsWithPendingDiscreteUpdates.get(fiber)), - (void 0 === priorityLevel || priorityLevel > expirationTime) && - rootsWithPendingDiscreteUpdates.set(fiber, expirationTime))); - } -} -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - fiber.expirationTime < expirationTime && - (fiber.expirationTime = expirationTime); - var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < expirationTime && - (alternate.expirationTime = expirationTime); - var node = fiber.return, - root = null; - if (null === node && 3 === fiber.tag) root = fiber.stateNode; - else - for (; null !== node; ) { - alternate = node.alternate; - node.childExpirationTime < expirationTime && - (node.childExpirationTime = expirationTime); - null !== alternate && - alternate.childExpirationTime < expirationTime && - (alternate.childExpirationTime = expirationTime); - if (null === node.return && 3 === node.tag) { - root = node.stateNode; - break; + Error( + "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." + )); + fiber = markUpdateLaneFromFiberToRoot(fiber, lane); + if (null === fiber) return null; + markRootUpdated(fiber, lane, eventTime); + fiber === workInProgressRoot && + ((workInProgressRootUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(fiber, workInProgressRootRenderLanes)); + var priorityLevel = getCurrentPriorityLevel(); + 1 === lane + ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) + ? performSyncWorkOnRoot(fiber) + : (ensureRootIsScheduled(fiber, eventTime), + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) + : (0 === (executionContext & 4) || + (98 !== priorityLevel && 99 !== priorityLevel) || + (null === rootsWithPendingDiscreteUpdates + ? (rootsWithPendingDiscreteUpdates = new Set([fiber])) + : rootsWithPendingDiscreteUpdates.add(fiber)), + ensureRootIsScheduled(fiber, eventTime)); + mostRecentlyUpdatedRoot = fiber; +} +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + sourceFiber.lanes |= lane; + var alternate = sourceFiber.alternate; + null !== alternate && (alternate.lanes |= lane); + alternate = sourceFiber; + for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + (sourceFiber.childLanes |= lane), + (alternate = sourceFiber.alternate), + null !== alternate && (alternate.childLanes |= lane), + (alternate = sourceFiber), + (sourceFiber = sourceFiber.return); + return 3 === alternate.tag ? alternate.stateNode : null; +} +function ensureRootIsScheduled(root, currentTime) { + for ( + var existingCallbackNode = root.callbackNode, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; + 0 < lanes; + + ) { + var index$7 = 31 - clz32(lanes), + lane = 1 << index$7, + expirationTime = expirationTimes[index$7]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) { + expirationTime = currentTime; + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; + expirationTimes[index$7] = + 10 <= priority + ? expirationTime + 250 + : 6 <= priority + ? expirationTime + 5e3 + : -1; } - node = node.return; - } - null !== root && - (workInProgressRoot === root && - (markUnprocessedUpdateTime(expirationTime), - workInProgressRootExitStatus === RootSuspendedWithDelay && - markRootSuspendedAtTime(root, renderExpirationTime$1)), - markRootUpdatedAtTime(root, expirationTime)); - return root; -} -function getNextRootExpirationTimeToWorkOn(root) { - var lastExpiredTime = root.lastExpiredTime; - if (0 !== lastExpiredTime) return lastExpiredTime; - lastExpiredTime = root.firstPendingTime; - if (!isRootSuspendedAtTime(root, lastExpiredTime)) return lastExpiredTime; - var lastPingedTime = root.lastPingedTime; - root = root.nextKnownPendingLevel; - root = lastPingedTime > root ? lastPingedTime : root; - return 2 >= root && lastExpiredTime !== root ? 0 : root; -} -function ensureRootIsScheduled(root) { - if (0 !== root.lastExpiredTime) - (root.callbackExpirationTime = 1073741823), - (root.callbackPriority = 99), - (root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - )); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + suspendedLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + currentTime = return_highestLanePriority; + if (0 === suspendedLanes) + null !== existingCallbackNode && + (existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode), + (root.callbackNode = null), + (root.callbackPriority = 0)); else { - var expirationTime = getNextRootExpirationTimeToWorkOn(root), - existingCallbackNode = root.callbackNode; - if (0 === expirationTime) - null !== existingCallbackNode && - ((root.callbackNode = null), - (root.callbackExpirationTime = 0), - (root.callbackPriority = 90)); - else { - var priorityLevel = requestCurrentTimeForUpdate(); - 1073741823 === expirationTime - ? (priorityLevel = 99) - : 1 === expirationTime || 2 === expirationTime - ? (priorityLevel = 95) - : ((priorityLevel = - 10 * (1073741821 - expirationTime) - - 10 * (1073741821 - priorityLevel)), - (priorityLevel = - 0 >= priorityLevel - ? 99 - : 250 >= priorityLevel - ? 98 - : 5250 >= priorityLevel - ? 97 - : 95)); - if (null !== existingCallbackNode) { - var existingCallbackPriority = root.callbackPriority; - if ( - root.callbackExpirationTime === expirationTime && - existingCallbackPriority >= priorityLevel - ) - return; - existingCallbackNode !== fakeCallbackNode && - Scheduler_cancelCallback(existingCallbackNode); - } - root.callbackExpirationTime = expirationTime; - root.callbackPriority = priorityLevel; - expirationTime = - 1073741823 === expirationTime - ? scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)) - : scheduleCallback( - priorityLevel, - performConcurrentWorkOnRoot.bind(null, root), - { timeout: 10 * (1073741821 - expirationTime) - now() } - ); - root.callbackNode = expirationTime; + if (null !== existingCallbackNode) { + if (root.callbackPriority === currentTime) return; + existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode); } + 15 === currentTime + ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), + null === syncQueue + ? ((syncQueue = [existingCallbackNode]), + (immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ))) + : syncQueue.push(existingCallbackNode), + (existingCallbackNode = fakeCallbackNode)) + : 14 === currentTime + ? (existingCallbackNode = scheduleCallback( + 99, + performSyncWorkOnRoot.bind(null, root) + )) + : ((existingCallbackNode = lanePriorityToSchedulerPriority(currentTime)), + (existingCallbackNode = scheduleCallback( + existingCallbackNode, + performConcurrentWorkOnRoot.bind(null, root) + ))); + root.callbackPriority = currentTime; + root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = 0; - if (didTimeout) { - didTimeout = requestCurrentTimeForUpdate(); - var lastExpiredTime = root.lastExpiredTime; - if (0 === lastExpiredTime || lastExpiredTime > didTimeout) - root.lastExpiredTime = didTimeout; - ensureRootIsScheduled(root); - return null; - } - lastExpiredTime = getNextRootExpirationTimeToWorkOn(root); - if (0 === lastExpiredTime) return null; - didTimeout = root.callbackNode; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) +function performConcurrentWorkOnRoot(root) { + currentEventTime = -1; + currentEventPendingLanes = currentEventWipLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - flushPassiveEffects(); - var expirationTime = lastExpiredTime; - var exitStatus = executionContext; - executionContext |= RenderContext; + var originalCallbackNode = root.callbackNode; + if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) + return null; + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + if (0 === lanes) return null; + var exitStatus = lanes; + var prevExecutionContext = executionContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - (root === workInProgressRoot && expirationTime === renderExpirationTime$1) || - prepareFreshStack(root, expirationTime); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== exitStatus + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, exitStatus); do try { workLoopConcurrent(); @@ -5801,199 +6099,163 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } while (1); resetContextDependencies(); - ReactCurrentDispatcher$1.current = prevDispatcher; - executionContext = exitStatus; + ReactCurrentDispatcher$2.current = prevDispatcher; + executionContext = prevExecutionContext; null !== workInProgress - ? (exitStatus = RootIncomplete) + ? (exitStatus = 0) : ((workInProgressRoot = null), + (workInProgressRootRenderLanes = 0), (exitStatus = workInProgressRootExitStatus)); - if (exitStatus !== RootIncomplete) { - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) - throw ((didTimeout = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), - didTimeout); - expirationTime = root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) + prepareFreshStack(root, 0); + else if (0 !== exitStatus) { + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && (root.hydrate = !1), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) + throw ((originalCallbackNode = workInProgressRootFatalError), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); + root.finishedWork = root.current.alternate; + root.finishedLanes = lanes; switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: + case 0: + case 1: throw Error("Root did not complete. This is a bug in React."); - case RootErrored: + case 2: commitRoot(root); break; - case RootSuspended: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - expirationTime - )); + case 3: + markRootSuspended$1(root, lanes); if ( - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - ((expirationTime = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now()), - 10 < expirationTime) + (lanes & 62914560) === lanes && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { - if ( - workInProgressRootHasPendingPing && - ((prevDispatcher = root.lastPingedTime), - 0 === prevDispatcher || prevDispatcher >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - prevDispatcher = getNextRootExpirationTimeToWorkOn(root); - if (0 !== prevDispatcher && prevDispatcher !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; + if (0 !== getNextLanes(root, 0)) break; + prevExecutionContext = root.suspendedLanes; + if ((prevExecutionContext & lanes) !== lanes) { + requestEventTime(); + root.pingedLanes |= root.suspendedLanes & prevExecutionContext; break; } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - expirationTime + exitStatus ); break; } commitRoot(root); break; - case RootSuspendedWithDelay: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - expirationTime - )); - if ( - workInProgressRootHasPendingPing && - ((expirationTime = root.lastPingedTime), - 0 === expirationTime || expirationTime >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - expirationTime = getNextRootExpirationTimeToWorkOn(root); - if (0 !== expirationTime && expirationTime !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; - break; + case 4: + markRootSuspended$1(root, lanes); + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevExecutionContext = -1; 0 < lanes; ) { + var index$6 = 31 - clz32(lanes); + prevDispatcher = 1 << index$6; + index$6 = exitStatus[index$6]; + index$6 > prevExecutionContext && (prevExecutionContext = index$6); + lanes &= ~prevDispatcher; } - 1073741823 !== workInProgressRootLatestSuspenseTimeout - ? (expirationTime = - 10 * (1073741821 - workInProgressRootLatestSuspenseTimeout) - - now()) - : 1073741823 === workInProgressRootLatestProcessedExpirationTime - ? (expirationTime = 0) - : ((expirationTime = - 10 * - (1073741821 - workInProgressRootLatestProcessedExpirationTime) - - 5e3), - (exitStatus = now()), - (lastExpiredTime = - 10 * (1073741821 - lastExpiredTime) - exitStatus), - (expirationTime = exitStatus - expirationTime), - 0 > expirationTime && (expirationTime = 0), - (expirationTime = - (120 > expirationTime - ? 120 - : 480 > expirationTime - ? 480 - : 1080 > expirationTime - ? 1080 - : 1920 > expirationTime - ? 1920 - : 3e3 > expirationTime - ? 3e3 - : 4320 > expirationTime - ? 4320 - : 1960 * ceil(expirationTime / 1960)) - expirationTime), - lastExpiredTime < expirationTime && - (expirationTime = lastExpiredTime)); - if (10 < expirationTime) { + lanes = prevExecutionContext; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; + if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - expirationTime + lanes ); break; } commitRoot(root); break; - case RootCompleted: - if ( - 1073741823 !== workInProgressRootLatestProcessedExpirationTime && - null !== workInProgressRootCanSuspendUsingConfig - ) { - prevDispatcher = workInProgressRootLatestProcessedExpirationTime; - var suspenseConfig = workInProgressRootCanSuspendUsingConfig; - expirationTime = suspenseConfig.busyMinDurationMs | 0; - 0 >= expirationTime - ? (expirationTime = 0) - : ((exitStatus = suspenseConfig.busyDelayMs | 0), - (prevDispatcher = - now() - - (10 * (1073741821 - prevDispatcher) - - (suspenseConfig.timeoutMs | 0 || 5e3))), - (expirationTime = - prevDispatcher <= exitStatus - ? 0 - : exitStatus + expirationTime - prevDispatcher)); - if (10 < expirationTime) { - markRootSuspendedAtTime(root, lastExpiredTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - expirationTime - ); - break; - } - } + case 5: commitRoot(root); break; default: throw Error("Unknown root exit status."); } } - ensureRootIsScheduled(root); - return root.callbackNode === didTimeout + ensureRootIsScheduled(root, now()); + return root.callbackNode === originalCallbackNode ? performConcurrentWorkOnRoot.bind(null, root) : null; } +function markRootSuspended$1(root, suspendedLanes) { + suspendedLanes &= ~workInProgressRootPingedLanes; + suspendedLanes &= ~workInProgressRootUpdatedLanes; + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; + for (root = root.expirationTimes; 0 < suspendedLanes; ) { + var index$11 = 31 - clz32(suspendedLanes), + lane = 1 << index$11; + root[index$11] = -1; + suspendedLanes &= ~lane; + } +} function performSyncWorkOnRoot(root) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - lastExpiredTime = - 0 !== lastExpiredTime - ? root === workInProgressRoot && renderExpirationTime$1 >= lastExpiredTime - ? renderExpirationTime$1 - : lastExpiredTime - : 1073741823; - var exitStatus = renderRootSync(root, lastExpiredTime); + if ( + root === workInProgressRoot && + 0 !== (root.expiredLanes & workInProgressRootRenderLanes) + ) { + var lanes = workInProgressRootRenderLanes; + var exitStatus = renderRootSync(root, lanes); + 0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes) && + ((lanes = getNextLanes(root, lanes)), + (exitStatus = renderRootSync(root, lanes))); + } else + (lanes = getNextLanes(root, 0)), (exitStatus = renderRootSync(root, lanes)); 0 !== root.tag && - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && (root.hydrate = !1), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), exitStatus); root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + root.finishedLanes = lanes; commitRoot(root); - ensureRootIsScheduled(root); + ensureRootIsScheduled(root, now()); return null; } -function prepareFreshStack(root, expirationTime) { +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes); + subtreeRenderLanes |= lanes; + workInProgressRootIncludedLanes |= lanes; +} +function popRenderLanes() { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor); +} +function prepareFreshStack(root, lanes) { root.finishedWork = null; - root.finishedExpirationTime = 0; + root.finishedLanes = 0; var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); @@ -6011,6 +6273,7 @@ function prepareFreshStack(root, expirationTime) { popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); + resetWorkInProgressVersions(); break; case 5: popHostContext(interruptedWork); @@ -6026,25 +6289,27 @@ function prepareFreshStack(root, expirationTime) { break; case 10: popProvider(interruptedWork); + break; + case 22: + case 23: + popRenderLanes(); } timeoutHandle = timeoutHandle.return; } workInProgressRoot = root; workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = workInProgressRootLatestProcessedExpirationTime = 1073741823; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = 0; - workInProgressRootHasPendingPing = !1; + workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; } function handleError(root$jscomp$0, thrownValue) { do { + var erroredWork = workInProgress; try { resetContextDependencies(); - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - if (didScheduleRenderPhaseUpdate) + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (didScheduleRenderPhaseUpdate) { for ( var hook = currentlyRenderingFiber$1.memoizedState; null !== hook; @@ -6054,49 +6319,52 @@ function handleError(root$jscomp$0, thrownValue) { null !== queue && (queue.pending = null); hook = hook.next; } - renderExpirationTime = 0; + didScheduleRenderPhaseUpdate = !1; + } + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; - didScheduleRenderPhaseUpdate = !1; - if (null === workInProgress || null === workInProgress.return) - return ( - (workInProgressRootExitStatus = RootFatalErrored), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null) - ); + didScheduleRenderPhaseUpdateDuringThisPass = !1; + ReactCurrentOwner$2.current = null; + if (null === erroredWork || null === erroredWork.return) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + break; + } a: { var root = root$jscomp$0, - returnFiber = workInProgress.return, - sourceFiber = workInProgress, + returnFiber = erroredWork.return, + sourceFiber = erroredWork, value = thrownValue; - thrownValue = renderExpirationTime$1; - sourceFiber.effectTag |= 2048; + thrownValue = workInProgressRootRenderLanes; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && "object" === typeof value && "function" === typeof value.then ) { - var thenable = value; + var wakeable = value; if (0 === (sourceFiber.mode & 2)) { var currentSource = sourceFiber.alternate; currentSource ? ((sourceFiber.updateQueue = currentSource.updateQueue), (sourceFiber.memoizedState = currentSource.memoizedState), - (sourceFiber.expirationTime = currentSource.expirationTime)) + (sourceFiber.lanes = currentSource.lanes)) : ((sourceFiber.updateQueue = null), (sourceFiber.memoizedState = null)); } var hasInvisibleParentBoundary = 0 !== (suspenseStackCursor.current & 1), - _workInProgress = returnFiber; + workInProgress$76 = returnFiber; do { var JSCompiler_temp; - if ((JSCompiler_temp = 13 === _workInProgress.tag)) { - var nextState = _workInProgress.memoizedState; + if ((JSCompiler_temp = 13 === workInProgress$76.tag)) { + var nextState = workInProgress$76.memoizedState; if (null !== nextState) JSCompiler_temp = null !== nextState.dehydrated ? !0 : !1; else { - var props = _workInProgress.memoizedProps; + var props = workInProgress$76.memoizedProps; JSCompiler_temp = void 0 === props.fallback ? !1 @@ -6108,23 +6376,24 @@ function handleError(root$jscomp$0, thrownValue) { } } if (JSCompiler_temp) { - var thenables = _workInProgress.updateQueue; - if (null === thenables) { + var wakeables = workInProgress$76.updateQueue; + if (null === wakeables) { var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else thenables.add(thenable); - if (0 === (_workInProgress.mode & 2)) { - _workInProgress.effectTag |= 64; - sourceFiber.effectTag &= -2981; + updateQueue.add(wakeable); + workInProgress$76.updateQueue = updateQueue; + } else wakeables.add(wakeable); + if (0 === (workInProgress$76.mode & 2)) { + workInProgress$76.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(1073741823, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } - sourceFiber.expirationTime = 1073741823; + sourceFiber.lanes |= 1; break a; } value = void 0; @@ -6133,108 +6402,98 @@ function handleError(root$jscomp$0, thrownValue) { null === pingCache ? ((pingCache = root.pingCache = new PossiblyWeakMap()), (value = new Set()), - pingCache.set(thenable, value)) - : ((value = pingCache.get(thenable)), + pingCache.set(wakeable, value)) + : ((value = pingCache.get(wakeable)), void 0 === value && - ((value = new Set()), pingCache.set(thenable, value))); + ((value = new Set()), pingCache.set(wakeable, value))); if (!value.has(sourceFiber)) { value.add(sourceFiber); var ping = pingSuspendedRoot.bind( null, root, - thenable, + wakeable, sourceFiber ); - thenable.then(ping, ping); + wakeable.then(ping, ping); } - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; + workInProgress$76.flags |= 8192; + workInProgress$76.lanes = thrownValue; break a; } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$76 = workInProgress$76.return; + } while (null !== workInProgress$76); value = Error( (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) + " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." ); } - workInProgressRootExitStatus !== RootCompleted && - (workInProgressRootExitStatus = RootErrored); + 5 !== workInProgressRootExitStatus && + (workInProgressRootExitStatus = 2); value = createCapturedValue(value, sourceFiber); - _workInProgress = returnFiber; + workInProgress$76 = returnFiber; do { - switch (_workInProgress.tag) { + switch (workInProgress$76.tag) { case 3: - thenable = value; - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update = createRootErrorUpdate( - _workInProgress, - thenable, + root = value; + workInProgress$76.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$76.lanes |= thrownValue; + var update$77 = createRootErrorUpdate( + workInProgress$76, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update); + enqueueCapturedUpdate(workInProgress$76, update$77); break a; case 1: - thenable = value; - var ctor = _workInProgress.type, - instance = _workInProgress.stateNode; + root = value; + var ctor = workInProgress$76.type, + instance = workInProgress$76.stateNode; if ( - 0 === (_workInProgress.effectTag & 64) && + 0 === (workInProgress$76.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update2 = createClassErrorUpdate( - _workInProgress, - thenable, + workInProgress$76.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$76.lanes |= thrownValue; + var update$80 = createClassErrorUpdate( + workInProgress$76, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update2); + enqueueCapturedUpdate(workInProgress$76, update$80); break a; } } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$76 = workInProgress$76.return; + } while (null !== workInProgress$76); } - workInProgress = completeUnitOfWork(workInProgress); + completeUnitOfWork(erroredWork); } catch (yetAnotherThrownValue) { thrownValue = yetAnotherThrownValue; + workInProgress === erroredWork && + null !== erroredWork && + (workInProgress = erroredWork = erroredWork.return); continue; } break; } while (1); } function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - expirationTime < workInProgressRootLatestProcessedExpirationTime && - 2 < expirationTime && - (workInProgressRootLatestProcessedExpirationTime = expirationTime); - null !== suspenseConfig && - expirationTime < workInProgressRootLatestSuspenseTimeout && - 2 < expirationTime && - ((workInProgressRootLatestSuspenseTimeout = expirationTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig)); -} -function markUnprocessedUpdateTime(expirationTime) { - expirationTime > workInProgressRootNextUnprocessedUpdateTime && - (workInProgressRootNextUnprocessedUpdateTime = expirationTime); -} -function renderRootSync(root, expirationTime) { +function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; - executionContext |= RenderContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - (root === workInProgressRoot && expirationTime === renderExpirationTime$1) || - prepareFreshStack(root, expirationTime); + (workInProgressRoot === root && workInProgressRootRenderLanes === lanes) || + prepareFreshStack(root, lanes); do try { workLoopSync(); @@ -6245,142 +6504,144 @@ function renderRootSync(root, expirationTime) { while (1); resetContextDependencies(); executionContext = prevExecutionContext; - ReactCurrentDispatcher$1.current = prevDispatcher; + ReactCurrentDispatcher$2.current = prevDispatcher; if (null !== workInProgress) throw Error( "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." ); workInProgressRoot = null; + workInProgressRootRenderLanes = 0; return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress; ) performUnitOfWork(workInProgress); } function workLoopConcurrent() { - for (; null !== workInProgress && !shouldYield(); ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress && !Scheduler_shouldYield(); ) + performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { - var next = beginWork$1( - unitOfWork.alternate, - unitOfWork, - renderExpirationTime$1 - ); + var next = beginWork$1(unitOfWork.alternate, unitOfWork, subtreeRenderLanes); unitOfWork.memoizedProps = unitOfWork.pendingProps; - null === next && (next = completeUnitOfWork(unitOfWork)); + null === next ? completeUnitOfWork(unitOfWork) : (workInProgress = next); ReactCurrentOwner$2.current = null; - return next; } function completeUnitOfWork(unitOfWork) { - workInProgress = unitOfWork; + var completedWork = unitOfWork; do { - var current = workInProgress.alternate; - unitOfWork = workInProgress.return; - if (0 === (workInProgress.effectTag & 2048)) { - current = completeWork(current, workInProgress, renderExpirationTime$1); + var current = completedWork.alternate; + unitOfWork = completedWork.return; + if (0 === (completedWork.flags & 4096)) { + current = completeWork(current, completedWork, subtreeRenderLanes); + if (null !== current) { + workInProgress = current; + return; + } + current = completedWork; if ( - 1 === renderExpirationTime$1 || - 1 !== workInProgress.childExpirationTime + (23 !== current.tag && 22 !== current.tag) || + null === current.memoizedState || + 0 !== (subtreeRenderLanes & 1073741824) || + 0 === (current.mode & 4) ) { - for ( - var newChildExpirationTime = 0, _child = workInProgress.child; - null !== _child; - - ) { - var _childUpdateExpirationTime = _child.expirationTime, - _childChildExpirationTime = _child.childExpirationTime; - _childUpdateExpirationTime > newChildExpirationTime && - (newChildExpirationTime = _childUpdateExpirationTime); - _childChildExpirationTime > newChildExpirationTime && - (newChildExpirationTime = _childChildExpirationTime); - _child = _child.sibling; - } - workInProgress.childExpirationTime = newChildExpirationTime; + for (var newChildLanes = 0, child = current.child; null !== child; ) + (newChildLanes |= child.lanes | child.childLanes), + (child = child.sibling); + current.childLanes = newChildLanes; } - if (null !== current) return current; null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && - (unitOfWork.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && + (unitOfWork.firstEffect = completedWork.firstEffect), + null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && - (unitOfWork.lastEffect.nextEffect = workInProgress.firstEffect), - (unitOfWork.lastEffect = workInProgress.lastEffect)), - 1 < workInProgress.effectTag && + (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), + (unitOfWork.lastEffect = completedWork.lastEffect)), + 1 < completedWork.flags && (null !== unitOfWork.lastEffect - ? (unitOfWork.lastEffect.nextEffect = workInProgress) - : (unitOfWork.firstEffect = workInProgress), - (unitOfWork.lastEffect = workInProgress))); + ? (unitOfWork.lastEffect.nextEffect = completedWork) + : (unitOfWork.firstEffect = completedWork), + (unitOfWork.lastEffect = completedWork))); } else { - current = unwindWork(workInProgress); - if (null !== current) return (current.effectTag &= 2047), current; + current = unwindWork(completedWork); + if (null !== current) { + current.flags &= 4095; + workInProgress = current; + return; + } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } - current = workInProgress.sibling; - if (null !== current) return current; - workInProgress = unitOfWork; - } while (null !== workInProgress); - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootCompleted); - return null; -} -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - fiber = fiber.childExpirationTime; - return updateExpirationTime > fiber ? updateExpirationTime : fiber; + completedWork = completedWork.sibling; + if (null !== completedWork) { + workInProgress = completedWork; + return; + } + workInProgress = completedWork = unitOfWork; + } while (null !== completedWork); + 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } function commitRoot(root) { var renderPriorityLevel = getCurrentPriorityLevel(); runWithPriority(99, commitRootImpl.bind(null, root, renderPriorityLevel)); return null; } -function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { +function commitRootImpl(root, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - var finishedWork = root$jscomp$0.finishedWork, - expirationTime = root$jscomp$0.finishedExpirationTime; + var finishedWork = root.finishedWork; if (null === finishedWork) return null; - root$jscomp$0.finishedWork = null; - root$jscomp$0.finishedExpirationTime = 0; - if (finishedWork === root$jscomp$0.current) + root.finishedWork = null; + root.finishedLanes = 0; + if (finishedWork === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - root$jscomp$0.callbackNode = null; - root$jscomp$0.callbackExpirationTime = 0; - root$jscomp$0.callbackPriority = 90; - root$jscomp$0.nextKnownPendingLevel = 0; - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - root$jscomp$0.firstPendingTime = remainingExpirationTimeBeforeCommit; - expirationTime <= root$jscomp$0.lastSuspendedTime - ? (root$jscomp$0.firstSuspendedTime = root$jscomp$0.lastSuspendedTime = root$jscomp$0.nextKnownPendingLevel = 0) - : expirationTime <= root$jscomp$0.firstSuspendedTime && - (root$jscomp$0.firstSuspendedTime = expirationTime - 1); - expirationTime <= root$jscomp$0.lastPingedTime && - (root$jscomp$0.lastPingedTime = 0); - expirationTime <= root$jscomp$0.lastExpiredTime && - (root$jscomp$0.lastExpiredTime = 0); - root$jscomp$0 === workInProgressRoot && + root.callbackNode = null; + var remainingLanes = finishedWork.lanes | finishedWork.childLanes, + remainingLanes$jscomp$0 = remainingLanes, + noLongerPendingLanes = root.pendingLanes & ~remainingLanes$jscomp$0; + root.pendingLanes = remainingLanes$jscomp$0; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes$jscomp$0; + root.mutableReadLanes &= remainingLanes$jscomp$0; + root.entangledLanes &= remainingLanes$jscomp$0; + remainingLanes$jscomp$0 = root.entanglements; + for ( + var eventTimes = root.eventTimes, expirationTimes = root.expirationTimes; + 0 < noLongerPendingLanes; + + ) { + var index$12 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$12; + remainingLanes$jscomp$0[index$12] = 0; + eventTimes[index$12] = -1; + expirationTimes[index$12] = -1; + noLongerPendingLanes &= ~lane; + } + null !== rootsWithPendingDiscreteUpdates && + 0 === (remainingLanes & 24) && + rootsWithPendingDiscreteUpdates.has(root) && + rootsWithPendingDiscreteUpdates.delete(root); + root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (renderExpirationTime$1 = 0)); - 1 < finishedWork.effectTag + (workInProgressRootRenderLanes = 0)); + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), - (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect)) - : (remainingExpirationTimeBeforeCommit = finishedWork) - : (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect); - if (null !== remainingExpirationTimeBeforeCommit) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - ReactCurrentOwner$2.current = null; - nextEffect = remainingExpirationTimeBeforeCommit; + (remainingLanes = finishedWork.firstEffect)) + : (remainingLanes = finishedWork) + : (remainingLanes = finishedWork.firstEffect); + if (null !== remainingLanes) { + remainingLanes$jscomp$0 = executionContext; + executionContext |= 32; + focusedInstanceHandle = ReactCurrentOwner$2.current = null; + shouldFireAfterActiveInstanceBlur = !1; + nextEffect = remainingLanes; do try { commitBeforeMutationEffects(); @@ -6390,17 +6651,13 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - nextEffect = remainingExpirationTimeBeforeCommit; + focusedInstanceHandle = null; + nextEffect = remainingLanes; do try { - for ( - var root = root$jscomp$0, - renderPriorityLevel = renderPriorityLevel$jscomp$0; - null !== nextEffect; - - ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + for (eventTimes = root; null !== nextEffect; ) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6410,52 +6667,50 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: commitWork(nextEffect.alternate, nextEffect); break; case 8: - var current$jscomp$0 = nextEffect; - unmountHostComponents( - root, - current$jscomp$0, - renderPriorityLevel - ); - detachFiber(current$jscomp$0); + expirationTimes = nextEffect; + unmountHostComponents(eventTimes, expirationTimes); + var alternate = expirationTimes.alternate; + detachFiberMutation(expirationTimes); + null !== alternate && detachFiberMutation(alternate); } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$88) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$88); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - root$jscomp$0.current = finishedWork; - nextEffect = remainingExpirationTimeBeforeCommit; + root.current = finishedWork; + nextEffect = remainingLanes; do try { - for (effectTag = root$jscomp$0; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6474,55 +6729,71 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$89) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$89); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); nextEffect = null; requestPaint(); - executionContext = prevExecutionContext; - } else root$jscomp$0.current = finishedWork; + executionContext = remainingLanes$jscomp$0; + } else root.current = finishedWork; if (rootDoesHavePassiveEffects) (rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root$jscomp$0), - (pendingPassiveEffectsRenderPriority = renderPriorityLevel$jscomp$0); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsRenderPriority = renderPriorityLevel); else - for ( - nextEffect = remainingExpirationTimeBeforeCommit; - null !== nextEffect; - - ) - (renderPriorityLevel$jscomp$0 = nextEffect.nextEffect), + for (nextEffect = remainingLanes; null !== nextEffect; ) + (renderPriorityLevel = nextEffect.nextEffect), (nextEffect.nextEffect = null), - (nextEffect = renderPriorityLevel$jscomp$0); - renderPriorityLevel$jscomp$0 = root$jscomp$0.firstPendingTime; - 0 === renderPriorityLevel$jscomp$0 && - (legacyErrorBoundariesThatAlreadyFailed = null); - 1073741823 === renderPriorityLevel$jscomp$0 - ? root$jscomp$0 === rootWithNestedUpdates + nextEffect.flags & 8 && + ((flags$jscomp$0 = nextEffect), + (flags$jscomp$0.sibling = null), + (flags$jscomp$0.stateNode = null)), + (nextEffect = renderPriorityLevel); + remainingLanes = root.pendingLanes; + 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); + 1 === remainingLanes + ? root === rootWithNestedUpdates ? nestedUpdateCount++ - : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root$jscomp$0)) + : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)) : (nestedUpdateCount = 0); - "function" === typeof onCommitFiberRoot && - onCommitFiberRoot(finishedWork.stateNode, expirationTime); - ensureRootIsScheduled(root$jscomp$0); + finishedWork = finishedWork.stateNode; + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + injectedHook.onCommitFiberRoot( + rendererID, + finishedWork, + void 0, + 64 === (finishedWork.current.flags & 64) + ); + } catch (err) {} + ensureRootIsScheduled(root, now()); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root$jscomp$0 = firstUncaughtError), + (root = firstUncaughtError), (firstUncaughtError = null), - root$jscomp$0); - if ((executionContext & LegacyUnbatchedContext) !== NoContext) return null; + root); + if (0 !== (executionContext & 8)) return null; flushSyncCallbackQueue(); return null; } function commitBeforeMutationEffects() { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect); - 0 === (effectTag & 512) || + var current = nextEffect.alternate; + shouldFireAfterActiveInstanceBlur || + null === focusedInstanceHandle || + (0 !== (nextEffect.flags & 8) + ? doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0) + : 13 === nextEffect.tag && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0)); + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6541,45 +6812,81 @@ function flushPassiveEffects() { pendingPassiveEffectsRenderPriority = 90; return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } + return !1; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); } function flushPassiveEffectsImpl() { if (null === rootWithPendingPassiveEffects) return !1; var root = rootWithPendingPassiveEffects; rootWithPendingPassiveEffects = null; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; - executionContext |= CommitContext; - for (root = root.current.firstEffect; null !== root; ) { + executionContext |= 32; + var unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + for (var i = 0; i < unmountEffects.length; i += 2) { + var effect$94 = unmountEffects[i], + fiber = unmountEffects[i + 1], + destroy = effect$94.destroy; + effect$94.destroy = void 0; + if ("function" === typeof destroy) + try { + destroy(); + } catch (error) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error); + } + } + unmountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; + for (i = 0; i < unmountEffects.length; i += 2) { + effect$94 = unmountEffects[i]; + fiber = unmountEffects[i + 1]; try { - var finishedWork = root; - if (0 !== (finishedWork.effectTag & 512)) - switch (finishedWork.tag) { - case 0: - case 11: - case 15: - case 22: - commitHookEffectListUnmount(5, finishedWork), - commitHookEffectListMount(5, finishedWork); - } - } catch (error) { - if (null === root) throw Error("Should be working on an effect."); - captureCommitPhaseError(root, error); + var create$98 = effect$94.create; + effect$94.destroy = create$98(); + } catch (error$99) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error$99); } - finishedWork = root.nextEffect; - root.nextEffect = null; - root = finishedWork; } + for (create$98 = root.current.firstEffect; null !== create$98; ) + (root = create$98.nextEffect), + (create$98.nextEffect = null), + create$98.flags & 8 && + ((create$98.sibling = null), (create$98.stateNode = null)), + (create$98 = root); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; } function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1073741823); + sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1); enqueueUpdate(rootFiber, sourceFiber); - rootFiber = markUpdateTimeFromFiberToRoot(rootFiber, 1073741823); - null !== rootFiber && ensureRootIsScheduled(rootFiber); + sourceFiber = requestEventTime(); + rootFiber = markUpdateLaneFromFiberToRoot(rootFiber, 1); + null !== rootFiber && + (markRootUpdated(rootFiber, 1, sourceFiber), + ensureRootIsScheduled(rootFiber, sourceFiber)); } function captureCommitPhaseError(sourceFiber, error) { if (3 === sourceFiber.tag) @@ -6598,145 +6905,166 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1073741823); - enqueueUpdate(fiber, sourceFiber); - fiber = markUpdateTimeFromFiberToRoot(fiber, 1073741823); - null !== fiber && ensureRootIsScheduled(fiber); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); + fiber = markUpdateLaneFromFiberToRoot(fiber, 1); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { +function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; - null !== pingCache && pingCache.delete(thenable); - workInProgressRoot === root && renderExpirationTime$1 === suspendedTime - ? workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ? prepareFreshStack(root, renderExpirationTime$1) - : (workInProgressRootHasPendingPing = !0) - : isRootSuspendedAtTime(root, suspendedTime) && - ((thenable = root.lastPingedTime), - (0 !== thenable && thenable < suspendedTime) || - ((root.lastPingedTime = suspendedTime), ensureRootIsScheduled(root))); -} -function resolveRetryThenable(boundaryFiber, thenable) { + null !== pingCache && pingCache.delete(wakeable); + wakeable = requestEventTime(); + root.pingedLanes |= root.suspendedLanes & pingedLanes; + workInProgressRoot === root && + (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && + (4 === workInProgressRootExitStatus || + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 62914560) === + workInProgressRootRenderLanes && + 500 > now() - globalMostRecentFallbackTime) + ? prepareFreshStack(root, 0) + : (workInProgressRootPingedLanes |= pingedLanes)); + ensureRootIsScheduled(root, wakeable); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(thenable); - thenable = 0; - 0 === thenable && - ((thenable = requestCurrentTimeForUpdate()), - (thenable = computeExpirationForFiber(thenable, boundaryFiber, null))); - boundaryFiber = markUpdateTimeFromFiberToRoot(boundaryFiber, thenable); - null !== boundaryFiber && ensureRootIsScheduled(boundaryFiber); + null !== retryCache && retryCache.delete(wakeable); + wakeable = 0; + 0 === wakeable && + ((wakeable = boundaryFiber.mode), + 0 === (wakeable & 2) + ? (wakeable = 1) + : 0 === (wakeable & 4) + ? (wakeable = 99 === getCurrentPriorityLevel() ? 1 : 2) + : (0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes), + (wakeable = getHighestPriorityLane(62914560 & ~currentEventWipLanes)), + 0 === wakeable && (wakeable = 4194304))); + retryCache = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); + null !== boundaryFiber && + (markRootUpdated(boundaryFiber, wakeable, retryCache), + ensureRootIsScheduled(boundaryFiber, retryCache)); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +beginWork$1 = function(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || didPerformWorkStackCursor.current ) didReceiveUpdate = !0; + else if (0 !== (renderLanes & updateLanes)) + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { - if (updateExpirationTime < renderExpirationTime) { - didReceiveUpdate = !1; - switch (workInProgress.tag) { - case 3: - pushHostRootContext(workInProgress); - break; - case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer( + didReceiveUpdate = !1; + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; + case 10: + updateLanes = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + push(valueCursor, context._currentValue); + context._currentValue = updateLanes; + break; + case 13: + if (null !== workInProgress.memoizedState) { + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + workInProgress = bailoutOnAlreadyFinishedWork( + current, workInProgress, - workInProgress.stateNode.containerInfo + renderLanes ); - break; - case 10: - updateExpirationTime = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - push(valueCursor, context._currentValue); - context._currentValue = updateExpirationTime; - break; - case 13: - if (null !== workInProgress.memoizedState) { - updateExpirationTime = workInProgress.child.childExpirationTime; - if ( - 0 !== updateExpirationTime && - updateExpirationTime >= renderExpirationTime - ) - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - workInProgress = bailoutOnAlreadyFinishedWork( + return null !== workInProgress ? workInProgress.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + updateLanes = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 64)) { + if (updateLanes) + return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); - return null !== workInProgress ? workInProgress.sibling : null; - } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - updateExpirationTime = - workInProgress.childExpirationTime >= renderExpirationTime; - if (0 !== (current.effectTag & 64)) { - if (updateExpirationTime) - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 64; - } - context = workInProgress.memoizedState; - null !== context && - ((context.rendering = null), (context.tail = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (!updateExpirationTime) return null; - } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + workInProgress.flags |= 64; + } + context = workInProgress.memoizedState; + null !== context && + ((context.rendering = null), + (context.tail = null), + (context.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (updateLanes) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); } - didReceiveUpdate = !1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else didReceiveUpdate = !1; - workInProgress.expirationTime = 0; + workInProgress.lanes = 0; switch (workInProgress.tag) { case 2: - updateExpirationTime = workInProgress.type; + updateLanes = workInProgress.type; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); context = renderWithHooks( null, workInProgress, - updateExpirationTime, + updateLanes, current, context, - renderExpirationTime + renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -6746,7 +7074,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress.tag = 1; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - if (isContextProvider(updateExpirationTime)) { + if (isContextProvider(updateLanes)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; @@ -6755,53 +7083,41 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ? context.state : null; initializeUpdateQueue(workInProgress); - var getDerivedStateFromProps = - updateExpirationTime.getDerivedStateFromProps; + var getDerivedStateFromProps = updateLanes.getDerivedStateFromProps; "function" === typeof getDerivedStateFromProps && applyDerivedStateFromProps( workInProgress, - updateExpirationTime, + updateLanes, getDerivedStateFromProps, current ); context.updater = classComponentUpdater; workInProgress.stateNode = context; - context._reactInternalFiber = workInProgress; - mountClassInstance( - workInProgress, - updateExpirationTime, - current, - renderExpirationTime - ); + context._reactInternals = workInProgress; + mountClassInstance(workInProgress, updateLanes, current, renderLanes); workInProgress = finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, hasContext, - renderExpirationTime + renderLanes ); } else (workInProgress.tag = 0), - reconcileChildren( - null, - workInProgress, - context, - renderExpirationTime - ), + reconcileChildren(null, workInProgress, context, renderLanes), (workInProgress = workInProgress.child); return workInProgress; case 16: + context = workInProgress.elementType; a: { - context = workInProgress.elementType; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; - initializeLazyComponentType(context); - if (1 !== context._status) throw context._result; - context = context._result; + hasContext = context._init; + context = hasContext(context._payload); workInProgress.type = context; hasContext = workInProgress.tag = resolveLazyComponentTag(context); current = resolveDefaultProps(context, current); @@ -6812,7 +7128,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 1: @@ -6821,7 +7137,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 11: @@ -6830,7 +7146,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 14: @@ -6839,8 +7155,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, resolveDefaultProps(context.type, current), - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); break a; } @@ -6853,126 +7169,106 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return workInProgress; case 0: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateFunctionComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 1: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateClassComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 3: pushHostRootContext(workInProgress); - updateExpirationTime = workInProgress.updateQueue; - if (null === current || null === updateExpirationTime) + updateLanes = workInProgress.updateQueue; + if (null === current || null === updateLanes) throw Error( "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue." ); - updateExpirationTime = workInProgress.pendingProps; + updateLanes = workInProgress.pendingProps; context = workInProgress.memoizedState; context = null !== context ? context.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue( - workInProgress, - updateExpirationTime, - null, - renderExpirationTime - ); - updateExpirationTime = workInProgress.memoizedState.element; - updateExpirationTime === context + processUpdateQueue(workInProgress, updateLanes, null, renderLanes); + updateLanes = workInProgress.memoizedState.element; + updateLanes === context ? (workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes )) - : (reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + : (reconcileChildren(current, workInProgress, updateLanes, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; case 5: return ( pushHostContext(workInProgress), - (updateExpirationTime = workInProgress.pendingProps.children), + (updateLanes = workInProgress.pendingProps.children), markRef(current, workInProgress), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), - (workInProgress = workInProgress.child), - workInProgress + reconcileChildren(current, workInProgress, updateLanes, renderLanes), + workInProgress.child ); case 6: return null; case 13: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case 4: return ( pushHostContainer( workInProgress, workInProgress.stateNode.containerInfo ), - (updateExpirationTime = workInProgress.pendingProps), + (updateLanes = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, null, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes )) : reconcileChildren( current, workInProgress, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ), workInProgress.child ); case 11: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateForwardRef( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 7: @@ -6981,7 +7277,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -6991,7 +7287,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -7001,13 +7297,13 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 10: a: { - updateExpirationTime = workInProgress.type._context; + updateLanes = workInProgress.type._context; context = workInProgress.pendingProps; getDerivedStateFromProps = workInProgress.memoizedProps; hasContext = context.value; @@ -7019,9 +7315,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ((context$jscomp$0 = getDerivedStateFromProps.value), (hasContext = objectIs(context$jscomp$0, hasContext) ? 0 - : ("function" === - typeof updateExpirationTime._calculateChangedBits - ? updateExpirationTime._calculateChangedBits( + : ("function" === typeof updateLanes._calculateChangedBits + ? updateLanes._calculateChangedBits( context$jscomp$0, hasContext ) @@ -7035,7 +7330,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); break a; } @@ -7056,25 +7351,24 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ) { if ( - dependency.context === updateExpirationTime && + dependency.context === updateLanes && 0 !== (dependency.observedBits & hasContext) ) { 1 === context$jscomp$0.tag && - ((dependency = createUpdate(renderExpirationTime, null)), + ((dependency = createUpdate( + -1, + renderLanes & -renderLanes + )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); - context$jscomp$0.expirationTime < renderExpirationTime && - (context$jscomp$0.expirationTime = renderExpirationTime); + context$jscomp$0.lanes |= renderLanes; dependency = context$jscomp$0.alternate; - null !== dependency && - dependency.expirationTime < renderExpirationTime && - (dependency.expirationTime = renderExpirationTime); + null !== dependency && (dependency.lanes |= renderLanes); scheduleWorkOnParentPath( context$jscomp$0.return, - renderExpirationTime + renderLanes ); - list.expirationTime < renderExpirationTime && - (list.expirationTime = renderExpirationTime); + list.lanes |= renderLanes; break; } dependency = dependency.next; @@ -7112,7 +7406,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, context.children, - renderExpirationTime + renderLanes ); workInProgress = workInProgress.child; } @@ -7121,17 +7415,12 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return ( (context = workInProgress.type), (hasContext = workInProgress.pendingProps), - (updateExpirationTime = hasContext.children), - prepareToReadContext(workInProgress, renderExpirationTime), + (updateLanes = hasContext.children), + prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), - (updateExpirationTime = updateExpirationTime(context)), - (workInProgress.effectTag |= 1), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + (updateLanes = updateLanes(context)), + (workInProgress.flags |= 1), + reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); case 14: @@ -7147,8 +7436,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, hasContext, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); case 15: @@ -7157,48 +7446,43 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); case 17: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), - isContextProvider(updateExpirationTime) + isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) : (current = !1), - prepareToReadContext(workInProgress, renderExpirationTime), - constructClassInstance(workInProgress, updateExpirationTime, context), - mountClassInstance( - workInProgress, - updateExpirationTime, - context, - renderExpirationTime - ), + prepareToReadContext(workInProgress, renderLanes), + constructClassInstance(workInProgress, updateLanes, context), + mountClassInstance(workInProgress, updateLanes, context, renderLanes), finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, current, - renderExpirationTime + renderLanes ) ); case 19: - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + case 22: + return updateOffscreenComponent(current, workInProgress, renderLanes); + case 23: + return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( "Unknown unit of work tag (" + @@ -7206,32 +7490,6 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { "). This error is likely caused by a bug in React. Please file an issue." ); }; -var onCommitFiberRoot = null, - onCommitFiberUnmount = null; -function injectInternals(internals) { - if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled || !hook.supportsFiber) return !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = function(root) { - try { - hook.onCommitFiberRoot( - rendererID, - root, - void 0, - 64 === (root.current.effectTag & 64) - ); - } catch (err) {} - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) {} - }; - } catch (err) {} - return !0; -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -7241,11 +7499,14 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; - this.childExpirationTime = this.expirationTime = 0; + this.childLanes = this.lanes = 0; this.alternate = null; } +function createFiber(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); +} function shouldConstruct(Component) { Component = Component.prototype; return !(!Component || !Component.isReactComponent); @@ -7263,7 +7524,7 @@ function resolveLazyComponentTag(Component) { function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress - ? ((workInProgress = new FiberNode( + ? ((workInProgress = createFiber( current.tag, pendingProps, current.key, @@ -7275,12 +7536,13 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.alternate = current), (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), - (workInProgress.effectTag = 0), + (workInProgress.type = current.type), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null)); - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -7289,11 +7551,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.dependencies = null === pendingProps ? null - : { - expirationTime: pendingProps.expirationTime, - firstContext: pendingProps.firstContext, - responders: pendingProps.responders - }; + : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext }; workInProgress.sibling = current.sibling; workInProgress.index = current.index; workInProgress.ref = current.ref; @@ -7305,7 +7563,7 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { var fiberTag = 2; owner = type; @@ -7314,15 +7572,10 @@ function createFiberFromTypeAndProps( else a: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_CONCURRENT_MODE_TYPE: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = 8; - mode |= 7; + mode |= 16; break; case REACT_STRICT_MODE_TYPE: fiberTag = 8; @@ -7330,25 +7583,34 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: return ( - (type = new FiberNode(12, pendingProps, key, mode | 8)), + (type = createFiber(12, pendingProps, key, mode | 8)), (type.elementType = REACT_PROFILER_TYPE), (type.type = REACT_PROFILER_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_TYPE: return ( - (type = new FiberNode(13, pendingProps, key, mode)), + (type = createFiber(13, pendingProps, key, mode)), (type.type = REACT_SUSPENSE_TYPE), (type.elementType = REACT_SUSPENSE_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_LIST_TYPE: return ( - (type = new FiberNode(19, pendingProps, key, mode)), + (type = createFiber(19, pendingProps, key, mode)), (type.elementType = REACT_SUSPENSE_LIST_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), + type + ); + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + case REACT_LEGACY_HIDDEN_TYPE: + return ( + (type = createFiber(23, pendingProps, key, mode)), + (type.elementType = REACT_LEGACY_HIDDEN_TYPE), + (type.lanes = lanes), type ); default: @@ -7370,9 +7632,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7380,30 +7639,36 @@ function createFiberFromTypeAndProps( "." ); } - key = new FiberNode(fiberTag, pendingProps, key, mode); + key = createFiber(fiberTag, pendingProps, key, mode); key.elementType = type; key.type = owner; - key.expirationTime = expirationTime; + key.lanes = lanes; return key; } -function createFiberFromFragment(elements, mode, expirationTime, key) { - elements = new FiberNode(7, elements, key, mode); - elements.expirationTime = expirationTime; +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; return elements; } -function createFiberFromText(content, mode, expirationTime) { - content = new FiberNode(6, content, null, mode); - content.expirationTime = expirationTime; +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; return content; } -function createFiberFromPortal(portal, mode, expirationTime) { - mode = new FiberNode( +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( 4, null !== portal.children ? portal.children : [], portal.key, mode ); - mode.expirationTime = expirationTime; + mode.lanes = lanes; mode.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -7413,51 +7678,31 @@ function createFiberFromPortal(portal, mode, expirationTime) { } function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; - this.pingCache = this.pendingChildren = null; - this.finishedExpirationTime = 0; - this.finishedWork = null; + this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; this.timeoutHandle = -1; this.pendingContext = this.context = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = 90; - this.lastExpiredTime = this.lastPingedTime = this.nextKnownPendingLevel = this.lastSuspendedTime = this.firstSuspendedTime = this.firstPendingTime = 0; -} -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - root = root.lastSuspendedTime; - return ( - 0 !== firstSuspendedTime && - firstSuspendedTime >= expirationTime && - root <= expirationTime - ); + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; + this.entanglements = createLaneMap(0); } -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime, - lastSuspendedTime = root.lastSuspendedTime; - firstSuspendedTime < expirationTime && - (root.firstSuspendedTime = expirationTime); - if (lastSuspendedTime > expirationTime || 0 === firstSuspendedTime) - root.lastSuspendedTime = expirationTime; - expirationTime <= root.lastPingedTime && (root.lastPingedTime = 0); - expirationTime <= root.lastExpiredTime && (root.lastExpiredTime = 0); -} -function markRootUpdatedAtTime(root, expirationTime) { - expirationTime > root.firstPendingTime && - (root.firstPendingTime = expirationTime); - var firstSuspendedTime = root.firstSuspendedTime; - 0 !== firstSuspendedTime && - (expirationTime >= firstSuspendedTime - ? (root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = 0) - : expirationTime >= root.lastSuspendedTime && - (root.lastSuspendedTime = expirationTime + 1), - expirationTime > root.nextKnownPendingLevel && - (root.nextKnownPendingLevel = expirationTime)); +function createPortal(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } function findHostInstance(component) { - var fiber = component._reactInternalFiber; + var fiber = component._reactInternals; if (void 0 === fiber) { if ("function" === typeof component.render) throw Error("Unable to find node on an unmounted component."); @@ -7471,11 +7716,10 @@ function findHostInstance(component) { } function updateContainer(element, container, parentComponent, callback) { var current = container.current, - currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, current, suspenseConfig); + eventTime = requestEventTime(), + lane = requestUpdateLane(current); a: if (parentComponent) { - parentComponent = parentComponent._reactInternalFiber; + parentComponent = parentComponent._reactInternals; b: { if ( getNearestMountedFiber(parentComponent) !== parentComponent || @@ -7484,22 +7728,23 @@ function updateContainer(element, container, parentComponent, callback) { throw Error( "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." ); - var parentContext = parentComponent; + var JSCompiler_inline_result = parentComponent; do { - switch (parentContext.tag) { + switch (JSCompiler_inline_result.tag) { case 3: - parentContext = parentContext.stateNode.context; + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; break b; case 1: - if (isContextProvider(parentContext.type)) { - parentContext = - parentContext.stateNode + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode .__reactInternalMemoizedMergedChildContext; break b; } } - parentContext = parentContext.return; - } while (null !== parentContext); + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); throw Error( "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." ); @@ -7510,34 +7755,26 @@ function updateContainer(element, container, parentComponent, callback) { parentComponent = processChildContext( parentComponent, Component, - parentContext + JSCompiler_inline_result ); break a; } } - parentComponent = parentContext; + parentComponent = JSCompiler_inline_result; } else parentComponent = emptyContextObject; null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(currentTime, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); enqueueUpdate(current, container); - scheduleWork(current, currentTime); - return currentTime; + scheduleUpdateOnFiber(current, lane, eventTime); + return lane; } -function createPortal(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; +function emptyFindFiberByHostInstance() { + return null; } function findNodeHandle(componentOrHandle) { if (null == componentOrHandle) return null; @@ -7566,53 +7803,70 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - executionContext === NoContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; -var roots = new Map(); -(function(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: null, - overrideProps: null, - setSuspenseHandler: null, - scheduleUpdate: null, - currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - fiber = findCurrentHostFiber(fiber); - return null === fiber ? null : fiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - return findFiberByHostInstance ? findFiberByHostInstance(instance) : null; - }, - findHostInstancesForRefresh: null, - scheduleRefresh: null, - scheduleRoot: null, - setRefreshHandler: null, - getCurrentFiber: null - }); -})({ - findFiberByHostInstance: getInstanceFromTag, - bundleType: 0, - version: "16.13.0", - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: function() { - throw Error( - "getInspectorDataForViewTag() is not available in production" - ); - }, - getInspectorDataForViewAtPoint: function() { - throw Error( - "getInspectorDataForViewAtPoint() is not available in production." - ); - }.bind(null, findNodeHandle) - } -}); +var roots = new Map(), + devToolsConfig$jscomp$inline_908 = { + findFiberByHostInstance: getInstanceFromTag, + bundleType: 0, + version: "17.0.1-454c2211c", + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: function() { + throw Error( + "getInspectorDataForViewTag() is not available in production" + ); + }, + getInspectorDataForViewAtPoint: function() { + throw Error( + "getInspectorDataForViewAtPoint() is not available in production." + ); + }.bind(null, findNodeHandle) + } + }; +var internals$jscomp$inline_1115 = { + bundleType: devToolsConfig$jscomp$inline_908.bundleType, + version: devToolsConfig$jscomp$inline_908.version, + rendererPackageName: devToolsConfig$jscomp$inline_908.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_908.rendererConfig, + overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, + overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, + setSuspenseHandler: null, + scheduleUpdate: null, + currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, + findHostInstanceByFiber: function(fiber) { + fiber = findCurrentHostFiber(fiber); + return null === fiber ? null : fiber.stateNode; + }, + findFiberByHostInstance: + devToolsConfig$jscomp$inline_908.findFiberByHostInstance || + emptyFindFiberByHostInstance, + findHostInstancesForRefresh: null, + scheduleRefresh: null, + scheduleRoot: null, + setRefreshHandler: null, + getCurrentFiber: null +}; +if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { + var hook$jscomp$inline_1116 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if ( + !hook$jscomp$inline_1116.isDisabled && + hook$jscomp$inline_1116.supportsFiber + ) + try { + (rendererID = hook$jscomp$inline_1116.inject( + internals$jscomp$inline_1115 + )), + (injectedHook = hook$jscomp$inline_1116); + } catch (err) {} +} exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { computeComponentStackForErrorReporting: function(reactTag) { return (reactTag = getInstanceFromTag(reactTag)) @@ -7659,7 +7913,7 @@ exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { root = new FiberRootNode(containerTag, 0, !1); - var uninitializedFiber = new FiberNode(3, null, null, 0); + var uninitializedFiber = createFiber(3, null, null, 0); root.current = uninitializedFiber; uninitializedFiber.stateNode = root; initializeUpdateQueue(uninitializedFiber); diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js index 315906ade58741..7937b1e922259d 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js @@ -920,7 +920,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_232 = { +var injectedNamesToPlugins$jscomp$inline_226 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -955,34 +955,34 @@ var injectedNamesToPlugins$jscomp$inline_232 = { } } }, - isOrderingDirty$jscomp$inline_233 = !1, - pluginName$jscomp$inline_234; -for (pluginName$jscomp$inline_234 in injectedNamesToPlugins$jscomp$inline_232) + isOrderingDirty$jscomp$inline_227 = !1, + pluginName$jscomp$inline_228; +for (pluginName$jscomp$inline_228 in injectedNamesToPlugins$jscomp$inline_226) if ( - injectedNamesToPlugins$jscomp$inline_232.hasOwnProperty( - pluginName$jscomp$inline_234 + injectedNamesToPlugins$jscomp$inline_226.hasOwnProperty( + pluginName$jscomp$inline_228 ) ) { - var pluginModule$jscomp$inline_235 = - injectedNamesToPlugins$jscomp$inline_232[pluginName$jscomp$inline_234]; + var pluginModule$jscomp$inline_229 = + injectedNamesToPlugins$jscomp$inline_226[pluginName$jscomp$inline_228]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_234) || - namesToPlugins[pluginName$jscomp$inline_234] !== - pluginModule$jscomp$inline_235 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_228) || + namesToPlugins[pluginName$jscomp$inline_228] !== + pluginModule$jscomp$inline_229 ) { - if (namesToPlugins[pluginName$jscomp$inline_234]) + if (namesToPlugins[pluginName$jscomp$inline_228]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_234 + + pluginName$jscomp$inline_228 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_234 - ] = pluginModule$jscomp$inline_235; - isOrderingDirty$jscomp$inline_233 = !0; + pluginName$jscomp$inline_228 + ] = pluginModule$jscomp$inline_229; + isOrderingDirty$jscomp$inline_227 = !0; } } -isOrderingDirty$jscomp$inline_233 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_227 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1138,7 +1138,6 @@ var ReactSharedInternals = REACT_SUSPENSE_LIST_TYPE = 60120, REACT_MEMO_TYPE = 60115, REACT_LAZY_TYPE = 60116, - REACT_BLOCK_TYPE = 60121, REACT_DEBUG_TRACING_MODE_TYPE = 60129, REACT_OFFSCREEN_TYPE = 60130, REACT_LEGACY_HIDDEN_TYPE = 60131; @@ -1156,7 +1155,6 @@ if ("function" === typeof Symbol && Symbol.for) { REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); REACT_MEMO_TYPE = symbolFor("react.memo"); REACT_LAZY_TYPE = symbolFor("react.lazy"); - REACT_BLOCK_TYPE = symbolFor("react.block"); symbolFor("react.scope"); REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); @@ -1203,8 +1201,6 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type._render); case REACT_LAZY_TYPE: innerType = type._payload; type = type._init; @@ -1222,7 +1218,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1739,7 +1735,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1779,31 +1775,27 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); Scheduler_now(); -var return_highestLanePriority = 10; +var return_highestLanePriority = 8; function getHighestPriorityLanes(lanes) { - if (0 !== (1 & lanes)) return (return_highestLanePriority = 17), 1; - if (0 !== (2 & lanes)) return (return_highestLanePriority = 16), 2; - if (0 !== (4 & lanes)) return (return_highestLanePriority = 15), 4; + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; var inputDiscreteLanes = 24 & lanes; - if (0 !== inputDiscreteLanes) - return (return_highestLanePriority = 14), inputDiscreteLanes; - if (0 !== (lanes & 32)) return (return_highestLanePriority = 13), 32; - inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 12), inputDiscreteLanes; - if (0 !== (lanes & 256)) return (return_highestLanePriority = 11), 256; - inputDiscreteLanes = 3584 & lanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 10), inputDiscreteLanes; - if (0 !== (lanes & 4096)) return (return_highestLanePriority = 9), 4096; - inputDiscreteLanes = 122880 & lanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 8), inputDiscreteLanes; - if (0 !== (lanes & 131072)) return (return_highestLanePriority = 7), 131072; - inputDiscreteLanes = 3932160 & lanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; if (0 !== inputDiscreteLanes) return (return_highestLanePriority = 6), inputDiscreteLanes; inputDiscreteLanes = 62914560 & lanes; @@ -1817,18 +1809,18 @@ function getHighestPriorityLanes(lanes) { return (return_highestLanePriority = 2), inputDiscreteLanes; if (0 !== (1073741824 & lanes)) return (return_highestLanePriority = 1), 1073741824; - return_highestLanePriority = 10; + return_highestLanePriority = 8; return lanes; } function schedulerPriorityToLanePriority(schedulerPriorityLevel) { switch (schedulerPriorityLevel) { case 99: - return 17; + return 15; case 98: - return 12; + return 10; case 97: case 96: - return 10; + return 8; case 95: return 2; default: @@ -1837,16 +1829,14 @@ function schedulerPriorityToLanePriority(schedulerPriorityLevel) { } function lanePriorityToSchedulerPriority(lanePriority) { switch (lanePriority) { - case 17: - case 16: - return 99; case 15: case 14: + return 99; case 13: case 12: - return 98; case 11: case 10: + return 98; case 9: case 8: case 7: @@ -1876,7 +1866,7 @@ function getNextLanes(root, wipLanes) { pingedLanes = root.pingedLanes; if (0 !== expiredLanes) (nextLanes = expiredLanes), - (nextLanePriority = return_highestLanePriority = 17); + (nextLanePriority = return_highestLanePriority = 15); else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; 0 !== nonIdleUnblockedLanes @@ -1915,42 +1905,31 @@ function getNextLanes(root, wipLanes) { (wipLanes &= ~nextLanePriority); return nextLanes; } -function getMostRecentEventTime(root, lanes) { - root = root.eventTimes; - for (var mostRecentEventTime = -1; 0 < lanes; ) { - var index$6 = 31 - clz32(lanes), - lane = 1 << index$6; - index$6 = root[index$6]; - index$6 > mostRecentEventTime && (mostRecentEventTime = index$6); - lanes &= ~lane; - } - return mostRecentEventTime; -} function getLanesToRetrySynchronouslyOnError(root) { root = root.pendingLanes & -1073741825; return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; } function findUpdateLane(lanePriority, wipLanes) { switch (lanePriority) { - case 17: + case 15: return 1; - case 16: - return 2; case 14: + return 2; + case 12: return ( (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(12, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority ); - case 12: + case 10: return ( (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), - 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority ); - case 10: + case 8: return ( (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), 0 === lanePriority && - ((lanePriority = getHighestPriorityLane(4055040 & ~wipLanes)), + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), 0 === lanePriority && (lanePriority = 512)), lanePriority ); @@ -1968,8 +1947,9 @@ function findUpdateLane(lanePriority, wipLanes) { function getHighestPriorityLane(lanes) { return lanes & -lanes; } -function pickArbitraryLane(lanes) { - return lanes & -lanes; +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; } function markRootUpdated(root, updateLane, eventTime) { root.pendingLanes |= updateLane; @@ -2004,7 +1984,7 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); var fakeCallbackNode = {}, requestPaint = @@ -2093,6 +2073,32 @@ function flushSyncCallbackQueueImpl() { } } } +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; +function is(x, y) { + return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); +} +var objectIs = "function" === typeof Object.is ? Object.is : is, + hasOwnProperty = Object.prototype.hasOwnProperty; +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) return !0; + if ( + "object" !== typeof objA || + null === objA || + "object" !== typeof objB || + null === objB + ) + return !1; + var keysA = Object.keys(objA), + keysB = Object.keys(objB); + if (keysA.length !== keysB.length) return !1; + for (keysB = 0; keysB < keysA.length; keysB++) + if ( + !hasOwnProperty.call(objB, keysA[keysB]) || + !objectIs(objA[keysA[keysB]], objB[keysA[keysB]]) + ) + return !1; + return !0; +} function describeFiber(fiber) { switch (fiber.tag) { case 5: @@ -2109,8 +2115,6 @@ function describeFiber(fiber) { return describeFunctionComponentFrame(fiber.type, null); case 11: return describeFunctionComponentFrame(fiber.type.render, null); - case 22: - return describeFunctionComponentFrame(fiber.type._render, null); case 1: return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; default: @@ -2129,31 +2133,6 @@ function getStackByFiberInDevAndProd(workInProgress) { return "\nError generating stack: " + x.message + "\n" + x.stack; } } -function is(x, y) { - return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); -} -var objectIs = "function" === typeof Object.is ? Object.is : is, - hasOwnProperty = Object.prototype.hasOwnProperty; -function shallowEqual(objA, objB) { - if (objectIs(objA, objB)) return !0; - if ( - "object" !== typeof objA || - null === objA || - "object" !== typeof objB || - null === objB - ) - return !1; - var keysA = Object.keys(objA), - keysB = Object.keys(objB); - if (keysA.length !== keysB.length) return !1; - for (keysB = 0; keysB < keysA.length; keysB++) - if ( - !hasOwnProperty.call(objB, keysA[keysB]) || - !objectIs(objA[keysA[keysB]], objB[keysA[keysB]]) - ) - return !1; - return !0; -} function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { baseProps = Object.assign({}, baseProps); @@ -2247,11 +2226,10 @@ function cloneUpdateQueue(current, workInProgress) { effects: current.effects }); } -function createUpdate(eventTime, lane, suspenseConfig) { +function createUpdate(eventTime, lane) { return { eventTime: eventTime, lane: lane, - suspenseConfig: suspenseConfig, tag: 0, payload: null, callback: null, @@ -2284,7 +2262,6 @@ function enqueueCapturedUpdate(workInProgress, capturedUpdate) { var clone = { eventTime: queue.eventTime, lane: queue.lane, - suspenseConfig: queue.suspenseConfig, tag: queue.tag, payload: queue.payload, callback: queue.callback, @@ -2358,16 +2335,11 @@ function processUpdateQueue( (current = current.next = { eventTime: updateEventTime, lane: 0, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, next: null }); - markRenderEventTimeAndConfig( - updateEventTime, - firstBaseUpdate.suspenseConfig - ); a: { var workInProgress = workInProgress$jscomp$0, update = firstBaseUpdate; @@ -2387,8 +2359,7 @@ function processUpdateQueue( currentLastBaseUpdate = workInProgress; break a; case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; + workInProgress.flags = (workInProgress.flags & -8193) | 64; case 0: workInProgress = update.payload; pendingQueue = @@ -2411,7 +2382,7 @@ function processUpdateQueue( } } null !== firstBaseUpdate.callback && - ((workInProgress$jscomp$0.effectTag |= 32), + ((workInProgress$jscomp$0.flags |= 32), (pendingQueue = queue.effects), null === pendingQueue ? (queue.effects = [firstBaseUpdate]) @@ -2420,7 +2391,6 @@ function processUpdateQueue( (updateEventTime = { eventTime: updateEventTime, lane: pendingQueue, - suspenseConfig: firstBaseUpdate.suspenseConfig, tag: firstBaseUpdate.tag, payload: firstBaseUpdate.payload, callback: firstBaseUpdate.callback, @@ -2472,8 +2442,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2499,41 +2468,32 @@ var classComponentUpdater = { enqueueSetState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { inst = inst._reactInternals; var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(inst, suspenseConfig); - suspenseConfig = createUpdate(eventTime, lane, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); scheduleUpdateOnFiber(inst, lane, eventTime); } }; @@ -2626,7 +2586,7 @@ function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2641,7 +2601,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2675,7 +2635,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2699,7 +2659,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2731,16 +2691,16 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } function updateTextNode(returnFiber, current, textContent, lanes) { @@ -3275,11 +3235,12 @@ function ChildReconciler(shouldTrackSideEffects) { switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3339,7 +3300,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim() || shim())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3371,7 +3332,7 @@ var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3496,40 +3457,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var suspenseConfig = update.suspenseConfig, - updateLane = update.lane, - updateEventTime = update.eventTime; - (renderLanes & updateLane) === updateLane - ? (null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - eventTime: updateEventTime, - lane: 0, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }), - markRenderEventTimeAndConfig(updateEventTime, suspenseConfig), - (current = - update.eagerReducer === reducer - ? update.eagerState - : reducer(current, update.action))) - : ((suspenseConfig = { - eventTime: updateEventTime, - lane: updateLane, - suspenseConfig: suspenseConfig, + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) + null !== newBaseQueueLast && + (newBaseQueueLast = newBaseQueueLast.next = { + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = suspenseConfig), - (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = suspenseConfig), - (currentlyRenderingFiber$1.lanes |= updateLane), - (workInProgressRootSkippedLanes |= updateLane)); + (current = + update.eagerReducer === reducer + ? update.eagerState + : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3614,10 +3569,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { maybeNewVersion = getSnapshot(source._source); objectIs(snapshot, maybeNewVersion) || (setSnapshot(maybeNewVersion), - (maybeNewVersion = requestUpdateLane( - fiber, - ReactCurrentBatchConfig.suspense - )), + (maybeNewVersion = requestUpdateLane(fiber)), (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); maybeNewVersion = root.mutableReadLanes; root.entangledLanes |= maybeNewVersion; @@ -3626,9 +3578,9 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { 0 < lanes; ) { - var index$14 = 31 - clz32(lanes), - lane = 1 << index$14; - entanglements[index$14] |= maybeNewVersion; + var index$13 = 31 - clz32(lanes), + lane = 1 << index$13; + entanglements[index$13] |= maybeNewVersion; lanes &= ~lane; } } @@ -3642,7 +3594,7 @@ function useMutableSource(hook, source, getSnapshot, subscribe) { latestSetSnapshot = refs.setSnapshot; try { latestSetSnapshot(latestGetSnapshot(source._source)); - var lane = requestUpdateLane(fiber, ReactCurrentBatchConfig.suspense); + var lane = requestUpdateLane(fiber); root.mutableReadLanes |= lane & root.pendingLanes; } catch (error) { latestSetSnapshot(function() { @@ -3713,17 +3665,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3731,12 +3683,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3775,13 +3727,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3809,39 +3754,36 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { var eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(fiber, suspenseConfig); - suspenseConfig = { - eventTime: eventTime, - lane: lane, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || @@ -3857,8 +3799,8 @@ function dispatchAction(fiber, queue, action) { try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { @@ -3886,7 +3828,13 @@ var ContextOnlyDispatcher = { }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3932,36 +3880,30 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; }, useMutableSource: function(source, getSnapshot, subscribe) { var hook = mountWorkInProgressHook(); @@ -3991,36 +3933,27 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4042,36 +3975,27 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, useMutableSource: updateMutableSource, useOpaqueIdentifier: function() { @@ -4128,11 +4052,11 @@ function updateForwardRef( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } @@ -4169,7 +4093,7 @@ function updateMemoComponent( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, renderLanes ); @@ -4186,7 +4110,7 @@ function updateMemoComponent( Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -4206,7 +4130,7 @@ function updateSimpleMemoComponent( current.ref === workInProgress.ref ) if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) - 0 !== (current.effectTag & 16384) && (didReceiveUpdate = !0); + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); else return ( (workInProgress.lanes = current.lanes), @@ -4241,9 +4165,7 @@ function updateOffscreenComponent(current, workInProgress, renderLanes) { return ( (current = null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [1073741824]) - : spawnedWorkDuringRender.push(1073741824), + markSpawnedWork(1073741824), (workInProgress.lanes = workInProgress.childLanes = 1073741824), (workInProgress.memoizedState = { baseLanes: current }), pushRenderLanes(workInProgress, current), @@ -4264,7 +4186,7 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, @@ -4289,11 +4211,11 @@ function updateFunctionComponent( if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), + (workInProgress.flags &= -517), (current.lanes &= ~renderLanes), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } @@ -4313,7 +4235,7 @@ function updateClassComponent( null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); @@ -4379,9 +4301,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -4389,7 +4311,7 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); } else { instance = workInProgress.stateNode; @@ -4462,17 +4384,17 @@ function updateClassComponent( oldContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) + (workInProgress.flags |= 256)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = newState)), (instance.props = nextProps), @@ -4482,11 +4404,11 @@ function updateClassComponent( : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), "function" !== typeof instance.getSnapshotBeforeUpdate || (oldProps === current.memoizedProps && oldState === current.memoizedState) || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), (nextProps = !1)); } return finishClassComponent( @@ -4507,7 +4429,7 @@ function finishClassComponent( renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), @@ -4522,7 +4444,7 @@ function finishClassComponent( var nextChildren = null; profilerStartTime = -1; } else nextChildren = shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((didCaptureError = nextChildren), (workInProgress.child = reconcileChildFibers( @@ -4560,55 +4482,49 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { suspenseContext = suspenseStackCursor.current, showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = null !== current && null === current.memoizedState ? !1 : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((showFallback = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { + current = nextProps.children; + suspenseContext = nextProps.fallback; if (showFallback) return ( - (current = nextProps.fallback), - (suspenseContext = workInProgress.mode), - (showFallback = workInProgress.child), - (nextProps = { mode: "hidden", children: nextProps.children }), - 0 === (suspenseContext & 2) && null !== showFallback - ? ((showFallback.childLanes = 0), - (showFallback.pendingProps = nextProps), - workInProgress.mode & 8 && - ((showFallback.actualDuration = 0), - (showFallback.actualStartTime = -1), - (showFallback.selfBaseDuration = 0), - (showFallback.treeBaseDuration = 0))) - : (showFallback = createFiberFromOffscreen( - nextProps, - suspenseContext, - 0, - null - )), - (current = createFiberFromFragment( + (current = mountSuspenseFallbackChildren( + workInProgress, current, suspenseContext, - renderLanes, - null + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current + ); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes )), - (showFallback.return = workInProgress), - (current.return = workInProgress), - (showFallback.sibling = current), - (workInProgress.child = showFallback), (workInProgress.child.memoizedState = { baseLanes: renderLanes }), (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432), current ); renderLanes = createFiberFromOffscreen( - { mode: "visible", children: nextProps.children }, + { mode: "visible", children: current }, workInProgress.mode, renderLanes, null @@ -4626,13 +4542,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4654,13 +4570,13 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { nextProps.fallback, renderLanes )), - (suspenseContext = workInProgress.child), - (showFallback = current.child.memoizedState), - (suspenseContext.memoizedState = - null === showFallback + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext ? { baseLanes: renderLanes } - : { baseLanes: showFallback.baseLanes | renderLanes }), - (suspenseContext.childLanes = current.childLanes & ~renderLanes), + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), (workInProgress.memoizedState = SUSPENDED_MARKER), nextProps ); @@ -4673,6 +4589,41 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { workInProgress.memoizedState = null; return renderLanes; } +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren), + workInProgress.mode & 8 && + ((progressedPrimaryFragment.actualDuration = 0), + (progressedPrimaryFragment.actualStartTime = -1), + (progressedPrimaryFragment.selfBaseDuration = 0), + (progressedPrimaryFragment.treeBaseDuration = 0))) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} function updateSuspensePrimaryChildren( current, workInProgress, @@ -4690,7 +4641,7 @@ function updateSuspensePrimaryChildren( primaryChildren.sibling = null; null !== current && ((current.nextEffect = null), - (current.effectTag = 8), + (current.flags = 8), (workInProgress.firstEffect = workInProgress.lastEffect = current)); return (workInProgress.child = primaryChildren); } @@ -4734,7 +4685,7 @@ function updateSuspenseFallbackChildren( renderLanes, null )), - (fallbackChildren.effectTag |= 2)); + (fallbackChildren.flags |= 2)); fallbackChildren.return = workInProgress; primaryChildren.return = workInProgress; primaryChildren.sibling = fallbackChildren; @@ -4763,7 +4714,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4772,7 +4722,6 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } @@ -4783,9 +4732,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && @@ -4921,10 +4870,10 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { current.memoizedProps !== newProps && (requiredContext(contextStackCursor$1.current), (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); }; updateHostText$1 = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.effectTag |= 4); + oldText !== newText && (workInProgress.flags |= 4); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { @@ -4978,7 +4927,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.pendingContext = null)), (null !== current && null !== current.child) || newProps.hydrate || - (workInProgress.effectTag |= 256), + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4996,8 +4945,7 @@ function completeWork(current, workInProgress, renderLanes) { newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -5031,8 +4979,8 @@ function completeWork(current, workInProgress, renderLanes) { appendAllChildren(rootContainerInstance, workInProgress, !1, !1); workInProgress.stateNode = rootContainerInstance; finalizeInitialChildren(rootContainerInstance) && - (workInProgress.effectTag |= 4); - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -5067,7 +5015,7 @@ function completeWork(current, workInProgress, renderLanes) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return ( (workInProgress.lanes = renderLanes), 0 !== (workInProgress.mode & 8) && @@ -5100,7 +5048,7 @@ function completeWork(current, workInProgress, renderLanes) { workInProgressRootRenderLanes ); } - if (newProps || rootContainerInstance) workInProgress.effectTag |= 4; + if (newProps || rootContainerInstance) workInProgress.flags |= 4; return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -5112,24 +5060,24 @@ function completeWork(current, workInProgress, renderLanes) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( 0 !== workInProgressRootExitStatus || - (null !== current && 0 !== (current.effectTag & 64)) + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; @@ -5137,7 +5085,7 @@ function completeWork(current, workInProgress, renderLanes) { for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (updatePayload = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), @@ -5185,6 +5133,13 @@ function completeWork(current, workInProgress, renderLanes) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); } else { if (!rootContainerInstance) @@ -5192,12 +5147,12 @@ function completeWork(current, workInProgress, renderLanes) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -5210,15 +5165,14 @@ function completeWork(current, workInProgress, renderLanes) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && 1073741824 !== renderLanes && - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (workInProgress.lanes = renderLanes), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [renderLanes]) - : spawnedWorkDuringRender.push(renderLanes)); + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -5229,9 +5183,7 @@ function completeWork(current, workInProgress, renderLanes) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -5246,15 +5198,15 @@ function completeWork(current, workInProgress, renderLanes) { ), current) : null; + case 22: case 23: - case 24: return ( popRenderLanes(), null !== current && (null !== current.memoizedState) !== (null !== workInProgress.memoizedState) && "unstable-defer-without-hiding" !== newProps.mode && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), null ); } @@ -5268,9 +5220,9 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), 0 !== (workInProgress.mode & 8) && transferActualDuration(workInProgress), workInProgress) @@ -5280,21 +5232,21 @@ function unwindWork(workInProgress) { pop(didPerformWorkStackCursor); pop(contextStackCursor); resetWorkInProgressVersions(); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), 0 !== (workInProgress.mode & 8) && transferActualDuration(workInProgress), workInProgress) @@ -5306,8 +5258,8 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: case 23: - case 24: return popRenderLanes(), null; default: return null; @@ -5344,7 +5296,7 @@ function logCapturedError(boundary, errorInfo) { } var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; lane.payload = { element: null }; var error = errorInfo.value; @@ -5355,7 +5307,7 @@ function createRootErrorUpdate(fiber, errorInfo, lane) { return lane; } function createClassErrorUpdate(fiber, errorInfo, lane) { - lane = createUpdate(-1, lane, null); + lane = createUpdate(-1, lane); lane.tag = 3; var getDerivedStateFromError = fiber.type.getDerivedStateFromError; if ("function" === typeof getDerivedStateFromError) { @@ -5398,10 +5350,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5431,7 +5382,6 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 0: case 11: case 15: - case 22: current = finishedWork.updateQueue; current = null !== current ? current.lastEffect : null; if (null !== current) { @@ -5462,7 +5412,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { return; case 1: finishedRoot = finishedWork.stateNode; - finishedWork.effectTag & 4 && + finishedWork.flags & 4 && (null === current ? finishedRoot.componentDidMount() : ((create$82 = @@ -5522,8 +5472,8 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: case 23: - case 24: return; } throw Error( @@ -5569,7 +5519,7 @@ function hideOrUnhideAllChildren(finishedWork, isHidden) { } else { if (6 === node.tag) throw Error("Not yet implemented."); if ( - ((23 !== node.tag && 24 !== node.tag) || + ((22 !== node.tag && 23 !== node.tag) || null === node.memoizedState || node === finishedWork) && null !== node.child @@ -5598,7 +5548,6 @@ function commitUnmount(finishedRoot, current) { case 11: case 14: case 15: - case 22: finishedRoot = current.updateQueue; if ( null !== finishedRoot && @@ -5687,7 +5636,7 @@ function commitPlacement(finishedWork) { "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." ); } - parentFiber.effectTag & 16 && (parentFiber.effectTag &= -17); + parentFiber.flags & 16 && (parentFiber.flags &= -17); a: b: for (parentFiber = finishedWork; ; ) { for (; null === parentFiber.sibling; ) { if (null === parentFiber.return || isHostParent(parentFiber.return)) { @@ -5702,13 +5651,13 @@ function commitPlacement(finishedWork) { 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { - if (parentFiber.effectTag & 2) continue b; + if (parentFiber.flags & 2) continue b; if (null === parentFiber.child || 4 === parentFiber.tag) continue b; else (parentFiber.child.return = parentFiber), (parentFiber = parentFiber.child); } - if (!(parentFiber.effectTag & 2)) { + if (!(parentFiber.flags & 2)) { parentFiber = parentFiber.stateNode; break a; } @@ -5917,7 +5866,6 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: var updateQueue = finishedWork.updateQueue; updateQueue = null !== updateQueue ? updateQueue.lastEffect : null; if (null !== updateQueue) { @@ -5983,8 +5931,8 @@ function commitWork(current, finishedWork) { return; case 17: return; + case 22: case 23: - case 24: hideOrUnhideAllChildren( finishedWork, null !== finishedWork.memoizedState @@ -6031,14 +5979,13 @@ var ceil = Math.ceil, subtreeRenderLanesCursor = createCursor(0), workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestSuspenseTimeout = -1, - workInProgressRootCanSuspendUsingConfig = null, workInProgressRootIncludedLanes = 0, workInProgressRootSkippedLanes = 0, workInProgressRootUpdatedLanes = 0, workInProgressRootPingedLanes = 0, mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -6065,46 +6012,33 @@ function requestEventTime() { ? currentEventTime : (currentEventTime = now()); } -function requestUpdateLane(fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; if (0 === (fiber & 2)) return 1; if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; 0 === currentEventWipLanes && (currentEventWipLanes = workInProgressRootIncludedLanes); - if (null !== suspenseConfig) { - suspenseConfig = suspenseConfig.timeoutMs; - fiber = void 0 === suspenseConfig || 1e4 > (suspenseConfig | 0) ? 8 : 6; + if (0 !== ReactCurrentBatchConfig.transition) { 0 !== currentEventPendingLanes && (currentEventPendingLanes = null !== mostRecentlyUpdatedRoot ? mostRecentlyUpdatedRoot.pendingLanes : 0); - suspenseConfig = currentEventWipLanes; - var pendingLanes = currentEventPendingLanes; - if (8 === fiber) - (fiber = pickArbitraryLane(122880 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(122880 & ~suspenseConfig)), - 0 === fiber && (fiber = 8192)), - (suspenseConfig = fiber); - else if (6 === fiber) - (fiber = pickArbitraryLane(3932160 & ~pendingLanes)), - 0 === fiber && - ((fiber = pickArbitraryLane(3932160 & ~suspenseConfig)), - 0 === fiber && (fiber = 262144)), - (suspenseConfig = fiber); - else - throw Error( - "Invalid transition priority: " + fiber + ". This is a bug in React." - ); - return suspenseConfig; + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; } - suspenseConfig = getCurrentPriorityLevel(); - 0 !== (executionContext & 4) && 98 === suspenseConfig - ? (suspenseConfig = findUpdateLane(14, currentEventWipLanes)) - : ((suspenseConfig = schedulerPriorityToLanePriority(suspenseConfig)), - (suspenseConfig = findUpdateLane(suspenseConfig, currentEventWipLanes))); - return suspenseConfig; + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; } function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) @@ -6126,7 +6060,9 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { ? (schedulePendingInteractions(fiber, lane), performSyncWorkOnRoot(fiber)) : (ensureRootIsScheduled(fiber, eventTime), schedulePendingInteractions(fiber, lane), - 0 === executionContext && flushSyncCallbackQueue()) + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) : (0 === (executionContext & 4) || (98 !== priorityLevel && 99 !== priorityLevel) || (null === rootsWithPendingDiscreteUpdates @@ -6168,8 +6104,8 @@ function ensureRootIsScheduled(root, currentTime) { getHighestPriorityLanes(lane); var priority = return_highestLanePriority; expirationTimes[index$7] = - 12 <= priority - ? expirationTime + 1e3 + 10 <= priority + ? expirationTime + 250 : 6 <= priority ? expirationTime + 5e3 : -1; @@ -6194,7 +6130,7 @@ function ensureRootIsScheduled(root, currentTime) { existingCallbackNode !== fakeCallbackNode && Scheduler_cancelCallback(existingCallbackNode); } - 17 === currentTime + 15 === currentTime ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), null === syncQueue ? ((syncQueue = [existingCallbackNode]), @@ -6204,7 +6140,7 @@ function ensureRootIsScheduled(root, currentTime) { ))) : syncQueue.push(existingCallbackNode), (existingCallbackNode = fakeCallbackNode)) - : 16 === currentTime + : 14 === currentTime ? (existingCallbackNode = scheduleCallback( 99, performSyncWorkOnRoot.bind(null, root) @@ -6218,7 +6154,7 @@ function ensureRootIsScheduled(root, currentTime) { root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { +function performConcurrentWorkOnRoot(root) { currentEventTime = -1; currentEventPendingLanes = currentEventWipLanes = 0; if (0 !== (executionContext & 48)) @@ -6231,21 +6167,16 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root === workInProgressRoot ? workInProgressRootRenderLanes : 0 ); if (0 === lanes) return null; - if (didTimeout) - return ( - (root.expiredLanes |= lanes & root.pendingLanes), - ensureRootIsScheduled(root, now()), - null - ); var lanes$jscomp$0 = lanes; - didTimeout = executionContext; + var exitStatus = executionContext; executionContext |= 16; var prevDispatcher = pushDispatcher(); if ( workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes$jscomp$0 ) - prepareFreshStack(root, lanes$jscomp$0), + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, lanes$jscomp$0), startWorkOnPendingInteractions(root, lanes$jscomp$0); lanes$jscomp$0 = pushInteractions(root); do @@ -6259,21 +6190,21 @@ function performConcurrentWorkOnRoot(root, didTimeout) { resetContextDependencies(); tracing.__interactionsRef.current = lanes$jscomp$0; ReactCurrentDispatcher$2.current = prevDispatcher; - executionContext = didTimeout; + executionContext = exitStatus; null !== workInProgress - ? (didTimeout = 0) + ? (exitStatus = 0) : ((workInProgressRoot = null), (workInProgressRootRenderLanes = 0), - (didTimeout = workInProgressRootExitStatus)); + (exitStatus = workInProgressRootExitStatus)); if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) prepareFreshStack(root, 0); - else if (0 !== didTimeout) { - 2 === didTimeout && + else if (0 !== exitStatus) { + 2 === exitStatus && ((executionContext |= 64), root.hydrate && (root.hydrate = !1), (lanes = getLanesToRetrySynchronouslyOnError(root)), - 0 !== lanes && (didTimeout = renderRootSync(root, lanes))); - if (1 === didTimeout) + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((originalCallbackNode = workInProgressRootFatalError), prepareFreshStack(root, 0), markRootSuspended$1(root, lanes), @@ -6281,7 +6212,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { originalCallbackNode); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - switch (didTimeout) { + switch (exitStatus) { case 0: case 1: throw Error("Root did not complete. This is a bug in React."); @@ -6292,8 +6223,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) { markRootSuspended$1(root, lanes); if ( (lanes & 62914560) === lanes && - ((didTimeout = globalMostRecentFallbackTime + 500 - now()), - 10 < didTimeout) + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { if (0 !== getNextLanes(root, 0)) break; prevDispatcher = root.suspendedLanes; @@ -6304,7 +6235,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - didTimeout + exitStatus ); break; } @@ -6312,33 +6243,31 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; case 4: markRootSuspended$1(root, lanes); - if (0 !== getNextLanes(root, 0)) break; - didTimeout = root.suspendedLanes; - if ((didTimeout & lanes) !== lanes) { - requestEventTime(); - root.pingedLanes |= root.suspendedLanes & didTimeout; - break; + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevDispatcher = -1; 0 < lanes; ) { + var index$6 = 31 - clz32(lanes); + lanes$jscomp$0 = 1 << index$6; + index$6 = exitStatus[index$6]; + index$6 > prevDispatcher && (prevDispatcher = index$6); + lanes &= ~lanes$jscomp$0; } - lanes = getMostRecentEventTime(root, lanes); - -1 !== workInProgressRootLatestSuspenseTimeout - ? (lanes = workInProgressRootLatestSuspenseTimeout - now()) - : -1 === lanes - ? (lanes = 0) - : ((lanes = now() - lanes), - (lanes = - (120 > lanes - ? 120 - : 480 > lanes - ? 480 - : 1080 > lanes - ? 1080 - : 1920 > lanes - ? 1920 - : 3e3 > lanes - ? 3e3 - : 4320 > lanes - ? 4320 - : 1960 * ceil(lanes / 1960)) - lanes)); + lanes = prevDispatcher; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), @@ -6349,30 +6278,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) { commitRoot(root); break; case 5: - lanes$jscomp$0 = getMostRecentEventTime(root, lanes); - if ( - -1 !== lanes$jscomp$0 && - null !== workInProgressRootCanSuspendUsingConfig && - ((didTimeout = - workInProgressRootCanSuspendUsingConfig.busyMinDurationMs | 0), - 0 >= didTimeout - ? (didTimeout = 0) - : ((prevDispatcher = - workInProgressRootCanSuspendUsingConfig.busyDelayMs | 0), - (lanes$jscomp$0 = now() - lanes$jscomp$0), - (didTimeout = - lanes$jscomp$0 <= prevDispatcher - ? 0 - : prevDispatcher + didTimeout - lanes$jscomp$0)), - 10 < didTimeout) - ) { - markRootSuspended$1(root, lanes); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - didTimeout - ); - break; - } commitRoot(root); break; default: @@ -6390,9 +6295,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$12 = 31 - clz32(suspendedLanes), - lane = 1 << index$12; - root[index$12] = -1; + var index$11 = 31 - clz32(suspendedLanes), + lane = 1 << index$11; + root[index$11] = -1; suspendedLanes &= ~lane; } } @@ -6475,8 +6380,8 @@ function prepareFreshStack(root, lanes) { case 10: popProvider(interruptedWork); break; + case 22: case 23: - case 24: popRenderLanes(); } timeoutHandle = timeoutHandle.return; @@ -6486,8 +6391,6 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = -1; - workInProgressRootCanSuspendUsingConfig = null; workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; spawnedWorkDuringRender = null; } @@ -6527,7 +6430,7 @@ function handleError(root$jscomp$0, thrownValue) { sourceFiber = erroredWork, value = thrownValue; thrownValue = workInProgressRootRenderLanes; - sourceFiber.effectTag |= 2048; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && @@ -6573,13 +6476,13 @@ function handleError(root$jscomp$0, thrownValue) { workInProgress$77.updateQueue = updateQueue; } else wakeables.add(wakeable); if (0 === (workInProgress$77.mode & 2)) { - workInProgress$77.effectTag |= 64; - sourceFiber.effectTag |= 16384; - sourceFiber.effectTag &= -2981; + workInProgress$77.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(-1, 1, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } @@ -6606,7 +6509,7 @@ function handleError(root$jscomp$0, thrownValue) { ); wakeable.then(ping, ping); } - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; workInProgress$77.lanes = thrownValue; break a; } @@ -6625,7 +6528,7 @@ function handleError(root$jscomp$0, thrownValue) { switch (workInProgress$77.tag) { case 3: root = value; - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; thrownValue &= -thrownValue; workInProgress$77.lanes |= thrownValue; var update$78 = createRootErrorUpdate( @@ -6640,14 +6543,14 @@ function handleError(root$jscomp$0, thrownValue) { var ctor = workInProgress$77.type, instance = workInProgress$77.stateNode; if ( - 0 === (workInProgress$77.effectTag & 64) && + 0 === (workInProgress$77.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - workInProgress$77.effectTag |= 4096; + workInProgress$77.flags |= 8192; thrownValue &= -thrownValue; workInProgress$77.lanes |= thrownValue; var update$81 = createClassErrorUpdate( @@ -6683,13 +6586,6 @@ function pushInteractions(root) { tracing.__interactionsRef.current = root.memoizedInteractions; return prevInteractions; } -function markRenderEventTimeAndConfig(eventTime, suspenseConfig) { - null !== suspenseConfig && - ((eventTime += suspenseConfig.timeoutMs | 0 || 5e3), - eventTime > workInProgressRootLatestSuspenseTimeout && - ((workInProgressRootLatestSuspenseTimeout = eventTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig))); -} function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; executionContext |= 16; @@ -6743,7 +6639,7 @@ function completeUnitOfWork(unitOfWork) { do { var current = completedWork.alternate; unitOfWork = completedWork.return; - if (0 === (completedWork.effectTag & 2048)) { + if (0 === (completedWork.flags & 4096)) { if (0 === (completedWork.mode & 8)) current = completeWork(current, completedWork, subtreeRenderLanes); else { @@ -6759,7 +6655,7 @@ function completeUnitOfWork(unitOfWork) { } current = completedWork; if ( - (24 !== current.tag && 23 !== current.tag) || + (23 !== current.tag && 22 !== current.tag) || null === current.memoizedState || 0 !== (subtreeRenderLanes & 1073741824) || 0 === (current.mode & 4) @@ -6796,14 +6692,14 @@ function completeUnitOfWork(unitOfWork) { current.childLanes = fiber; } null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && (unitOfWork.firstEffect = completedWork.firstEffect), null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), (unitOfWork.lastEffect = completedWork.lastEffect)), - 1 < completedWork.effectTag && + 1 < completedWork.flags && (null !== unitOfWork.lastEffect ? (unitOfWork.lastEffect.nextEffect = completedWork) : (unitOfWork.firstEffect = completedWork), @@ -6811,7 +6707,7 @@ function completeUnitOfWork(unitOfWork) { } else { current = unwindWork(completedWork); if (null !== current) { - current.effectTag &= 2047; + current.flags &= 4095; workInProgress = current; return; } @@ -6824,7 +6720,7 @@ function completeUnitOfWork(unitOfWork) { } null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } completedWork = completedWork.sibling; if (null !== completedWork) { @@ -6870,11 +6766,11 @@ function commitRootImpl(root, renderPriorityLevel) { 0 < noLongerPendingLanes; ) { - var index$13 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$13; - remainingLanes$jscomp$0[index$13] = 0; - eventTimes[index$13] = -1; - expirationTimes[index$13] = -1; + var index$12 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$12; + remainingLanes$jscomp$0[index$12] = 0; + eventTimes[index$12] = -1; + expirationTimes[index$12] = -1; noLongerPendingLanes &= ~lane; } null !== rootsWithPendingDiscreteUpdates && @@ -6884,7 +6780,7 @@ function commitRootImpl(root, renderPriorityLevel) { root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), (workInProgressRootRenderLanes = 0)); - 1 < finishedWork.effectTag + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), (remainingLanes = finishedWork.firstEffect)) @@ -6912,8 +6808,8 @@ function commitRootImpl(root, renderPriorityLevel) { do try { for (expirationTimes = root; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6923,21 +6819,21 @@ function commitRootImpl(root, renderPriorityLevel) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: @@ -6952,9 +6848,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$96) { + } catch (error$91) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$96); + captureCommitPhaseError(nextEffect, error$91); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6962,11 +6858,11 @@ function commitRootImpl(root, renderPriorityLevel) { nextEffect = remainingLanes; do try { - for (effectTag = root; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6985,9 +6881,9 @@ function commitRootImpl(root, renderPriorityLevel) { } nextEffect = nextEffect.nextEffect; } - } catch (error$97) { + } catch (error$92) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error$97); + captureCommitPhaseError(nextEffect, error$92); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); @@ -6996,7 +6892,7 @@ function commitRootImpl(root, renderPriorityLevel) { tracing.__interactionsRef.current = eventTimes; executionContext = remainingLanes$jscomp$0; } else (root.current = finishedWork), (commitTime = now$1()); - if ((effectTag$jscomp$0 = rootDoesHavePassiveEffects)) + if ((flags$jscomp$0 = rootDoesHavePassiveEffects)) (rootDoesHavePassiveEffects = !1), (rootWithPendingPassiveEffects = root), (pendingPassiveEffectsLanes = lanes), @@ -7005,7 +6901,7 @@ function commitRootImpl(root, renderPriorityLevel) { for (nextEffect = remainingLanes; null !== nextEffect; ) (ref = nextEffect.nextEffect), (nextEffect.nextEffect = null), - nextEffect.effectTag & 8 && + nextEffect.flags & 8 && ((instance = nextEffect), (instance.sibling = null), (instance.stateNode = null)), @@ -7023,7 +6919,7 @@ function commitRootImpl(root, renderPriorityLevel) { scheduleInteractions(root, ref[instance], root.memoizedInteractions); schedulePendingInteractions(root, remainingLanes); } else legacyErrorBoundariesThatAlreadyFailed = null; - effectTag$jscomp$0 || finishPendingInteractions(root, lanes); + flags$jscomp$0 || finishPendingInteractions(root, lanes); 1 === remainingLanes ? root === rootWithNestedUpdates ? nestedUpdateCount++ @@ -7036,7 +6932,7 @@ function commitRootImpl(root, renderPriorityLevel) { rendererID, finishedWork, renderPriorityLevel, - 64 === (finishedWork.current.effectTag & 64) + 64 === (finishedWork.current.flags & 64) ); } catch (err) {} ensureRootIsScheduled(root, now()); @@ -7054,17 +6950,16 @@ function commitBeforeMutationEffects() { var current = nextEffect.alternate; shouldFireAfterActiveInstanceBlur || null === focusedInstanceHandle || - (0 !== (nextEffect.effectTag & 8) + (0 !== (nextEffect.flags & 8) ? doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0) : 13 === nextEffect.tag && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle) && (shouldFireAfterActiveInstanceBlur = !0)); - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(current, nextEffect); - 0 === (effectTag & 512) || + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -7081,7 +6976,6 @@ function flushPassiveEffects() { ? 97 : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = 90; - schedulerPriorityToLanePriority(priorityLevel); return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } return !1; @@ -7118,10 +7012,10 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsUnmount; pendingPassiveHookEffectsUnmount = []; for (var i = 0; i < unmountEffects.length; i += 2) { - var effect$102 = unmountEffects[i], + var effect$97 = unmountEffects[i], fiber = unmountEffects[i + 1], - destroy = effect$102.destroy; - effect$102.destroy = void 0; + destroy = effect$97.destroy; + effect$97.destroy = void 0; if ("function" === typeof destroy) try { destroy(); @@ -7133,22 +7027,22 @@ function flushPassiveEffectsImpl() { unmountEffects = pendingPassiveHookEffectsMount; pendingPassiveHookEffectsMount = []; for (i = 0; i < unmountEffects.length; i += 2) { - effect$102 = unmountEffects[i]; + effect$97 = unmountEffects[i]; fiber = unmountEffects[i + 1]; try { - var create$106 = effect$102.create; - effect$102.destroy = create$106(); - } catch (error$107) { + var create$101 = effect$97.create; + effect$97.destroy = create$101(); + } catch (error$102) { if (null === fiber) throw Error("Should be working on an effect."); - captureCommitPhaseError(fiber, error$107); + captureCommitPhaseError(fiber, error$102); } } for (unmountEffects = root.current.firstEffect; null !== unmountEffects; ) - (create$106 = unmountEffects.nextEffect), + (create$101 = unmountEffects.nextEffect), (unmountEffects.nextEffect = null), - unmountEffects.effectTag & 8 && + unmountEffects.flags & 8 && ((unmountEffects.sibling = null), (unmountEffects.stateNode = null)), - (unmountEffects = create$106); + (unmountEffects = create$101); tracing.__interactionsRef.current = prevInteractions; finishPendingInteractions(root, lanes); executionContext = prevExecutionContext; @@ -7183,14 +7077,22 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1); - enqueueUpdate(fiber, sourceFiber); - sourceFiber = requestEventTime(); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); fiber = markUpdateLaneFromFiberToRoot(fiber, 1); - null !== fiber && - (markRootUpdated(fiber, 1, sourceFiber), - ensureRootIsScheduled(fiber, sourceFiber), - schedulePendingInteractions(fiber, 1)); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update), + schedulePendingInteractions(fiber, 1); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } @@ -7245,7 +7147,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ) didReceiveUpdate = !0; else if (0 !== (renderLanes & updateLanes)) - didReceiveUpdate = 0 !== (current.effectTag & 16384) ? !0 : !1; + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { didReceiveUpdate = !1; switch (workInProgress.tag) { @@ -7273,7 +7175,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 12: 0 !== (renderLanes & workInProgress.childLanes) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); updateLanes = workInProgress.stateNode; updateLanes.effectDuration = 0; updateLanes.passiveEffectDuration = 0; @@ -7298,14 +7200,14 @@ beginWork$1 = function(current, workInProgress, renderLanes) { break; case 19: updateLanes = 0 !== (renderLanes & workInProgress.childLanes); - if (0 !== (current.effectTag & 64)) { + if (0 !== (current.flags & 64)) { if (updateLanes) return updateSuspenseListComponent( current, workInProgress, renderLanes ); - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; } context = workInProgress.memoizedState; null !== context && @@ -7315,8 +7217,8 @@ beginWork$1 = function(current, workInProgress, renderLanes) { push(suspenseStackCursor, suspenseStackCursor.current); if (updateLanes) break; else return null; + case 22: case 23: - case 24: return ( (workInProgress.lanes = 0), updateOffscreenComponent(current, workInProgress, renderLanes) @@ -7332,7 +7234,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); prepareToReadContext(workInProgress, renderLanes); @@ -7344,7 +7246,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { context, renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -7394,7 +7296,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; hasContext = context._init; context = hasContext(context._payload); @@ -7573,7 +7475,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 12: return ( - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (updateLanes = workInProgress.stateNode), (updateLanes.effectDuration = 0), (updateLanes.passiveEffectDuration = 0), @@ -7641,8 +7543,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { 1 === context$jscomp$0.tag && ((dependency = createUpdate( -1, - renderLanes & -renderLanes, - null + renderLanes & -renderLanes )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); @@ -7704,7 +7605,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), (updateLanes = updateLanes(context)), - (workInProgress.effectTag |= 1), + (workInProgress.flags |= 1), reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); @@ -7745,7 +7646,7 @@ beginWork$1 = function(current, workInProgress, renderLanes) { null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) @@ -7764,9 +7665,9 @@ beginWork$1 = function(current, workInProgress, renderLanes) { ); case 19: return updateSuspenseListComponent(current, workInProgress, renderLanes); - case 23: + case 22: return updateOffscreenComponent(current, workInProgress, renderLanes); - case 24: + case 23: return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( @@ -7775,6 +7676,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { "). This error is likely caused by a bug in React. Please file an issue." ); }; +function markSpawnedWork(lane) { + null === spawnedWorkDuringRender + ? (spawnedWorkDuringRender = [lane]) + : spawnedWorkDuringRender.push(lane); +} function scheduleInteractions(root, lane, interactions) { if (0 < interactions.size) { var pendingInteractionMap = root.pendingInteractionMap, @@ -7848,9 +7754,9 @@ function finishPendingInteractions(root, committedLanes) { if (null !== subscriber && 0 === interaction.__count) try { subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error$108) { + } catch (error$103) { scheduleCallback(99, function() { - throw error$108; + throw error$103; }); } })); @@ -7866,7 +7772,7 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; this.childLanes = this.lanes = 0; this.alternate = null; @@ -7907,7 +7813,7 @@ function createWorkInProgress(current, pendingProps) { (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), (workInProgress.type = current.type), - (workInProgress.effectTag = 0), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null), @@ -7983,7 +7889,7 @@ function createFiberFromTypeAndProps( return createFiberFromOffscreen(pendingProps, mode, lanes, key); case REACT_LEGACY_HIDDEN_TYPE: return ( - (type = createFiber(24, pendingProps, key, mode)), + (type = createFiber(23, pendingProps, key, mode)), (type.elementType = REACT_LEGACY_HIDDEN_TYPE), (type.lanes = lanes), type @@ -8007,9 +7913,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -8029,7 +7932,7 @@ function createFiberFromFragment(elements, mode, lanes, key) { return elements; } function createFiberFromOffscreen(pendingProps, mode, lanes, key) { - pendingProps = createFiber(23, pendingProps, key, mode); + pendingProps = createFiber(22, pendingProps, key, mode); pendingProps.elementType = REACT_OFFSCREEN_TYPE; pendingProps.lanes = lanes; return pendingProps; @@ -8063,10 +7966,10 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.hydrate = hydrate; this.callbackNode = null; this.callbackPriority = 0; - this.eventTimes = Array(31).fill(0); - this.expirationTimes = Array(31).fill(-1); + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; - this.entanglements = Array(31).fill(0); + this.entanglements = createLaneMap(0); this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); @@ -8098,8 +8001,7 @@ function findHostInstance(component) { function updateContainer(element, container, parentComponent, callback) { var current = container.current, eventTime = requestEventTime(), - suspenseConfig = ReactCurrentBatchConfig.suspense, - lane = requestUpdateLane(current, suspenseConfig); + lane = requestUpdateLane(current); a: if (parentComponent) { parentComponent = parentComponent._reactInternals; b: { @@ -8147,7 +8049,7 @@ function updateContainer(element, container, parentComponent, callback) { null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(eventTime, lane, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); @@ -8185,14 +8087,16 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - 0 === executionContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; var roots = new Map(), - devToolsConfig$jscomp$inline_956 = { + devToolsConfig$jscomp$inline_930 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "17.0.0-alpha.0", + version: "17.0.1-454c2211c", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8207,13 +8111,17 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1172 = { - bundleType: devToolsConfig$jscomp$inline_956.bundleType, - version: devToolsConfig$jscomp$inline_956.version, - rendererPackageName: devToolsConfig$jscomp$inline_956.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_956.rendererConfig, +var internals$jscomp$inline_1148 = { + bundleType: devToolsConfig$jscomp$inline_930.bundleType, + version: devToolsConfig$jscomp$inline_930.version, + rendererPackageName: devToolsConfig$jscomp$inline_930.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_930.rendererConfig, overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, setSuspenseHandler: null, scheduleUpdate: null, currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, @@ -8222,7 +8130,7 @@ var internals$jscomp$inline_1172 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_956.findFiberByHostInstance || + devToolsConfig$jscomp$inline_930.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, @@ -8231,16 +8139,16 @@ var internals$jscomp$inline_1172 = { getCurrentFiber: null }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1173 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1149 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1173.isDisabled && - hook$jscomp$inline_1173.supportsFiber + !hook$jscomp$inline_1149.isDisabled && + hook$jscomp$inline_1149.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1173.inject( - internals$jscomp$inline_1172 + (rendererID = hook$jscomp$inline_1149.inject( + internals$jscomp$inline_1148 )), - (injectedHook = hook$jscomp$inline_1173); + (injectedHook = hook$jscomp$inline_1149); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -8314,6 +8222,18 @@ exports.render = function(element, containerTag, callback) { else element = null; return element; }; +exports.sendAccessibilityEvent = function(handle, eventType) { + null != handle._nativeTag && + (handle._internalInstanceHandle + ? nativeFabricUIManager.sendAccessibilityEvent( + handle._internalInstanceHandle.stateNode.node, + eventType + ) + : ReactNativePrivateInterface.legacySendAccessibilityEvent( + handle._nativeTag, + eventType + )); +}; exports.unmountComponentAtNode = unmountComponentAtNode; exports.unmountComponentAtNodeAndRemoveContainer = function(containerTag) { unmountComponentAtNode(containerTag); diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js index c81740113065d3..726a064c70b56a 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js @@ -17,16 +17,6 @@ var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/R React = require("react"), Scheduler = require("scheduler"), tracing = require("scheduler/tracing"); -function getParent(inst) { - do inst = inst.return; - while (inst && 5 !== inst.tag); - return inst ? inst : null; -} -function traverseTwoPhase(inst, fn, arg) { - for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); - for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); - for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); -} function invokeGuardedCallbackImpl(name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try { @@ -97,109 +87,6 @@ function executeDirectDispatch(event) { event._dispatchInstances = null; return dispatchListener; } -function getListener(inst, registrationName) { - var listener = inst.stateNode; - if (!listener) return null; - var props = getFiberCurrentPropsFromNode(listener); - if (!props) return null; - listener = props[registrationName]; - a: switch (registrationName) { - case "onClick": - case "onClickCapture": - case "onDoubleClick": - case "onDoubleClickCapture": - case "onMouseDown": - case "onMouseDownCapture": - case "onMouseMove": - case "onMouseMoveCapture": - case "onMouseUp": - case "onMouseUpCapture": - case "onMouseEnter": - (props = !props.disabled) || - ((inst = inst.type), - (props = !( - "button" === inst || - "input" === inst || - "select" === inst || - "textarea" === inst - ))); - inst = !props; - break a; - default: - inst = !1; - } - if (inst) return null; - if (listener && "function" !== typeof listener) - throw Error( - "Expected `" + - registrationName + - "` listener to be a function, instead got a value of `" + - typeof listener + - "` type." - ); - return listener; -} -function accumulateInto(current, next) { - if (null == next) - throw Error( - "accumulateInto(...): Accumulated items must not be null or undefined." - ); - if (null == current) return next; - if (Array.isArray(current)) { - if (Array.isArray(next)) return current.push.apply(current, next), current; - current.push(next); - return current; - } - return Array.isArray(next) ? [current].concat(next) : [current, next]; -} -function forEachAccumulated(arr, cb, scope) { - Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); -} -function accumulateDirectionalDispatches(inst, phase, event) { - if ( - (phase = getListener( - inst, - event.dispatchConfig.phasedRegistrationNames[phase] - )) - ) - (event._dispatchListeners = accumulateInto( - event._dispatchListeners, - phase - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - )); -} -function accumulateTwoPhaseDispatchesSingle(event) { - event && - event.dispatchConfig.phasedRegistrationNames && - traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); -} -function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { - if (event && event.dispatchConfig.phasedRegistrationNames) { - var targetInst = event._targetInst; - targetInst = targetInst ? getParent(targetInst) : null; - traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); - } -} -function accumulateDirectDispatchesSingle(event) { - if (event && event.dispatchConfig.registrationName) { - var inst = event._targetInst; - if (inst && event && event.dispatchConfig.registrationName) { - var listener = getListener(inst, event.dispatchConfig.registrationName); - listener && - ((event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener - )), - (event._dispatchInstances = accumulateInto( - event._dispatchInstances, - inst - ))); - } - } -} function functionThatReturnsTrue() { return !0; } @@ -215,6 +102,7 @@ function SyntheticEvent( this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; + this._dispatchInstances = this._dispatchListeners = null; dispatchConfig = this.constructor.Interface; for (var propName in dispatchConfig) dispatchConfig.hasOwnProperty(propName) && @@ -294,7 +182,12 @@ SyntheticEvent.extend = function(Interface) { return Class; }; addEventPoolingTo(SyntheticEvent); -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst +) { if (this.eventPool.length) { var instance = this.eventPool.pop(); this.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst); @@ -311,8 +204,8 @@ function releasePooledEvent(event) { 10 > this.eventPool.length && this.eventPool.push(event); } function addEventPoolingTo(EventConstructor) { + EventConstructor.getPooled = createOrGetPooledEvent; EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; EventConstructor.release = releasePooledEvent; } var ResponderSyntheticEvent = SyntheticEvent.extend({ @@ -440,6 +333,22 @@ function accumulate(current, next) { ? [current].concat(next) : [current, next]; } +function accumulateInto(current, next) { + if (null == next) + throw Error( + "accumulateInto(...): Accumulated items must not be null or undefined." + ); + if (null == current) return next; + if (Array.isArray(current)) { + if (Array.isArray(next)) return current.push.apply(current, next), current; + current.push(next); + return current; + } + return Array.isArray(next) ? [current].concat(next) : [current, next]; +} +function forEachAccumulated(arr, cb, scope) { + Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); +} var responderInst = null, trackedTouchCount = 0; function changeResponder(nextResponderInst, blockHostResponder) { @@ -453,65 +362,132 @@ function changeResponder(nextResponderInst, blockHostResponder) { ); } var eventTypes = { - startShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onStartShouldSetResponder", - captured: "onStartShouldSetResponderCapture" - }, - dependencies: startDependencies - }, - scrollShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onScrollShouldSetResponder", - captured: "onScrollShouldSetResponderCapture" - }, - dependencies: ["topScroll"] - }, - selectionChangeShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onSelectionChangeShouldSetResponder", - captured: "onSelectionChangeShouldSetResponderCapture" - }, - dependencies: ["topSelectionChange"] - }, - moveShouldSetResponder: { - phasedRegistrationNames: { - bubbled: "onMoveShouldSetResponder", - captured: "onMoveShouldSetResponderCapture" - }, - dependencies: moveDependencies - }, - responderStart: { - registrationName: "onResponderStart", - dependencies: startDependencies - }, - responderMove: { - registrationName: "onResponderMove", - dependencies: moveDependencies + startShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onStartShouldSetResponder", + captured: "onStartShouldSetResponderCapture" }, - responderEnd: { - registrationName: "onResponderEnd", - dependencies: endDependencies - }, - responderRelease: { - registrationName: "onResponderRelease", - dependencies: endDependencies + dependencies: startDependencies + }, + scrollShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onScrollShouldSetResponder", + captured: "onScrollShouldSetResponderCapture" }, - responderTerminationRequest: { - registrationName: "onResponderTerminationRequest", - dependencies: [] + dependencies: ["topScroll"] + }, + selectionChangeShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onSelectionChangeShouldSetResponder", + captured: "onSelectionChangeShouldSetResponderCapture" }, - responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, - responderReject: { - registrationName: "onResponderReject", - dependencies: [] + dependencies: ["topSelectionChange"] + }, + moveShouldSetResponder: { + phasedRegistrationNames: { + bubbled: "onMoveShouldSetResponder", + captured: "onMoveShouldSetResponderCapture" }, - responderTerminate: { - registrationName: "onResponderTerminate", - dependencies: [] - } + dependencies: moveDependencies + }, + responderStart: { + registrationName: "onResponderStart", + dependencies: startDependencies + }, + responderMove: { + registrationName: "onResponderMove", + dependencies: moveDependencies + }, + responderEnd: { + registrationName: "onResponderEnd", + dependencies: endDependencies }, - ResponderEventPlugin = { + responderRelease: { + registrationName: "onResponderRelease", + dependencies: endDependencies + }, + responderTerminationRequest: { + registrationName: "onResponderTerminationRequest", + dependencies: [] + }, + responderGrant: { registrationName: "onResponderGrant", dependencies: [] }, + responderReject: { registrationName: "onResponderReject", dependencies: [] }, + responderTerminate: { + registrationName: "onResponderTerminate", + dependencies: [] + } +}; +function getParent(inst) { + do inst = inst.return; + while (inst && 5 !== inst.tag); + return inst ? inst : null; +} +function traverseTwoPhase(inst, fn, arg) { + for (var path = []; inst; ) path.push(inst), (inst = getParent(inst)); + for (inst = path.length; 0 < inst--; ) fn(path[inst], "captured", arg); + for (inst = 0; inst < path.length; inst++) fn(path[inst], "bubbled", arg); +} +function getListener(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +function accumulateDirectionalDispatches(inst, phase, event) { + if ( + (phase = getListener( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + targetInst = targetInst ? getParent(targetInst) : null; + traverseTwoPhase(targetInst, accumulateDirectionalDispatches, event); + } +} +function accumulateTwoPhaseDispatchesSingle(event) { + event && + event.dispatchConfig.phasedRegistrationNames && + traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); +} +var ResponderEventPlugin = { _getResponder: function() { return responderInst; }, @@ -572,68 +548,70 @@ var eventTypes = { JSCompiler_temp = null; } else JSCompiler_temp = targetInst; - targetInst = JSCompiler_temp === responderInst; - JSCompiler_temp = ResponderSyntheticEvent.getPooled( + targetInst = JSCompiler_temp; + JSCompiler_temp = targetInst === responderInst; + shouldSetEventType = ResponderSyntheticEvent.getPooled( shouldSetEventType, - JSCompiler_temp, + targetInst, nativeEvent, nativeEventTarget ); - JSCompiler_temp.touchHistory = ResponderTouchHistoryStore.touchHistory; - targetInst + shouldSetEventType.touchHistory = + ResponderTouchHistoryStore.touchHistory; + JSCompiler_temp ? forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingleSkipTarget ) : forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateTwoPhaseDispatchesSingle ); b: { - shouldSetEventType = JSCompiler_temp._dispatchListeners; - targetInst = JSCompiler_temp._dispatchInstances; - if (Array.isArray(shouldSetEventType)) + JSCompiler_temp = shouldSetEventType._dispatchListeners; + targetInst = shouldSetEventType._dispatchInstances; + if (Array.isArray(JSCompiler_temp)) for ( depthA = 0; - depthA < shouldSetEventType.length && - !JSCompiler_temp.isPropagationStopped(); + depthA < JSCompiler_temp.length && + !shouldSetEventType.isPropagationStopped(); depthA++ ) { if ( - shouldSetEventType[depthA](JSCompiler_temp, targetInst[depthA]) + JSCompiler_temp[depthA](shouldSetEventType, targetInst[depthA]) ) { - shouldSetEventType = targetInst[depthA]; + JSCompiler_temp = targetInst[depthA]; break b; } } else if ( - shouldSetEventType && - shouldSetEventType(JSCompiler_temp, targetInst) + JSCompiler_temp && + JSCompiler_temp(shouldSetEventType, targetInst) ) { - shouldSetEventType = targetInst; + JSCompiler_temp = targetInst; break b; } - shouldSetEventType = null; + JSCompiler_temp = null; } - JSCompiler_temp._dispatchInstances = null; - JSCompiler_temp._dispatchListeners = null; - JSCompiler_temp.isPersistent() || - JSCompiler_temp.constructor.release(JSCompiler_temp); - if (shouldSetEventType && shouldSetEventType !== responderInst) + shouldSetEventType._dispatchInstances = null; + shouldSetEventType._dispatchListeners = null; + shouldSetEventType.isPersistent() || + shouldSetEventType.constructor.release(shouldSetEventType); + if (JSCompiler_temp && JSCompiler_temp !== responderInst) if ( - ((JSCompiler_temp = ResponderSyntheticEvent.getPooled( + ((shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderGrant, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), - (JSCompiler_temp.touchHistory = + (shouldSetEventType.touchHistory = ResponderTouchHistoryStore.touchHistory), forEachAccumulated( - JSCompiler_temp, + shouldSetEventType, accumulateDirectDispatchesSingle ), - (targetInst = !0 === executeDirectDispatch(JSCompiler_temp)), + (targetInst = !0 === executeDirectDispatch(shouldSetEventType)), responderInst) ) if ( @@ -660,13 +638,13 @@ var eventTypes = { forEachAccumulated(depthA, accumulateDirectDispatchesSingle); var JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - [JSCompiler_temp, depthA] + [shouldSetEventType, depthA] ); - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); } else (shouldSetEventType = ResponderSyntheticEvent.getPooled( eventTypes.responderReject, - shouldSetEventType, + JSCompiler_temp, nativeEvent, nativeEventTarget )), @@ -683,9 +661,9 @@ var eventTypes = { else (JSCompiler_temp$jscomp$0 = accumulate( JSCompiler_temp$jscomp$0, - JSCompiler_temp + shouldSetEventType )), - changeResponder(shouldSetEventType, targetInst); + changeResponder(JSCompiler_temp, targetInst); else JSCompiler_temp$jscomp$0 = null; } else JSCompiler_temp$jscomp$0 = null; shouldSetEventType = responderInst && isStartish(topLevelType); @@ -813,7 +791,6 @@ function recomputePluginOrdering() { for (var eventName in pluginIndex) { var JSCompiler_inline_result = void 0; var dispatchConfig = pluginIndex[eventName], - pluginModule$jscomp$0 = pluginModule, eventName$jscomp$0 = eventName; if (eventNameDispatchConfigs.hasOwnProperty(eventName$jscomp$0)) throw Error( @@ -830,7 +807,7 @@ function recomputePluginOrdering() { ) && publishRegistrationName( phasedRegistrationNames[JSCompiler_inline_result], - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ); JSCompiler_inline_result = !0; @@ -838,7 +815,7 @@ function recomputePluginOrdering() { dispatchConfig.registrationName ? (publishRegistrationName( dispatchConfig.registrationName, - pluginModule$jscomp$0, + pluginModule, eventName$jscomp$0 ), (JSCompiler_inline_result = !0)) @@ -866,13 +843,75 @@ function publishRegistrationName(registrationName, pluginModule) { } var plugins = [], eventNameDispatchConfigs = {}, - registrationNameModules = {}, - customBubblingEventTypes = + registrationNameModules = {}; +function getListener$1(inst, registrationName) { + inst = inst.stateNode; + if (null === inst) return null; + inst = getFiberCurrentPropsFromNode(inst); + if (null === inst) return null; + if ((inst = inst[registrationName]) && "function" !== typeof inst) + throw Error( + "Expected `" + + registrationName + + "` listener to be a function, instead got a value of `" + + typeof inst + + "` type." + ); + return inst; +} +var customBubblingEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customBubblingEventTypes, customDirectEventTypes = ReactNativePrivateInterface.ReactNativeViewConfigRegistry .customDirectEventTypes; +function accumulateDirectionalDispatches$1(inst, phase, event) { + if ( + (phase = getListener$1( + inst, + event.dispatchConfig.phasedRegistrationNames[phase] + )) + ) + (event._dispatchListeners = accumulateInto( + event._dispatchListeners, + phase + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + )); +} +function accumulateTwoPhaseDispatchesSingle$1(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + for (var inst = event._targetInst, path = []; inst; ) { + path.push(inst); + do inst = inst.return; + while (inst && 5 !== inst.tag); + inst = inst ? inst : null; + } + for (inst = path.length; 0 < inst--; ) + accumulateDirectionalDispatches$1(path[inst], "captured", event); + for (inst = 0; inst < path.length; inst++) + accumulateDirectionalDispatches$1(path[inst], "bubbled", event); + } +} +function accumulateDirectDispatchesSingle$1(event) { + if (event && event.dispatchConfig.registrationName) { + var inst = event._targetInst; + if (inst && event && event.dispatchConfig.registrationName) { + var listener = getListener$1(inst, event.dispatchConfig.registrationName); + listener && + ((event._dispatchListeners = accumulateInto( + event._dispatchListeners, + listener + )), + (event._dispatchInstances = accumulateInto( + event._dispatchInstances, + inst + ))); + } + } +} if (eventPluginOrder) throw Error( "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React." @@ -882,7 +921,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_94 = { +var injectedNamesToPlugins$jscomp$inline_226 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -906,42 +945,45 @@ var injectedNamesToPlugins$jscomp$inline_94 = { nativeEventTarget ); if (bubbleDispatchConfig) - forEachAccumulated(topLevelType, accumulateTwoPhaseDispatchesSingle); + forEachAccumulated( + topLevelType, + accumulateTwoPhaseDispatchesSingle$1 + ); else if (directDispatchConfig) - forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle); + forEachAccumulated(topLevelType, accumulateDirectDispatchesSingle$1); else return null; return topLevelType; } } }, - isOrderingDirty$jscomp$inline_95 = !1, - pluginName$jscomp$inline_96; -for (pluginName$jscomp$inline_96 in injectedNamesToPlugins$jscomp$inline_94) + isOrderingDirty$jscomp$inline_227 = !1, + pluginName$jscomp$inline_228; +for (pluginName$jscomp$inline_228 in injectedNamesToPlugins$jscomp$inline_226) if ( - injectedNamesToPlugins$jscomp$inline_94.hasOwnProperty( - pluginName$jscomp$inline_96 + injectedNamesToPlugins$jscomp$inline_226.hasOwnProperty( + pluginName$jscomp$inline_228 ) ) { - var pluginModule$jscomp$inline_97 = - injectedNamesToPlugins$jscomp$inline_94[pluginName$jscomp$inline_96]; + var pluginModule$jscomp$inline_229 = + injectedNamesToPlugins$jscomp$inline_226[pluginName$jscomp$inline_228]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_96) || - namesToPlugins[pluginName$jscomp$inline_96] !== - pluginModule$jscomp$inline_97 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_228) || + namesToPlugins[pluginName$jscomp$inline_228] !== + pluginModule$jscomp$inline_229 ) { - if (namesToPlugins[pluginName$jscomp$inline_96]) + if (namesToPlugins[pluginName$jscomp$inline_228]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - pluginName$jscomp$inline_96 + + pluginName$jscomp$inline_228 + "`." ); namesToPlugins[ - pluginName$jscomp$inline_96 - ] = pluginModule$jscomp$inline_97; - isOrderingDirty$jscomp$inline_95 = !0; + pluginName$jscomp$inline_228 + ] = pluginModule$jscomp$inline_229; + isOrderingDirty$jscomp$inline_227 = !0; } } -isOrderingDirty$jscomp$inline_95 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_227 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -987,34 +1029,41 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) { target = null; null != inst && (target = inst.stateNode); batchedUpdates(function() { - var events = target; - for (var events$jscomp$0 = null, i = 0; i < plugins.length; i++) { - var possiblePlugin = plugins[i]; + var JSCompiler_inline_result = target; + for ( + var events = null, legacyPlugins = plugins, i = 0; + i < legacyPlugins.length; + i++ + ) { + var possiblePlugin = legacyPlugins[i]; possiblePlugin && (possiblePlugin = possiblePlugin.extractEvents( topLevelType, inst, nativeEvent, - events, - 1 + JSCompiler_inline_result )) && - (events$jscomp$0 = accumulateInto(events$jscomp$0, possiblePlugin)); + (events = accumulateInto(events, possiblePlugin)); } - events = events$jscomp$0; - null !== events && (eventQueue = accumulateInto(eventQueue, events)); - events = eventQueue; + JSCompiler_inline_result = events; + null !== JSCompiler_inline_result && + (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); + JSCompiler_inline_result = eventQueue; eventQueue = null; - if (events) { - forEachAccumulated(events, executeDispatchesAndReleaseTopLevel); + if (JSCompiler_inline_result) { + forEachAccumulated( + JSCompiler_inline_result, + executeDispatchesAndReleaseTopLevel + ); if (eventQueue) throw Error( "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." ); if (hasRethrowError) - throw ((events = rethrowError), + throw ((JSCompiler_inline_result = rethrowError), (hasRethrowError = !1), (rethrowError = null), - events); + JSCompiler_inline_result); } }); } @@ -1029,13 +1078,13 @@ ReactNativePrivateInterface.RCTEventEmitter.register({ ) { var JSCompiler_temp = []; for (var i = 0; i < changedIndices.length; i++) { - var index = changedIndices[i]; - JSCompiler_temp.push(touches[index]); - touches[index] = null; + var index$0 = changedIndices[i]; + JSCompiler_temp.push(touches[index$0]); + touches[index$0] = null; } for (i = changedIndices = 0; i < touches.length; i++) - (index = touches[i]), - null !== index && (touches[changedIndices++] = index); + (index$0 = touches[i]), + null !== index$0 && (touches[changedIndices++] = index$0); touches.length = changedIndices; } else for (JSCompiler_temp = [], i = 0; i < changedIndices.length; i++) @@ -1048,10 +1097,10 @@ ReactNativePrivateInterface.RCTEventEmitter.register({ i = JSCompiler_temp[changedIndices]; i.changedTouches = JSCompiler_temp; i.touches = touches; - index = null; + index$0 = null; var target = i.target; - null === target || void 0 === target || 1 > target || (index = target); - _receiveRootNodeIDEvent(index, eventTopLevelType, i); + null === target || void 0 === target || 1 > target || (index$0 = target); + _receiveRootNodeIDEvent(index$0, eventTopLevelType, i); } } }); @@ -1077,31 +1126,42 @@ ResponderEventPlugin.injection.injectGlobalResponderHandler({ } }); var ReactSharedInternals = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; -ReactSharedInternals.hasOwnProperty("ReactCurrentDispatcher") || - (ReactSharedInternals.ReactCurrentDispatcher = { current: null }); -ReactSharedInternals.hasOwnProperty("ReactCurrentBatchConfig") || - (ReactSharedInternals.ReactCurrentBatchConfig = { suspense: null }); -var hasSymbol = "function" === typeof Symbol && Symbol.for, - REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, - REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, - REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, - REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, - REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, - REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, - REACT_CONCURRENT_MODE_TYPE = hasSymbol - ? Symbol.for("react.concurrent_mode") - : 60111, - REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, - REACT_SUSPENSE_LIST_TYPE = hasSymbol - ? Symbol.for("react.suspense_list") - : 60120, - REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115, - REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116, - REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121, - MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + REACT_ELEMENT_TYPE = 60103, + REACT_PORTAL_TYPE = 60106, + REACT_FRAGMENT_TYPE = 60107, + REACT_STRICT_MODE_TYPE = 60108, + REACT_PROFILER_TYPE = 60114, + REACT_PROVIDER_TYPE = 60109, + REACT_CONTEXT_TYPE = 60110, + REACT_FORWARD_REF_TYPE = 60112, + REACT_SUSPENSE_TYPE = 60113, + REACT_SUSPENSE_LIST_TYPE = 60120, + REACT_MEMO_TYPE = 60115, + REACT_LAZY_TYPE = 60116, + REACT_DEBUG_TRACING_MODE_TYPE = 60129, + REACT_OFFSCREEN_TYPE = 60130, + REACT_LEGACY_HIDDEN_TYPE = 60131; +if ("function" === typeof Symbol && Symbol.for) { + var symbolFor = Symbol.for; + REACT_ELEMENT_TYPE = symbolFor("react.element"); + REACT_PORTAL_TYPE = symbolFor("react.portal"); + REACT_FRAGMENT_TYPE = symbolFor("react.fragment"); + REACT_STRICT_MODE_TYPE = symbolFor("react.strict_mode"); + REACT_PROFILER_TYPE = symbolFor("react.profiler"); + REACT_PROVIDER_TYPE = symbolFor("react.provider"); + REACT_CONTEXT_TYPE = symbolFor("react.context"); + REACT_FORWARD_REF_TYPE = symbolFor("react.forward_ref"); + REACT_SUSPENSE_TYPE = symbolFor("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = symbolFor("react.suspense_list"); + REACT_MEMO_TYPE = symbolFor("react.memo"); + REACT_LAZY_TYPE = symbolFor("react.lazy"); + symbolFor("react.scope"); + REACT_DEBUG_TRACING_MODE_TYPE = symbolFor("react.debug_trace_mode"); + REACT_OFFSCREEN_TYPE = symbolFor("react.offscreen"); + REACT_LEGACY_HIDDEN_TYPE = symbolFor("react.legacy_hidden"); +} +var MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "object" !== typeof maybeIterable) return null; maybeIterable = @@ -1109,27 +1169,6 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } -function initializeLazyComponentType(lazyComponent) { - if (-1 === lazyComponent._status) { - var ctor = lazyComponent._result; - ctor || (ctor = lazyComponent._ctor); - ctor = ctor(); - lazyComponent._status = 0; - lazyComponent._result = ctor; - ctor.then( - function(moduleObject) { - 0 === lazyComponent._status && - ((moduleObject = moduleObject.default), - (lazyComponent._status = 1), - (lazyComponent._result = moduleObject)); - }, - function(error) { - 0 === lazyComponent._status && - ((lazyComponent._status = 2), (lazyComponent._result = error)); - } - ); - } -} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1163,11 +1202,12 @@ function getComponentName(type) { ); case REACT_MEMO_TYPE: return getComponentName(type.type); - case REACT_BLOCK_TYPE: - return getComponentName(type.render); case REACT_LAZY_TYPE: - if ((type = 1 === type._status ? type._result : null)) - return getComponentName(type); + innerType = type._payload; + type = type._init; + try { + return getComponentName(type(innerType)); + } catch (x) {} } return null; } @@ -1179,7 +1219,7 @@ function getNearestMountedFiber(fiber) { fiber = node; do (node = fiber), - 0 !== (node.effectTag & 1026) && (nearestMounted = node.return), + 0 !== (node.flags & 1026) && (nearestMounted = node.return), (fiber = node.return); while (fiber); } @@ -1219,36 +1259,36 @@ function findCurrentFiberUsingSlowPath(fiber) { } if (a.return !== b.return) (a = parentA), (b = parentB); else { - for (var didFindChild = !1, _child = parentA.child; _child; ) { - if (_child === a) { + for (var didFindChild = !1, child$1 = parentA.child; child$1; ) { + if (child$1 === a) { didFindChild = !0; a = parentA; b = parentB; break; } - if (_child === b) { + if (child$1 === b) { didFindChild = !0; b = parentA; a = parentB; break; } - _child = _child.sibling; + child$1 = child$1.sibling; } if (!didFindChild) { - for (_child = parentB.child; _child; ) { - if (_child === a) { + for (child$1 = parentB.child; child$1; ) { + if (child$1 === a) { didFindChild = !0; a = parentB; b = parentA; break; } - if (_child === b) { + if (child$1 === b) { didFindChild = !0; b = parentB; a = parentA; break; } - _child = _child.sibling; + child$1 = child$1.sibling; } if (!didFindChild) throw Error( @@ -1283,6 +1323,18 @@ function findCurrentHostFiber(parent) { } return null; } +function doesFiberContain(parentFiber, childFiber) { + for ( + var parentFiberAlternate = parentFiber.alternate; + null !== childFiber; + + ) { + if (childFiber === parentFiber || childFiber === parentFiberAlternate) + return !0; + childFiber = childFiber.return; + } + return !1; +} var emptyObject = {}, removedKeys = null, removedKeyCount = 0, @@ -1487,19 +1539,19 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) { ), (removedKeys = null)); } - for (var _propKey in prevProps) - void 0 === nextProps[_propKey] && - (!(attributeConfig = validAttributes[_propKey]) || - (updatePayload && void 0 !== updatePayload[_propKey]) || - ((prevProp = prevProps[_propKey]), + for (var propKey$3 in prevProps) + void 0 === nextProps[propKey$3] && + (!(attributeConfig = validAttributes[propKey$3]) || + (updatePayload && void 0 !== updatePayload[propKey$3]) || + ((prevProp = prevProps[propKey$3]), void 0 !== prevProp && ("object" !== typeof attributeConfig || "function" === typeof attributeConfig.diff || "function" === typeof attributeConfig.process - ? (((updatePayload || (updatePayload = {}))[_propKey] = null), + ? (((updatePayload || (updatePayload = {}))[propKey$3] = null), removedKeys || (removedKeys = {}), - removedKeys[_propKey] || - ((removedKeys[_propKey] = !0), removedKeyCount++)) + removedKeys[propKey$3] || + ((removedKeys[propKey$3] = !0), removedKeyCount++)) : (updatePayload = clearNestedProperty( updatePayload, prevProp, @@ -1608,9 +1660,22 @@ function finalizeInitialChildren(parentInstance) { return !1; } var scheduleTimeout = setTimeout, - cancelTimeout = clearTimeout, - valueStack = [], + cancelTimeout = clearTimeout; +function describeComponentFrame(name, source, ownerName) { + source = ""; + ownerName && (source = " (created by " + ownerName + ")"); + return "\n in " + (name || "Unknown") + source; +} +function describeFunctionComponentFrame(fn, source) { + return fn + ? describeComponentFrame(fn.displayName || fn.name || null, source, null) + : ""; +} +var valueStack = [], index = -1; +function createCursor(defaultValue) { + return { current: defaultValue }; +} function pop(cursor) { 0 > index || ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); @@ -1621,8 +1686,8 @@ function push(cursor, value) { cursor.current = value; } var emptyContextObject = {}, - contextStackCursor = { current: emptyContextObject }, - didPerformWorkStackCursor = { current: !1 }, + contextStackCursor = createCursor(emptyContextObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyContextObject; function getMaskedContext(workInProgress, unmaskedContext) { var contextTypes = workInProgress.type.contextTypes; @@ -1671,7 +1736,7 @@ function processChildContext(fiber, type, parentContext) { contextKey + '" is not defined in childContextTypes.' ); - return Object.assign({}, parentContext, {}, instance); + return Object.assign({}, parentContext, instance); } function pushContextProvider(workInProgress) { workInProgress = @@ -1702,12 +1767,212 @@ function invalidateContextProvider(workInProgress, type, didChange) { : pop(didPerformWorkStackCursor); push(didPerformWorkStackCursor, didChange); } +var rendererID = null, + injectedHook = null, + isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__, + Scheduler_now = Scheduler.unstable_now; +if ( + null == tracing.__interactionsRef || + null == tracing.__interactionsRef.current +) + throw Error( + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" + ); +Scheduler_now(); +var return_highestLanePriority = 8; +function getHighestPriorityLanes(lanes) { + if (0 !== (1 & lanes)) return (return_highestLanePriority = 15), 1; + if (0 !== (2 & lanes)) return (return_highestLanePriority = 14), 2; + if (0 !== (4 & lanes)) return (return_highestLanePriority = 13), 4; + var inputDiscreteLanes = 24 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 12), inputDiscreteLanes; + if (0 !== (lanes & 32)) return (return_highestLanePriority = 11), 32; + inputDiscreteLanes = 192 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 10), inputDiscreteLanes; + if (0 !== (lanes & 256)) return (return_highestLanePriority = 9), 256; + inputDiscreteLanes = 3584 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 8), inputDiscreteLanes; + if (0 !== (lanes & 4096)) return (return_highestLanePriority = 7), 4096; + inputDiscreteLanes = 4186112 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 6), inputDiscreteLanes; + inputDiscreteLanes = 62914560 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 5), inputDiscreteLanes; + if (lanes & 67108864) return (return_highestLanePriority = 4), 67108864; + if (0 !== (lanes & 134217728)) + return (return_highestLanePriority = 3), 134217728; + inputDiscreteLanes = 805306368 & lanes; + if (0 !== inputDiscreteLanes) + return (return_highestLanePriority = 2), inputDiscreteLanes; + if (0 !== (1073741824 & lanes)) + return (return_highestLanePriority = 1), 1073741824; + return_highestLanePriority = 8; + return lanes; +} +function schedulerPriorityToLanePriority(schedulerPriorityLevel) { + switch (schedulerPriorityLevel) { + case 99: + return 15; + case 98: + return 10; + case 97: + case 96: + return 8; + case 95: + return 2; + default: + return 0; + } +} +function lanePriorityToSchedulerPriority(lanePriority) { + switch (lanePriority) { + case 15: + case 14: + return 99; + case 13: + case 12: + case 11: + case 10: + return 98; + case 9: + case 8: + case 7: + case 6: + case 4: + case 5: + return 97; + case 3: + case 2: + case 1: + return 95; + case 0: + return 90; + default: + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); + } +} +function getNextLanes(root, wipLanes) { + var pendingLanes = root.pendingLanes; + if (0 === pendingLanes) return (return_highestLanePriority = 0); + var nextLanes = 0, + nextLanePriority = 0, + expiredLanes = root.expiredLanes, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes; + if (0 !== expiredLanes) + (nextLanes = expiredLanes), + (nextLanePriority = return_highestLanePriority = 15); + else if (((expiredLanes = pendingLanes & 134217727), 0 !== expiredLanes)) { + var nonIdleUnblockedLanes = expiredLanes & ~suspendedLanes; + 0 !== nonIdleUnblockedLanes + ? ((nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes)), + (nextLanePriority = return_highestLanePriority)) + : ((pingedLanes &= expiredLanes), + 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority))); + } else + (expiredLanes = pendingLanes & ~suspendedLanes), + 0 !== expiredLanes + ? ((nextLanes = getHighestPriorityLanes(expiredLanes)), + (nextLanePriority = return_highestLanePriority)) + : 0 !== pingedLanes && + ((nextLanes = getHighestPriorityLanes(pingedLanes)), + (nextLanePriority = return_highestLanePriority)); + if (0 === nextLanes) return 0; + nextLanes = 31 - clz32(nextLanes); + nextLanes = pendingLanes & (((0 > nextLanes ? 0 : 1 << nextLanes) << 1) - 1); + if ( + 0 !== wipLanes && + wipLanes !== nextLanes && + 0 === (wipLanes & suspendedLanes) + ) { + getHighestPriorityLanes(wipLanes); + if (nextLanePriority <= return_highestLanePriority) return wipLanes; + return_highestLanePriority = nextLanePriority; + } + wipLanes = root.entangledLanes; + if (0 !== wipLanes) + for (root = root.entanglements, wipLanes &= nextLanes; 0 < wipLanes; ) + (pendingLanes = 31 - clz32(wipLanes)), + (nextLanePriority = 1 << pendingLanes), + (nextLanes |= root[pendingLanes]), + (wipLanes &= ~nextLanePriority); + return nextLanes; +} +function getLanesToRetrySynchronouslyOnError(root) { + root = root.pendingLanes & -1073741825; + return 0 !== root ? root : root & 1073741824 ? 1073741824 : 0; +} +function findUpdateLane(lanePriority, wipLanes) { + switch (lanePriority) { + case 15: + return 1; + case 14: + return 2; + case 12: + return ( + (lanePriority = getHighestPriorityLane(24 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(10, wipLanes) : lanePriority + ); + case 10: + return ( + (lanePriority = getHighestPriorityLane(192 & ~wipLanes)), + 0 === lanePriority ? findUpdateLane(8, wipLanes) : lanePriority + ); + case 8: + return ( + (lanePriority = getHighestPriorityLane(3584 & ~wipLanes)), + 0 === lanePriority && + ((lanePriority = getHighestPriorityLane(4186112 & ~wipLanes)), + 0 === lanePriority && (lanePriority = 512)), + lanePriority + ); + case 2: + return ( + (wipLanes = getHighestPriorityLane(805306368 & ~wipLanes)), + 0 === wipLanes && (wipLanes = 268435456), + wipLanes + ); + } + throw Error( + "Invalid update priority: " + lanePriority + ". This is a bug in React." + ); +} +function getHighestPriorityLane(lanes) { + return lanes & -lanes; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial); + return laneMap; +} +function markRootUpdated(root, updateLane, eventTime) { + root.pendingLanes |= updateLane; + var higherPriorityLanes = updateLane - 1; + root.suspendedLanes &= higherPriorityLanes; + root.pingedLanes &= higherPriorityLanes; + root = root.eventTimes; + updateLane = 31 - clz32(updateLane); + root[updateLane] = eventTime; +} +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, + log = Math.log, + LN2 = Math.LN2; +function clz32Fallback(lanes) { + return 0 === lanes ? 32 : (31 - ((log(lanes) / LN2) | 0)) | 0; +} var Scheduler_runWithPriority = Scheduler.unstable_runWithPriority, Scheduler_scheduleCallback = Scheduler.unstable_scheduleCallback, Scheduler_cancelCallback = Scheduler.unstable_cancelCallback, Scheduler_shouldYield = Scheduler.unstable_shouldYield, Scheduler_requestPaint = Scheduler.unstable_requestPaint, - Scheduler_now = Scheduler.unstable_now, + Scheduler_now$1 = Scheduler.unstable_now, Scheduler_getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel, Scheduler_ImmediatePriority = Scheduler.unstable_ImmediatePriority, @@ -1720,7 +1985,7 @@ if ( null == tracing.__interactionsRef.current ) throw Error( - "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" + "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://reactjs.org/link/profiling" ); var fakeCallbackNode = {}, requestPaint = @@ -1728,12 +1993,12 @@ var fakeCallbackNode = {}, syncQueue = null, immediateQueueCallbackNode = null, isFlushingSyncQueue = !1, - initialTimeMs = Scheduler_now(), + initialTimeMs$1 = Scheduler_now$1(), now = - 1e4 > initialTimeMs - ? Scheduler_now + 1e4 > initialTimeMs$1 + ? Scheduler_now$1 : function() { - return Scheduler_now() - initialTimeMs; + return Scheduler_now$1() - initialTimeMs$1; }; function getCurrentPriorityLevel() { switch (Scheduler_getCurrentPriorityLevel()) { @@ -1775,16 +2040,6 @@ function scheduleCallback(reactPriorityLevel, callback, options) { reactPriorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel); return Scheduler_scheduleCallback(reactPriorityLevel, callback, options); } -function scheduleSyncCallback(callback) { - null === syncQueue - ? ((syncQueue = [callback]), - (immediateQueueCallbackNode = Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueueImpl - ))) - : syncQueue.push(callback); - return fakeCallbackNode; -} function flushSyncCallbackQueue() { if (null !== immediateQueueCallbackNode) { var node = immediateQueueCallbackNode; @@ -1819,19 +2074,7 @@ function flushSyncCallbackQueueImpl() { } } } -function inferPriorityFromExpirationTime(currentTime, expirationTime) { - if (1073741823 === expirationTime) return 99; - if (1 === expirationTime || 2 === expirationTime) return 95; - currentTime = - 10 * (1073741821 - expirationTime) - 10 * (1073741821 - currentTime); - return 0 >= currentTime - ? 99 - : 250 >= currentTime - ? 98 - : 5250 >= currentTime - ? 97 - : 95; -} +var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; function is(x, y) { return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y); } @@ -1857,42 +2100,39 @@ function shallowEqual(objA, objB) { return !1; return !0; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; +function describeFiber(fiber) { + switch (fiber.tag) { + case 5: + return describeComponentFrame(fiber.type, null, null); + case 16: + return describeComponentFrame("Lazy", null, null); + case 13: + return describeComponentFrame("Suspense", null, null); + case 19: + return describeComponentFrame("SuspenseList", null, null); + case 0: + case 2: + case 15: + return describeFunctionComponentFrame(fiber.type, null); + case 11: + return describeFunctionComponentFrame(fiber.type.render, null); + case 1: + return (fiber = describeFunctionComponentFrame(fiber.type, null)), fiber; + default: + return ""; + } +} function getStackByFiberInDevAndProd(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 3: - case 4: - case 6: - case 7: - case 10: - case 9: - var JSCompiler_inline_result = ""; - break a; - default: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource, - name = getComponentName(workInProgress.type); - JSCompiler_inline_result = null; - owner && (JSCompiler_inline_result = getComponentName(owner.type)); - owner = name; - name = ""; - source - ? (name = - " (at " + - source.fileName.replace(BEFORE_SLASH_RE, "") + - ":" + - source.lineNumber + - ")") - : JSCompiler_inline_result && - (name = " (created by " + JSCompiler_inline_result + ")"); - JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress.return; - } while (workInProgress); - return info; + try { + var info = ""; + do + (info += describeFiber(workInProgress)), + (workInProgress = workInProgress.return); + while (workInProgress); + return info; + } catch (x) { + return "\nError generating stack: " + x.message + "\n" + x.stack; + } } function resolveDefaultProps(Component, baseProps) { if (Component && Component.defaultProps) { @@ -1901,10 +2141,11 @@ function resolveDefaultProps(Component, baseProps) { for (var propName in Component) void 0 === baseProps[propName] && (baseProps[propName] = Component[propName]); + return baseProps; } return baseProps; } -var valueCursor = { current: null }, +var valueCursor = createCursor(null), currentlyRenderingFiber = null, lastContextDependency = null, lastContextWithAllBitsObserved = null; @@ -1916,31 +2157,29 @@ function popProvider(providerFiber) { pop(valueCursor); providerFiber.type._context._currentValue = currentValue; } -function scheduleWorkOnParentPath(parent, renderExpirationTime) { +function scheduleWorkOnParentPath(parent, renderLanes) { for (; null !== parent; ) { var alternate = parent.alternate; - if (parent.childExpirationTime < renderExpirationTime) - (parent.childExpirationTime = renderExpirationTime), - null !== alternate && - alternate.childExpirationTime < renderExpirationTime && - (alternate.childExpirationTime = renderExpirationTime); - else if ( - null !== alternate && - alternate.childExpirationTime < renderExpirationTime - ) - alternate.childExpirationTime = renderExpirationTime; - else break; + if ((parent.childLanes & renderLanes) === renderLanes) + if ( + null === alternate || + (alternate.childLanes & renderLanes) === renderLanes + ) + break; + else alternate.childLanes |= renderLanes; + else + (parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes); parent = parent.return; } } -function prepareToReadContext(workInProgress, renderExpirationTime) { +function prepareToReadContext(workInProgress, renderLanes) { currentlyRenderingFiber = workInProgress; lastContextWithAllBitsObserved = lastContextDependency = null; workInProgress = workInProgress.dependencies; null !== workInProgress && null !== workInProgress.firstContext && - (workInProgress.expirationTime >= renderExpirationTime && - (didReceiveUpdate = !0), + (0 !== (workInProgress.lanes & renderLanes) && (didReceiveUpdate = !0), (workInProgress.firstContext = null)); } function readContext(context, observedBits) { @@ -1959,7 +2198,7 @@ function readContext(context, observedBits) { ); lastContextDependency = observedBits; currentlyRenderingFiber.dependencies = { - expirationTime: 0, + lanes: 0, firstContext: observedBits, responders: null }; @@ -1971,7 +2210,8 @@ var hasForceUpdate = !1; function initializeUpdateQueue(fiber) { fiber.updateQueue = { baseState: fiber.memoizedState, - baseQueue: null, + firstBaseUpdate: null, + lastBaseUpdate: null, shared: { pending: null }, effects: null }; @@ -1981,21 +2221,21 @@ function cloneUpdateQueue(current, workInProgress) { workInProgress.updateQueue === current && (workInProgress.updateQueue = { baseState: current.baseState, - baseQueue: current.baseQueue, + firstBaseUpdate: current.firstBaseUpdate, + lastBaseUpdate: current.lastBaseUpdate, shared: current.shared, effects: current.effects }); } -function createUpdate(expirationTime, suspenseConfig) { - expirationTime = { - expirationTime: expirationTime, - suspenseConfig: suspenseConfig, +function createUpdate(eventTime, lane) { + return { + eventTime: eventTime, + lane: lane, tag: 0, payload: null, callback: null, next: null }; - return (expirationTime.next = expirationTime); } function enqueueUpdate(fiber, update) { fiber = fiber.updateQueue; @@ -2008,132 +2248,177 @@ function enqueueUpdate(fiber, update) { fiber.pending = update; } } -function enqueueCapturedUpdate(workInProgress, update) { - var current = workInProgress.alternate; - null !== current && cloneUpdateQueue(current, workInProgress); - workInProgress = workInProgress.updateQueue; - current = workInProgress.baseQueue; - null === current - ? ((workInProgress.baseQueue = update.next = update), - (update.next = update)) - : ((update.next = current.next), (current.next = update)); +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + var queue = workInProgress.updateQueue, + current = workInProgress.alternate; + if ( + null !== current && + ((current = current.updateQueue), queue === current) + ) { + var newFirst = null, + newLast = null; + queue = queue.firstBaseUpdate; + if (null !== queue) { + do { + var clone = { + eventTime: queue.eventTime, + lane: queue.lane, + tag: queue.tag, + payload: queue.payload, + callback: queue.callback, + next: null + }; + null === newLast + ? (newFirst = newLast = clone) + : (newLast = newLast.next = clone); + queue = queue.next; + } while (null !== queue); + null === newLast + ? (newFirst = newLast = capturedUpdate) + : (newLast = newLast.next = capturedUpdate); + } else newFirst = newLast = capturedUpdate; + queue = { + baseState: current.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: current.shared, + effects: current.effects + }; + workInProgress.updateQueue = queue; + return; + } + workInProgress = queue.lastBaseUpdate; + null === workInProgress + ? (queue.firstBaseUpdate = capturedUpdate) + : (workInProgress.next = capturedUpdate); + queue.lastBaseUpdate = capturedUpdate; } function processUpdateQueue( workInProgress$jscomp$0, props, instance, - renderExpirationTime + renderLanes ) { var queue = workInProgress$jscomp$0.updateQueue; hasForceUpdate = !1; - var baseQueue = queue.baseQueue, + var firstBaseUpdate = queue.firstBaseUpdate, + lastBaseUpdate = queue.lastBaseUpdate, pendingQueue = queue.shared.pending; if (null !== pendingQueue) { - if (null !== baseQueue) { - var baseFirst = baseQueue.next; - baseQueue.next = pendingQueue.next; - pendingQueue.next = baseFirst; - } - baseQueue = pendingQueue; queue.shared.pending = null; - baseFirst = workInProgress$jscomp$0.alternate; - null !== baseFirst && - ((baseFirst = baseFirst.updateQueue), - null !== baseFirst && (baseFirst.baseQueue = pendingQueue)); + var lastPendingUpdate = pendingQueue, + firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; + null === lastBaseUpdate + ? (firstBaseUpdate = firstPendingUpdate) + : (lastBaseUpdate.next = firstPendingUpdate); + lastBaseUpdate = lastPendingUpdate; + var current = workInProgress$jscomp$0.alternate; + if (null !== current) { + current = current.updateQueue; + var currentLastBaseUpdate = current.lastBaseUpdate; + currentLastBaseUpdate !== lastBaseUpdate && + (null === currentLastBaseUpdate + ? (current.firstBaseUpdate = firstPendingUpdate) + : (currentLastBaseUpdate.next = firstPendingUpdate), + (current.lastBaseUpdate = lastPendingUpdate)); + } } - if (null !== baseQueue) { - baseFirst = baseQueue.next; - var newState = queue.baseState, - newExpirationTime = 0, - newBaseState = null, - newBaseQueueFirst = null, - newBaseQueueLast = null; - if (null !== baseFirst) { - var update = baseFirst; - do { - pendingQueue = update.expirationTime; - if (pendingQueue < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, + if (null !== firstBaseUpdate) { + currentLastBaseUpdate = queue.baseState; + lastBaseUpdate = 0; + current = firstPendingUpdate = lastPendingUpdate = null; + do { + pendingQueue = firstBaseUpdate.lane; + var updateEventTime = firstBaseUpdate.eventTime; + if ((renderLanes & pendingQueue) === pendingQueue) { + null !== current && + (current = current.next = { + eventTime: updateEventTime, + lane: 0, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, next: null - }; - null === newBaseQueueLast - ? ((newBaseQueueFirst = newBaseQueueLast = clone), - (newBaseState = newState)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - pendingQueue > newExpirationTime && - (newExpirationTime = pendingQueue); - } else { - null !== newBaseQueueLast && - (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, - tag: update.tag, - payload: update.payload, - callback: update.callback, - next: null - }); - markRenderEventTimeAndConfig(pendingQueue, update.suspenseConfig); - a: { - var workInProgress = workInProgress$jscomp$0, - update$jscomp$0 = update; - pendingQueue = props; - clone = instance; - switch (update$jscomp$0.tag) { - case 1: - workInProgress = update$jscomp$0.payload; - if ("function" === typeof workInProgress) { - newState = workInProgress.call(clone, newState, pendingQueue); - break a; - } - newState = workInProgress; - break a; - case 3: - workInProgress.effectTag = - (workInProgress.effectTag & -4097) | 64; - case 0: - workInProgress = update$jscomp$0.payload; - pendingQueue = - "function" === typeof workInProgress - ? workInProgress.call(clone, newState, pendingQueue) - : workInProgress; - if (null === pendingQueue || void 0 === pendingQueue) break a; - newState = Object.assign({}, newState, pendingQueue); + }); + a: { + var workInProgress = workInProgress$jscomp$0, + update = firstBaseUpdate; + pendingQueue = props; + updateEventTime = instance; + switch (update.tag) { + case 1: + workInProgress = update.payload; + if ("function" === typeof workInProgress) { + currentLastBaseUpdate = workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ); break a; - case 2: - hasForceUpdate = !0; - } + } + currentLastBaseUpdate = workInProgress; + break a; + case 3: + workInProgress.flags = (workInProgress.flags & -8193) | 64; + case 0: + workInProgress = update.payload; + pendingQueue = + "function" === typeof workInProgress + ? workInProgress.call( + updateEventTime, + currentLastBaseUpdate, + pendingQueue + ) + : workInProgress; + if (null === pendingQueue || void 0 === pendingQueue) break a; + currentLastBaseUpdate = Object.assign( + {}, + currentLastBaseUpdate, + pendingQueue + ); + break a; + case 2: + hasForceUpdate = !0; } - null !== update.callback && - ((workInProgress$jscomp$0.effectTag |= 32), - (pendingQueue = queue.effects), - null === pendingQueue - ? (queue.effects = [update]) - : pendingQueue.push(update)); } - update = update.next; - if (null === update || update === baseFirst) - if (((pendingQueue = queue.shared.pending), null === pendingQueue)) - break; - else - (update = baseQueue.next = pendingQueue.next), - (pendingQueue.next = baseFirst), - (queue.baseQueue = baseQueue = pendingQueue), - (queue.shared.pending = null); - } while (1); - } - null === newBaseQueueLast - ? (newBaseState = newState) - : (newBaseQueueLast.next = newBaseQueueFirst); - queue.baseState = newBaseState; - queue.baseQueue = newBaseQueueLast; - markUnprocessedUpdateTime(newExpirationTime); - workInProgress$jscomp$0.expirationTime = newExpirationTime; - workInProgress$jscomp$0.memoizedState = newState; + null !== firstBaseUpdate.callback && + ((workInProgress$jscomp$0.flags |= 32), + (pendingQueue = queue.effects), + null === pendingQueue + ? (queue.effects = [firstBaseUpdate]) + : pendingQueue.push(firstBaseUpdate)); + } else + (updateEventTime = { + eventTime: updateEventTime, + lane: pendingQueue, + tag: firstBaseUpdate.tag, + payload: firstBaseUpdate.payload, + callback: firstBaseUpdate.callback, + next: null + }), + null === current + ? ((firstPendingUpdate = current = updateEventTime), + (lastPendingUpdate = currentLastBaseUpdate)) + : (current = current.next = updateEventTime), + (lastBaseUpdate |= pendingQueue); + firstBaseUpdate = firstBaseUpdate.next; + if (null === firstBaseUpdate) + if (((pendingQueue = queue.shared.pending), null === pendingQueue)) + break; + else + (firstBaseUpdate = pendingQueue.next), + (pendingQueue.next = null), + (queue.lastBaseUpdate = pendingQueue), + (queue.shared.pending = null); + } while (1); + null === current && (lastPendingUpdate = currentLastBaseUpdate); + queue.baseState = lastPendingUpdate; + queue.firstBaseUpdate = firstPendingUpdate; + queue.lastBaseUpdate = current; + workInProgressRootSkippedLanes |= lastBaseUpdate; + workInProgress$jscomp$0.lanes = lastBaseUpdate; + workInProgress$jscomp$0.memoizedState = currentLastBaseUpdate; } } function commitUpdateQueue(finishedWork, finishedQueue, instance) { @@ -2158,8 +2443,7 @@ function commitUpdateQueue(finishedWork, finishedQueue, instance) { } } } -var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig, - emptyRefsObject = new React.Component().refs; +var emptyRefsObject = new React.Component().refs; function applyDerivedStateFromProps( workInProgress, ctor, @@ -2173,54 +2457,45 @@ function applyDerivedStateFromProps( ? ctor : Object.assign({}, ctor, getDerivedStateFromProps); workInProgress.memoizedState = getDerivedStateFromProps; - 0 === workInProgress.expirationTime && + 0 === workInProgress.lanes && (workInProgress.updateQueue.baseState = getDerivedStateFromProps); } var classComponentUpdater = { isMounted: function(component) { - return (component = component._reactInternalFiber) + return (component = component._reactInternals) ? getNearestMountedFiber(component) === component : !1; }, enqueueSetState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueReplaceState: function(inst, payload, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 1; - suspenseConfig.payload = payload; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 1; + update.payload = payload; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); }, enqueueForceUpdate: function(inst, callback) { - inst = inst._reactInternalFiber; - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, inst, suspenseConfig); - suspenseConfig = createUpdate(currentTime, suspenseConfig); - suspenseConfig.tag = 2; - void 0 !== callback && - null !== callback && - (suspenseConfig.callback = callback); - enqueueUpdate(inst, suspenseConfig); - scheduleWork(inst, currentTime); + inst = inst._reactInternals; + var eventTime = requestEventTime(), + lane = requestUpdateLane(inst), + update = createUpdate(eventTime, lane); + update.tag = 2; + void 0 !== callback && null !== callback && (update.callback = callback); + enqueueUpdate(inst, update); + scheduleUpdateOnFiber(inst, lane, eventTime); } }; function checkShouldComponentUpdate( @@ -2258,7 +2533,7 @@ function constructClassInstance(workInProgress, ctor, props) { null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; ctor.updater = classComponentUpdater; workInProgress.stateNode = ctor; - ctor._reactInternalFiber = workInProgress; + ctor._reactInternals = workInProgress; isLegacyContextConsumer && ((workInProgress = workInProgress.stateNode), (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), @@ -2279,12 +2554,7 @@ function callComponentWillReceiveProps( instance.state !== workInProgress && classComponentUpdater.enqueueReplaceState(instance, instance.state, null); } -function mountClassInstance( - workInProgress, - ctor, - newProps, - renderExpirationTime -) { +function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { var instance = workInProgress.stateNode; instance.props = newProps; instance.state = workInProgress.memoizedState; @@ -2297,7 +2567,7 @@ function mountClassInstance( ? previousContext : contextStackCursor.current), (instance.context = getMaskedContext(workInProgress, contextType))); - processUpdateQueue(workInProgress, newProps, instance, renderExpirationTime); + processUpdateQueue(workInProgress, newProps, instance, renderLanes); instance.state = workInProgress.memoizedState; contextType = ctor.getDerivedStateFromProps; "function" === typeof contextType && @@ -2314,15 +2584,10 @@ function mountClassInstance( instance.UNSAFE_componentWillMount(), ctor !== instance.state && classComponentUpdater.enqueueReplaceState(instance, instance.state, null), - processUpdateQueue( - workInProgress, - newProps, - instance, - renderExpirationTime - ), + processUpdateQueue(workInProgress, newProps, instance, renderLanes), (instance.state = workInProgress.memoizedState)); "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); } var isArray = Array.isArray; function coerceRef(returnFiber, current, element) { @@ -2337,7 +2602,7 @@ function coerceRef(returnFiber, current, element) { if (element) { if (1 !== element.tag) throw Error( - "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://fb.me/react-strict-mode-string-ref" + "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref" ); var inst = element.stateNode; } @@ -2371,7 +2636,7 @@ function coerceRef(returnFiber, current, element) { throw Error( "Element ref was specified as a string (" + returnFiber + - ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information." + ") but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://reactjs.org/link/refs-must-have-owner for more information." ); } return returnFiber; @@ -2383,7 +2648,7 @@ function throwOnInvalidObjectType(returnFiber, newChild) { ("[object Object]" === Object.prototype.toString.call(newChild) ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : newChild) + - ")." + "). If you meant to render a collection of children, use an array instead." ); } function ChildReconciler(shouldTrackSideEffects) { @@ -2395,7 +2660,7 @@ function ChildReconciler(shouldTrackSideEffects) { (returnFiber.lastEffect = childToDelete)) : (returnFiber.firstEffect = returnFiber.lastEffect = childToDelete); childToDelete.nextEffect = null; - childToDelete.effectTag = 8; + childToDelete.flags = 8; } } function deleteRemainingChildren(returnFiber, currentFirstChild) { @@ -2427,26 +2692,22 @@ function ChildReconciler(shouldTrackSideEffects) { return ( (newIndex = newIndex.index), newIndex < lastPlacedIndex - ? ((newFiber.effectTag = 2), lastPlacedIndex) + ? ((newFiber.flags = 2), lastPlacedIndex) : newIndex ); - newFiber.effectTag = 2; + newFiber.flags = 2; return lastPlacedIndex; } function placeSingleChild(newFiber) { shouldTrackSideEffects && null === newFiber.alternate && - (newFiber.effectTag = 2); + (newFiber.flags = 2); return newFiber; } - function updateTextNode(returnFiber, current, textContent, expirationTime) { + function updateTextNode(returnFiber, current, textContent, lanes) { if (null === current || 6 !== current.tag) return ( - (current = createFiberFromText( - textContent, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromText(textContent, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2454,27 +2715,27 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateElement(returnFiber, current, element, expirationTime) { + function updateElement(returnFiber, current, element, lanes) { if (null !== current && current.elementType === element.type) return ( - (expirationTime = useFiber(current, element.props)), - (expirationTime.ref = coerceRef(returnFiber, current, element)), - (expirationTime.return = returnFiber), - expirationTime + (lanes = useFiber(current, element.props)), + (lanes.ref = coerceRef(returnFiber, current, element)), + (lanes.return = returnFiber), + lanes ); - expirationTime = createFiberFromTypeAndProps( + lanes = createFiberFromTypeAndProps( element.type, element.key, element.props, null, returnFiber.mode, - expirationTime + lanes ); - expirationTime.ref = coerceRef(returnFiber, current, element); - expirationTime.return = returnFiber; - return expirationTime; + lanes.ref = coerceRef(returnFiber, current, element); + lanes.return = returnFiber; + return lanes; } - function updatePortal(returnFiber, current, portal, expirationTime) { + function updatePortal(returnFiber, current, portal, lanes) { if ( null === current || 4 !== current.tag || @@ -2482,11 +2743,7 @@ function ChildReconciler(shouldTrackSideEffects) { current.stateNode.implementation !== portal.implementation ) return ( - (current = createFiberFromPortal( - portal, - returnFiber.mode, - expirationTime - )), + (current = createFiberFromPortal(portal, returnFiber.mode, lanes)), (current.return = returnFiber), current ); @@ -2494,13 +2751,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function updateFragment(returnFiber, current, fragment, expirationTime, key) { + function updateFragment(returnFiber, current, fragment, lanes, key) { if (null === current || 7 !== current.tag) return ( (current = createFiberFromFragment( fragment, returnFiber.mode, - expirationTime, + lanes, key )), (current.return = returnFiber), @@ -2510,13 +2767,13 @@ function ChildReconciler(shouldTrackSideEffects) { current.return = returnFiber; return current; } - function createChild(returnFiber, newChild, expirationTime) { + function createChild(returnFiber, newChild, lanes) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (newChild = createFiberFromText( "" + newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2525,24 +2782,24 @@ function ChildReconciler(shouldTrackSideEffects) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: return ( - (expirationTime = createFiberFromTypeAndProps( + (lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef(returnFiber, null, newChild)), - (expirationTime.return = returnFiber), - expirationTime + (lanes.ref = coerceRef(returnFiber, null, newChild)), + (lanes.return = returnFiber), + lanes ); case REACT_PORTAL_TYPE: return ( (newChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes )), (newChild.return = returnFiber), newChild @@ -2553,7 +2810,7 @@ function ChildReconciler(shouldTrackSideEffects) { (newChild = createFiberFromFragment( newChild, returnFiber.mode, - expirationTime, + lanes, null )), (newChild.return = returnFiber), @@ -2563,12 +2820,12 @@ function ChildReconciler(shouldTrackSideEffects) { } return null; } - function updateSlot(returnFiber, oldFiber, newChild, expirationTime) { + function updateSlot(returnFiber, oldFiber, newChild, lanes) { var key = null !== oldFiber ? oldFiber.key : null; if ("string" === typeof newChild || "number" === typeof newChild) return null !== key ? null - : updateTextNode(returnFiber, oldFiber, "" + newChild, expirationTime); + : updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: @@ -2578,26 +2835,20 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChild.props.children, - expirationTime, + lanes, key ) - : updateElement(returnFiber, oldFiber, newChild, expirationTime) + : updateElement(returnFiber, oldFiber, newChild, lanes) : null; case REACT_PORTAL_TYPE: return newChild.key === key - ? updatePortal(returnFiber, oldFiber, newChild, expirationTime) + ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; } if (isArray(newChild) || getIteratorFn(newChild)) return null !== key ? null - : updateFragment( - returnFiber, - oldFiber, - newChild, - expirationTime, - null - ); + : updateFragment(returnFiber, oldFiber, newChild, lanes, null); throwOnInvalidObjectType(returnFiber, newChild); } return null; @@ -2607,17 +2858,12 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChild, - expirationTime + lanes ) { if ("string" === typeof newChild || "number" === typeof newChild) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateTextNode( - returnFiber, - existingChildren, - "" + newChild, - expirationTime - ) + updateTextNode(returnFiber, existingChildren, "" + newChild, lanes) ); if ("object" === typeof newChild && null !== newChild) { switch (newChild.$$typeof) { @@ -2632,15 +2878,10 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, existingChildren, newChild.props.children, - expirationTime, + lanes, newChild.key ) - : updateElement( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + : updateElement(returnFiber, existingChildren, newChild, lanes) ); case REACT_PORTAL_TYPE: return ( @@ -2648,24 +2889,13 @@ function ChildReconciler(shouldTrackSideEffects) { existingChildren.get( null === newChild.key ? newIdx : newChild.key ) || null), - updatePortal( - returnFiber, - existingChildren, - newChild, - expirationTime - ) + updatePortal(returnFiber, existingChildren, newChild, lanes) ); } if (isArray(newChild) || getIteratorFn(newChild)) return ( (existingChildren = existingChildren.get(newIdx) || null), - updateFragment( - returnFiber, - existingChildren, - newChild, - expirationTime, - null - ) + updateFragment(returnFiber, existingChildren, newChild, lanes, null) ); throwOnInvalidObjectType(returnFiber, newChild); } @@ -2675,7 +2905,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildren, - expirationTime + lanes ) { for ( var resultingFirstChild = null, @@ -2693,7 +2923,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, oldFiber, newChildren[newIdx], - expirationTime + lanes ); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); @@ -2716,11 +2946,7 @@ function ChildReconciler(shouldTrackSideEffects) { ); if (null === oldFiber) { for (; newIdx < newChildren.length; newIdx++) - (oldFiber = createChild( - returnFiber, - newChildren[newIdx], - expirationTime - )), + (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)), null !== oldFiber && ((currentFirstChild = placeChild( oldFiber, @@ -2743,7 +2969,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, newIdx, newChildren[newIdx], - expirationTime + lanes )), null !== nextOldFiber && (shouldTrackSideEffects && @@ -2770,7 +2996,7 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChildrenIterable, - expirationTime + lanes ) { var iteratorFn = getIteratorFn(newChildrenIterable); if ("function" !== typeof iteratorFn) @@ -2792,12 +3018,7 @@ function ChildReconciler(shouldTrackSideEffects) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) : (nextOldFiber = oldFiber.sibling); - var newFiber = updateSlot( - returnFiber, - oldFiber, - step.value, - expirationTime - ); + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); if (null === newFiber) { null === oldFiber && (oldFiber = nextOldFiber); break; @@ -2817,7 +3038,7 @@ function ChildReconciler(shouldTrackSideEffects) { return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { for (; !step.done; newIdx++, step = newChildrenIterable.next()) - (step = createChild(returnFiber, step.value, expirationTime)), + (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), null === previousNewFiber @@ -2831,13 +3052,7 @@ function ChildReconciler(shouldTrackSideEffects) { !step.done; newIdx++, step = newChildrenIterable.next() ) - (step = updateFromMap( - oldFiber, - returnFiber, - newIdx, - step.value, - expirationTime - )), + (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && (shouldTrackSideEffects && null !== step.alternate && @@ -2853,7 +3068,7 @@ function ChildReconciler(shouldTrackSideEffects) { }); return iteratorFn; } - return function(returnFiber, currentFirstChild, newChild, expirationTime) { + return function(returnFiber, currentFirstChild, newChild, lanes) { var isUnkeyedTopLevelFragment = "object" === typeof newChild && null !== newChild && @@ -2919,26 +3134,26 @@ function ChildReconciler(shouldTrackSideEffects) { ? ((currentFirstChild = createFiberFromFragment( newChild.props.children, returnFiber.mode, - expirationTime, + lanes, newChild.key )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)) - : ((expirationTime = createFiberFromTypeAndProps( + : ((lanes = createFiberFromTypeAndProps( newChild.type, newChild.key, newChild.props, null, returnFiber.mode, - expirationTime + lanes )), - (expirationTime.ref = coerceRef( + (lanes.ref = coerceRef( returnFiber, currentFirstChild, newChild )), - (expirationTime.return = returnFiber), - (returnFiber = expirationTime)); + (lanes.return = returnFiber), + (returnFiber = lanes)); } return placeSingleChild(returnFiber); case REACT_PORTAL_TYPE: @@ -2977,7 +3192,7 @@ function ChildReconciler(shouldTrackSideEffects) { currentFirstChild = createFiberFromPortal( newChild, returnFiber.mode, - expirationTime + lanes ); currentFirstChild.return = returnFiber; returnFiber = currentFirstChild; @@ -2996,7 +3211,7 @@ function ChildReconciler(shouldTrackSideEffects) { (currentFirstChild = createFiberFromText( newChild, returnFiber.mode, - expirationTime + lanes )), (currentFirstChild.return = returnFiber), (returnFiber = currentFirstChild)), @@ -3007,25 +3222,26 @@ function ChildReconciler(shouldTrackSideEffects) { returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); if (getIteratorFn(newChild)) return reconcileChildrenIterator( returnFiber, currentFirstChild, newChild, - expirationTime + lanes ); isObject && throwOnInvalidObjectType(returnFiber, newChild); if ("undefined" === typeof newChild && !isUnkeyedTopLevelFragment) switch (returnFiber.tag) { case 1: case 0: - throw ((returnFiber = returnFiber.type), - Error( - (returnFiber.displayName || returnFiber.name || "Component") + + case 11: + case 15: + throw Error( + (getComponentName(returnFiber.type) || "Component") + "(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null." - )); + ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; @@ -3033,9 +3249,9 @@ function ChildReconciler(shouldTrackSideEffects) { var reconcileChildFibers = ChildReconciler(!0), mountChildFibers = ChildReconciler(!1), NO_CONTEXT = {}, - contextStackCursor$1 = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + contextStackCursor$1 = createCursor(NO_CONTEXT), + contextFiberStackCursor = createCursor(NO_CONTEXT), + rootInstanceStackCursor = createCursor(NO_CONTEXT); function requiredContext(c) { if (c === NO_CONTEXT) throw Error( @@ -3058,26 +3274,26 @@ function popHostContainer() { function pushHostContext(fiber) { requiredContext(rootInstanceStackCursor.current); var context = requiredContext(contextStackCursor$1.current); - var nextContext = fiber.type; - nextContext = - "AndroidTextInput" === nextContext || - "RCTMultilineTextInputView" === nextContext || - "RCTSinglelineTextInputView" === nextContext || - "RCTText" === nextContext || - "RCTVirtualText" === nextContext; - nextContext = - context.isInAParentText !== nextContext - ? { isInAParentText: nextContext } + var JSCompiler_inline_result = fiber.type; + JSCompiler_inline_result = + "AndroidTextInput" === JSCompiler_inline_result || + "RCTMultilineTextInputView" === JSCompiler_inline_result || + "RCTSinglelineTextInputView" === JSCompiler_inline_result || + "RCTText" === JSCompiler_inline_result || + "RCTVirtualText" === JSCompiler_inline_result; + JSCompiler_inline_result = + context.isInAParentText !== JSCompiler_inline_result + ? { isInAParentText: JSCompiler_inline_result } : context; - context !== nextContext && + context !== JSCompiler_inline_result && (push(contextFiberStackCursor, fiber), - push(contextStackCursor$1, nextContext)); + push(contextStackCursor$1, JSCompiler_inline_result)); } function popHostContext(fiber) { contextFiberStackCursor.current === fiber && (pop(contextStackCursor$1), pop(contextFiberStackCursor)); } -var suspenseStackCursor = { current: 0 }; +var suspenseStackCursor = createCursor(0); function findFirstSuspended(row) { for (var node = row; null !== node; ) { if (13 === node.tag) { @@ -3085,7 +3301,7 @@ function findFirstSuspended(row) { if (null !== state && (null === state.dehydrated || shim() || shim())) return node; } else if (19 === node.tag && void 0 !== node.memoizedProps.revealOrder) { - if (0 !== (node.effectTag & 64)) return node; + if (0 !== (node.flags & 64)) return node; } else if (null !== node.child) { node.child.return = node; node = node.child; @@ -3101,19 +3317,23 @@ function findFirstSuspended(row) { } return null; } -function createDeprecatedResponderListener(responder, props) { - return { responder: responder, props: props }; +var workInProgressSources = []; +function resetWorkInProgressVersions() { + for (var i = 0; i < workInProgressSources.length; i++) + workInProgressSources[i]._workInProgressVersionPrimary = null; + workInProgressSources.length = 0; } -var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher, +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig, - renderExpirationTime = 0, + renderLanes = 0, currentlyRenderingFiber$1 = null, currentHook = null, workInProgressHook = null, - didScheduleRenderPhaseUpdate = !1; + didScheduleRenderPhaseUpdate = !1, + didScheduleRenderPhaseUpdateDuringThisPass = !1; function throwInvalidHookError() { throw Error( - "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." + "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } function areHookInputsEqual(nextDeps, prevDeps) { @@ -3128,36 +3348,36 @@ function renderWithHooks( Component, props, secondArg, - nextRenderExpirationTime + nextRenderLanes ) { - renderExpirationTime = nextRenderExpirationTime; + renderLanes = nextRenderLanes; currentlyRenderingFiber$1 = workInProgress; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - workInProgress.expirationTime = 0; - ReactCurrentDispatcher.current = + workInProgress.lanes = 0; + ReactCurrentDispatcher$1.current = null === current || null === current.memoizedState ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; current = Component(props, secondArg); - if (workInProgress.expirationTime === renderExpirationTime) { - nextRenderExpirationTime = 0; + if (didScheduleRenderPhaseUpdateDuringThisPass) { + nextRenderLanes = 0; do { - workInProgress.expirationTime = 0; - if (!(25 > nextRenderExpirationTime)) + didScheduleRenderPhaseUpdateDuringThisPass = !1; + if (!(25 > nextRenderLanes)) throw Error( "Too many re-renders. React limits the number of renders to prevent an infinite loop." ); - nextRenderExpirationTime += 1; + nextRenderLanes += 1; workInProgressHook = currentHook = null; workInProgress.updateQueue = null; - ReactCurrentDispatcher.current = HooksDispatcherOnRerender; + ReactCurrentDispatcher$1.current = HooksDispatcherOnRerender; current = Component(props, secondArg); - } while (workInProgress.expirationTime === renderExpirationTime); + } while (didScheduleRenderPhaseUpdateDuringThisPass); } - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; workInProgress = null !== currentHook && null !== currentHook.next; - renderExpirationTime = 0; + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; didScheduleRenderPhaseUpdate = !1; if (workInProgress) @@ -3238,40 +3458,34 @@ function updateReducer(reducer) { var newBaseQueueLast = (baseFirst = pendingQueue = null), update = baseQueue; do { - var updateExpirationTime = update.expirationTime; - if (updateExpirationTime < renderExpirationTime) { - var clone = { - expirationTime: update.expirationTime, - suspenseConfig: update.suspenseConfig, - action: update.action, - eagerReducer: update.eagerReducer, - eagerState: update.eagerState, - next: null - }; - null === newBaseQueueLast - ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) - : (newBaseQueueLast = newBaseQueueLast.next = clone); - updateExpirationTime > currentlyRenderingFiber$1.expirationTime && - ((currentlyRenderingFiber$1.expirationTime = updateExpirationTime), - markUnprocessedUpdateTime(updateExpirationTime)); - } else + var updateLane = update.lane; + if ((renderLanes & updateLane) === updateLane) null !== newBaseQueueLast && (newBaseQueueLast = newBaseQueueLast.next = { - expirationTime: 1073741823, - suspenseConfig: update.suspenseConfig, + lane: 0, action: update.action, eagerReducer: update.eagerReducer, eagerState: update.eagerState, next: null }), - markRenderEventTimeAndConfig( - updateExpirationTime, - update.suspenseConfig - ), (current = update.eagerReducer === reducer ? update.eagerState : reducer(current, update.action)); + else { + var clone = { + lane: updateLane, + action: update.action, + eagerReducer: update.eagerReducer, + eagerState: update.eagerState, + next: null + }; + null === newBaseQueueLast + ? ((baseFirst = newBaseQueueLast = clone), (pendingQueue = current)) + : (newBaseQueueLast = newBaseQueueLast.next = clone); + currentlyRenderingFiber$1.lanes |= updateLane; + workInProgressRootSkippedLanes |= updateLane; + } update = update.next; } while (null !== update && update !== baseQueue); null === newBaseQueueLast @@ -3308,6 +3522,114 @@ function rerenderReducer(reducer) { } return [newState, dispatch]; } +function readFromUnsubcribedMutableSource(root, source, getSnapshot) { + var getVersion = source._getVersion; + getVersion = getVersion(source._source); + var JSCompiler_inline_result = source._workInProgressVersionPrimary; + if (null !== JSCompiler_inline_result) + root = JSCompiler_inline_result === getVersion; + else if ( + ((root = root.mutableReadLanes), (root = (renderLanes & root) === root)) + ) + (source._workInProgressVersionPrimary = getVersion), + workInProgressSources.push(source); + if (root) return getSnapshot(source._source); + workInProgressSources.push(source); + throw Error( + "Cannot read from mutable source during the current render without tearing. This is a bug in React. Please file an issue." + ); +} +function useMutableSource(hook, source, getSnapshot, subscribe) { + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + var getVersion = source._getVersion, + version = getVersion(source._source), + dispatcher = ReactCurrentDispatcher$1.current, + _dispatcher$useState = dispatcher.useState(function() { + return readFromUnsubcribedMutableSource(root, source, getSnapshot); + }), + setSnapshot = _dispatcher$useState[1], + snapshot = _dispatcher$useState[0]; + _dispatcher$useState = workInProgressHook; + var memoizedState = hook.memoizedState, + refs = memoizedState.refs, + prevGetSnapshot = refs.getSnapshot, + prevSource = memoizedState.source; + memoizedState = memoizedState.subscribe; + var fiber = currentlyRenderingFiber$1; + hook.memoizedState = { refs: refs, source: source, subscribe: subscribe }; + dispatcher.useEffect( + function() { + refs.getSnapshot = getSnapshot; + refs.setSnapshot = setSnapshot; + var maybeNewVersion = getVersion(source._source); + if (!objectIs(version, maybeNewVersion)) { + maybeNewVersion = getSnapshot(source._source); + objectIs(snapshot, maybeNewVersion) || + (setSnapshot(maybeNewVersion), + (maybeNewVersion = requestUpdateLane(fiber)), + (root.mutableReadLanes |= maybeNewVersion & root.pendingLanes)); + maybeNewVersion = root.mutableReadLanes; + root.entangledLanes |= maybeNewVersion; + for ( + var entanglements = root.entanglements, lanes = maybeNewVersion; + 0 < lanes; + + ) { + var index$13 = 31 - clz32(lanes), + lane = 1 << index$13; + entanglements[index$13] |= maybeNewVersion; + lanes &= ~lane; + } + } + }, + [getSnapshot, source, subscribe] + ); + dispatcher.useEffect( + function() { + return subscribe(source._source, function() { + var latestGetSnapshot = refs.getSnapshot, + latestSetSnapshot = refs.setSnapshot; + try { + latestSetSnapshot(latestGetSnapshot(source._source)); + var lane = requestUpdateLane(fiber); + root.mutableReadLanes |= lane & root.pendingLanes; + } catch (error) { + latestSetSnapshot(function() { + throw error; + }); + } + }); + }, + [source, subscribe] + ); + (objectIs(prevGetSnapshot, getSnapshot) && + objectIs(prevSource, source) && + objectIs(memoizedState, subscribe)) || + ((hook = { + pending: null, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: snapshot + }), + (hook.dispatch = setSnapshot = dispatchAction.bind( + null, + currentlyRenderingFiber$1, + hook + )), + (_dispatcher$useState.queue = hook), + (_dispatcher$useState.baseQueue = null), + (snapshot = readFromUnsubcribedMutableSource(root, source, getSnapshot)), + (_dispatcher$useState.memoizedState = _dispatcher$useState.baseState = snapshot)); + return snapshot; +} +function updateMutableSource(source, getSnapshot, subscribe) { + var hook = updateWorkInProgressHook(); + return useMutableSource(hook, source, getSnapshot, subscribe); +} function mountState(initialState) { var hook = mountWorkInProgressHook(); "function" === typeof initialState && (initialState = initialState()); @@ -3344,17 +3666,17 @@ function pushEffect(tag, create, destroy, deps) { function updateRef() { return updateWorkInProgressHook().memoizedState; } -function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = mountWorkInProgressHook(); - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; + currentlyRenderingFiber$1.flags |= fiberFlags; hook.memoizedState = pushEffect( - 1 | hookEffectTag, + 1 | hookFlags, create, void 0, void 0 === deps ? null : deps ); } -function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; var destroy = void 0; @@ -3362,12 +3684,12 @@ function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) { var prevEffect = currentHook.memoizedState; destroy = prevEffect.destroy; if (null !== deps && areHookInputsEqual(deps, prevEffect.deps)) { - pushEffect(hookEffectTag, create, destroy, deps); + pushEffect(hookFlags, create, destroy, deps); return; } } - currentlyRenderingFiber$1.effectTag |= fiberEffectTag; - hook.memoizedState = pushEffect(1 | hookEffectTag, create, destroy, deps); + currentlyRenderingFiber$1.flags |= fiberFlags; + hook.memoizedState = pushEffect(1 | hookFlags, create, destroy, deps); } function mountEffect(create, deps) { return mountEffectImpl(516, 4, create, deps); @@ -3406,13 +3728,6 @@ function updateImperativeHandle(ref, create, deps) { ); } function mountDebugValue() {} -function mountCallback(callback, deps) { - mountWorkInProgressHook().memoizedState = [ - callback, - void 0 === deps ? null : deps - ]; - return callback; -} function updateCallback(callback, deps) { var hook = updateWorkInProgressHook(); deps = void 0 === deps ? null : deps; @@ -3440,65 +3755,60 @@ function updateMemo(nextCreate, deps) { hook.memoizedState = [nextCreate, deps]; return nextCreate; } -function startTransition(setPending, config, callback) { +function startTransition(setPending, callback) { var priorityLevel = getCurrentPriorityLevel(); runWithPriority(98 > priorityLevel ? 98 : priorityLevel, function() { setPending(!0); }); runWithPriority(97 < priorityLevel ? 97 : priorityLevel, function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setPending(!1), callback(); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }); } function dispatchAction(fiber, queue, action) { - var currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, fiber, suspenseConfig); - suspenseConfig = { - expirationTime: currentTime, - suspenseConfig: suspenseConfig, - action: action, - eagerReducer: null, - eagerState: null, - next: null - }; - var pending = queue.pending; + var eventTime = requestEventTime(), + lane = requestUpdateLane(fiber), + update = { + lane: lane, + action: action, + eagerReducer: null, + eagerState: null, + next: null + }, + pending = queue.pending; null === pending - ? (suspenseConfig.next = suspenseConfig) - : ((suspenseConfig.next = pending.next), (pending.next = suspenseConfig)); - queue.pending = suspenseConfig; + ? (update.next = update) + : ((update.next = pending.next), (pending.next = update)); + queue.pending = update; pending = fiber.alternate; if ( fiber === currentlyRenderingFiber$1 || (null !== pending && pending === currentlyRenderingFiber$1) ) - (didScheduleRenderPhaseUpdate = !0), - (suspenseConfig.expirationTime = renderExpirationTime), - (currentlyRenderingFiber$1.expirationTime = renderExpirationTime); + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = !0; else { if ( - 0 === fiber.expirationTime && - (null === pending || 0 === pending.expirationTime) && + 0 === fiber.lanes && + (null === pending || 0 === pending.lanes) && ((pending = queue.lastRenderedReducer), null !== pending) ) try { var currentState = queue.lastRenderedState, eagerState = pending(currentState, action); - suspenseConfig.eagerReducer = pending; - suspenseConfig.eagerState = eagerState; + update.eagerReducer = pending; + update.eagerState = eagerState; if (objectIs(eagerState, currentState)) return; } catch (error) { } finally { } - scheduleWork(fiber, currentTime); + scheduleUpdateOnFiber(fiber, lane, eventTime); } } -function updateEventListener() {} var ContextOnlyDispatcher = { readContext: readContext, useCallback: throwInvalidHookError, @@ -3511,14 +3821,21 @@ var ContextOnlyDispatcher = { useRef: throwInvalidHookError, useState: throwInvalidHookError, useDebugValue: throwInvalidHookError, - useResponder: throwInvalidHookError, useDeferredValue: throwInvalidHookError, useTransition: throwInvalidHookError, - useEvent: throwInvalidHookError + useMutableSource: throwInvalidHookError, + useOpaqueIdentifier: throwInvalidHookError, + unstable_isNewReconciler: !1 }, HooksDispatcherOnMount = { readContext: readContext, - useCallback: mountCallback, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + void 0 === deps ? null : deps + ]; + return callback; + }, useContext: readContext, useEffect: mountEffect, useImperativeHandle: function(ref, create, deps) { @@ -3564,39 +3881,44 @@ var ContextOnlyDispatcher = { }, useState: mountState, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _mountState = mountState(value), prevValue = _mountState[0], setValue = _mountState[1]; mountEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { + useTransition: function() { var _mountState2 = mountState(!1), isPending = _mountState2[0]; - _mountState2 = _mountState2[1]; - return [ - mountCallback(startTransition.bind(null, _mountState2, config), [ - _mountState2, - config - ]), - isPending - ]; + _mountState2 = startTransition.bind(null, _mountState2[1]); + mountWorkInProgressHook().memoizedState = _mountState2; + return [_mountState2, isPending]; + }, + useMutableSource: function(source, getSnapshot, subscribe) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = { + refs: { getSnapshot: getSnapshot, setSnapshot: null }, + source: source, + subscribe: subscribe + }; + return useMutableSource(hook, source, getSnapshot, subscribe); }, - useEvent: function() {} + useOpaqueIdentifier: function() { + throw Error("Not yet implemented"); + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnUpdate = { readContext: readContext, @@ -3612,39 +3934,33 @@ var ContextOnlyDispatcher = { return updateReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _updateState = updateReducer(basicStateReducer), prevValue = _updateState[0], setValue = _updateState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _updateState2 = updateReducer(basicStateReducer), - isPending = _updateState2[0]; - _updateState2 = _updateState2[1]; - return [ - updateCallback(startTransition.bind(null, _updateState2, config), [ - _updateState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = updateReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return updateReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, HooksDispatcherOnRerender = { readContext: readContext, @@ -3660,39 +3976,33 @@ var ContextOnlyDispatcher = { return rerenderReducer(basicStateReducer); }, useDebugValue: mountDebugValue, - useResponder: createDeprecatedResponderListener, - useDeferredValue: function(value, config) { + useDeferredValue: function(value) { var _rerenderState = rerenderReducer(basicStateReducer), prevValue = _rerenderState[0], setValue = _rerenderState[1]; updateEffect( function() { - var previousConfig = ReactCurrentBatchConfig$1.suspense; - ReactCurrentBatchConfig$1.suspense = - void 0 === config ? null : config; + var prevTransition = ReactCurrentBatchConfig$1.transition; + ReactCurrentBatchConfig$1.transition = 1; try { setValue(value); } finally { - ReactCurrentBatchConfig$1.suspense = previousConfig; + ReactCurrentBatchConfig$1.transition = prevTransition; } }, - [value, config] + [value] ); return prevValue; }, - useTransition: function(config) { - var _rerenderState2 = rerenderReducer(basicStateReducer), - isPending = _rerenderState2[0]; - _rerenderState2 = _rerenderState2[1]; - return [ - updateCallback(startTransition.bind(null, _rerenderState2, config), [ - _rerenderState2, - config - ]), - isPending - ]; + useTransition: function() { + var isPending = rerenderReducer(basicStateReducer)[0]; + return [updateWorkInProgressHook().memoizedState, isPending]; }, - useEvent: updateEventListener + useMutableSource: updateMutableSource, + useOpaqueIdentifier: function() { + return rerenderReducer(basicStateReducer)[0]; + }, + unstable_isNewReconciler: !1 }, now$1 = Scheduler.unstable_now, commitTime = 0, @@ -3705,27 +4015,21 @@ function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { profilerStartTime = -1; } } +function transferActualDuration(fiber) { + for (var child = fiber.child; child; ) + (fiber.actualDuration += child.actualDuration), (child = child.sibling); +} var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner, didReceiveUpdate = !1; -function reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime -) { +function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { workInProgress.child = null === current - ? mountChildFibers( - workInProgress, - null, - nextChildren, - renderExpirationTime - ) + ? mountChildFibers(workInProgress, null, nextChildren, renderLanes) : reconcileChildFibers( workInProgress, current.child, nextChildren, - renderExpirationTime + renderLanes ); } function updateForwardRef( @@ -3733,33 +4037,28 @@ function updateForwardRef( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { Component = Component.render; var ref = workInProgress.ref; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); nextProps = renderWithHooks( current, workInProgress, Component, nextProps, ref, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, nextProps, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes); return workInProgress.child; } function updateMemoComponent( @@ -3767,8 +4066,8 @@ function updateMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { if (null === current) { var type = Component.type; @@ -3787,17 +4086,17 @@ function updateMemoComponent( workInProgress, type, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); current = createFiberFromTypeAndProps( Component.type, null, nextProps, - null, + workInProgress, workInProgress.mode, - renderExpirationTime + renderLanes ); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3805,19 +4104,14 @@ function updateMemoComponent( } type = current.child; if ( - updateExpirationTime < renderExpirationTime && - ((updateExpirationTime = type.memoizedProps), + 0 === (updateLanes & renderLanes) && + ((updateLanes = type.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps) && - current.ref === workInProgress.ref) + Component(updateLanes, nextProps) && current.ref === workInProgress.ref) ) - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); + workInProgress.flags |= 1; current = createWorkInProgress(type, nextProps); current.ref = workInProgress.ref; current.return = workInProgress; @@ -3828,26 +4122,64 @@ function updateSimpleMemoComponent( workInProgress, Component, nextProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) { - return null !== current && + if ( + null !== current && shallowEqual(current.memoizedProps, nextProps) && - current.ref === workInProgress.ref && - ((didReceiveUpdate = !1), updateExpirationTime < renderExpirationTime) - ? ((workInProgress.expirationTime = current.expirationTime), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - )) - : updateFunctionComponent( - current, - workInProgress, - Component, - nextProps, - renderExpirationTime + current.ref === workInProgress.ref + ) + if (((didReceiveUpdate = !1), 0 !== (renderLanes & updateLanes))) + 0 !== (current.flags & 32768) && (didReceiveUpdate = !0); + else + return ( + (workInProgress.lanes = current.lanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) + ); + return updateFunctionComponent( + current, + workInProgress, + Component, + nextProps, + renderLanes + ); +} +function updateOffscreenComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, + nextChildren = nextProps.children, + prevState = null !== current ? current.memoizedState : null; + if ( + "hidden" === nextProps.mode || + "unstable-defer-without-hiding" === nextProps.mode + ) + if (0 === (workInProgress.mode & 4)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes(workInProgress, renderLanes); + else if (0 !== (renderLanes & 1073741824)) + (workInProgress.memoizedState = { baseLanes: 0 }), + pushRenderLanes( + workInProgress, + null !== prevState ? prevState.baseLanes : renderLanes + ); + else + return ( + (current = + null !== prevState ? prevState.baseLanes | renderLanes : renderLanes), + markSpawnedWork(1073741824), + (workInProgress.lanes = workInProgress.childLanes = 1073741824), + (workInProgress.memoizedState = { baseLanes: current }), + pushRenderLanes(workInProgress, current), + null ); + else + null !== prevState + ? ((nextProps = prevState.baseLanes | renderLanes), + (workInProgress.memoizedState = null)) + : (nextProps = renderLanes), + pushRenderLanes(workInProgress, nextProps); + reconcileChildren(current, workInProgress, nextChildren, renderLanes); + return workInProgress.child; } function markRef(current, workInProgress) { var ref = workInProgress.ref; @@ -3855,42 +4187,37 @@ function markRef(current, workInProgress) { (null === current && null !== ref) || (null !== current && current.ref !== ref) ) - workInProgress.effectTag |= 128; + workInProgress.flags |= 128; } function updateFunctionComponent( current, workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { var context = isContextProvider(Component) ? previousContext : contextStackCursor.current; context = getMaskedContext(workInProgress, context); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); Component = renderWithHooks( current, workInProgress, Component, nextProps, context, - renderExpirationTime + renderLanes ); if (null !== current && !didReceiveUpdate) return ( (workInProgress.updateQueue = current.updateQueue), - (workInProgress.effectTag &= -517), - current.expirationTime <= renderExpirationTime && - (current.expirationTime = 0), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + (workInProgress.flags &= -517), + (current.lanes &= ~renderLanes), + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, Component, renderExpirationTime); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, Component, renderLanes); return workInProgress.child; } function updateClassComponent( @@ -3898,25 +4225,20 @@ function updateClassComponent( workInProgress, Component, nextProps, - renderExpirationTime + renderLanes ) { if (isContextProvider(Component)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); if (null === workInProgress.stateNode) null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), constructClassInstance(workInProgress, Component, nextProps), - mountClassInstance( - workInProgress, - Component, - nextProps, - renderExpirationTime - ), + mountClassInstance(workInProgress, Component, nextProps, renderLanes), (nextProps = !0); else if (null === current) { var instance = workInProgress.stateNode, @@ -3947,12 +4269,7 @@ function updateClassComponent( hasForceUpdate = !1; var oldState = workInProgress.memoizedState; instance.state = oldState; - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ); + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); oldContext = workInProgress.memoizedState; oldProps !== nextProps || oldState !== oldContext || @@ -3985,9 +4302,9 @@ function updateClassComponent( "function" === typeof instance.UNSAFE_componentWillMount && instance.UNSAFE_componentWillMount()), "function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4)) + (workInProgress.flags |= 4)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (workInProgress.memoizedProps = nextProps), (workInProgress.memoizedState = oldContext)), (instance.props = nextProps), @@ -3995,119 +4312,113 @@ function updateClassComponent( (instance.context = contextType), (nextProps = oldProps)) : ("function" === typeof instance.componentDidMount && - (workInProgress.effectTag |= 4), + (workInProgress.flags |= 4), (nextProps = !1)); - } else - (instance = workInProgress.stateNode), - cloneUpdateQueue(current, workInProgress), - (oldProps = workInProgress.memoizedProps), - (instance.props = - workInProgress.type === workInProgress.elementType - ? oldProps - : resolveDefaultProps(workInProgress.type, oldProps)), - (oldContext = instance.context), - (contextType = Component.contextType), - "object" === typeof contextType && null !== contextType - ? (contextType = readContext(contextType)) - : ((contextType = isContextProvider(Component) - ? previousContext - : contextStackCursor.current), - (contextType = getMaskedContext(workInProgress, contextType))), - (getDerivedStateFromProps = Component.getDerivedStateFromProps), - (hasNewLifecycles = - "function" === typeof getDerivedStateFromProps || - "function" === typeof instance.getSnapshotBeforeUpdate) || - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || - ((oldProps !== nextProps || oldContext !== contextType) && - callComponentWillReceiveProps( + } else { + instance = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + oldProps = workInProgress.memoizedProps; + contextType = + workInProgress.type === workInProgress.elementType + ? oldProps + : resolveDefaultProps(workInProgress.type, oldProps); + instance.props = contextType; + hasNewLifecycles = workInProgress.pendingProps; + oldState = instance.context; + oldContext = Component.contextType; + "object" === typeof oldContext && null !== oldContext + ? (oldContext = readContext(oldContext)) + : ((oldContext = isContextProvider(Component) + ? previousContext + : contextStackCursor.current), + (oldContext = getMaskedContext(workInProgress, oldContext))); + var getDerivedStateFromProps$jscomp$0 = Component.getDerivedStateFromProps; + (getDerivedStateFromProps = + "function" === typeof getDerivedStateFromProps$jscomp$0 || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || + ((oldProps !== hasNewLifecycles || oldState !== oldContext) && + callComponentWillReceiveProps( + workInProgress, + instance, + nextProps, + oldContext + )); + hasForceUpdate = !1; + oldState = workInProgress.memoizedState; + instance.state = oldState; + processUpdateQueue(workInProgress, nextProps, instance, renderLanes); + var newState = workInProgress.memoizedState; + oldProps !== hasNewLifecycles || + oldState !== newState || + didPerformWorkStackCursor.current || + hasForceUpdate + ? ("function" === typeof getDerivedStateFromProps$jscomp$0 && + (applyDerivedStateFromProps( workInProgress, - instance, + Component, + getDerivedStateFromProps$jscomp$0, + nextProps + ), + (newState = workInProgress.memoizedState)), + (contextType = + hasForceUpdate || + checkShouldComponentUpdate( + workInProgress, + Component, + contextType, nextProps, - contextType - )), - (hasForceUpdate = !1), - (oldContext = workInProgress.memoizedState), - (instance.state = oldContext), - processUpdateQueue( - workInProgress, - nextProps, - instance, - renderExpirationTime - ), - (oldState = workInProgress.memoizedState), - oldProps !== nextProps || - oldContext !== oldState || - didPerformWorkStackCursor.current || - hasForceUpdate - ? ("function" === typeof getDerivedStateFromProps && - (applyDerivedStateFromProps( - workInProgress, - Component, - getDerivedStateFromProps, - nextProps - ), - (oldState = workInProgress.memoizedState)), - (getDerivedStateFromProps = - hasForceUpdate || - checkShouldComponentUpdate( - workInProgress, - Component, - oldProps, - nextProps, - oldContext, - oldState, - contextType - )) - ? (hasNewLifecycles || - ("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - nextProps, - oldState, - contextType - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - nextProps, - oldState, - contextType - )), - "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4), - "function" === typeof instance.getSnapshotBeforeUpdate && - (workInProgress.effectTag |= 256)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (workInProgress.memoizedProps = nextProps), - (workInProgress.memoizedState = oldState)), - (instance.props = nextProps), - (instance.state = oldState), - (instance.context = contextType), - (nextProps = getDerivedStateFromProps)) - : ("function" !== typeof instance.componentDidUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 4), - "function" !== typeof instance.getSnapshotBeforeUpdate || - (oldProps === current.memoizedProps && - oldContext === current.memoizedState) || - (workInProgress.effectTag |= 256), - (nextProps = !1)); + oldState, + newState, + oldContext + )) + ? (getDerivedStateFromProps || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || + ("function" === typeof instance.componentWillUpdate && + instance.componentWillUpdate(nextProps, newState, oldContext), + "function" === typeof instance.UNSAFE_componentWillUpdate && + instance.UNSAFE_componentWillUpdate( + nextProps, + newState, + oldContext + )), + "function" === typeof instance.componentDidUpdate && + (workInProgress.flags |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.flags |= 256)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (workInProgress.memoizedProps = nextProps), + (workInProgress.memoizedState = newState)), + (instance.props = nextProps), + (instance.state = newState), + (instance.context = oldContext), + (nextProps = contextType)) + : ("function" !== typeof instance.componentDidUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldState === current.memoizedState) || + (workInProgress.flags |= 256), + (nextProps = !1)); + } return finishClassComponent( current, workInProgress, Component, nextProps, hasContext, - renderExpirationTime + renderLanes ); } function finishClassComponent( @@ -4116,18 +4427,14 @@ function finishClassComponent( Component, shouldUpdate, hasContext, - renderExpirationTime + renderLanes ) { markRef(current, workInProgress); - var didCaptureError = 0 !== (workInProgress.effectTag & 64); + var didCaptureError = 0 !== (workInProgress.flags & 64); if (!shouldUpdate && !didCaptureError) return ( hasContext && invalidateContextProvider(workInProgress, Component, !1), - bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ) + bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) ); shouldUpdate = workInProgress.stateNode; ReactCurrentOwner$1.current = workInProgress; @@ -4138,27 +4445,22 @@ function finishClassComponent( var nextChildren = null; profilerStartTime = -1; } else nextChildren = shouldUpdate.render(); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; null !== current && didCaptureError ? ((didCaptureError = nextChildren), (workInProgress.child = reconcileChildFibers( workInProgress, current.child, null, - renderExpirationTime + renderLanes )), (workInProgress.child = reconcileChildFibers( workInProgress, null, didCaptureError, - renderExpirationTime + renderLanes ))) - : reconcileChildren( - current, - workInProgress, - nextChildren, - renderExpirationTime - ); + : reconcileChildren(current, workInProgress, nextChildren, renderLanes); workInProgress.memoizedState = shouldUpdate.state; hasContext && invalidateContextProvider(workInProgress, Component, !0); return workInProgress.child; @@ -4175,169 +4477,227 @@ function pushHostRootContext(workInProgress) { pushTopLevelContextObject(workInProgress, root.context, !1); pushHostContainer(workInProgress, root.containerInfo); } -var SUSPENDED_MARKER = { dehydrated: null, retryTime: 0 }; -function updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime -) { - var mode = workInProgress.mode, - nextProps = workInProgress.pendingProps, +var SUSPENDED_MARKER = { dehydrated: null, retryLane: 0 }; +function updateSuspenseComponent(current, workInProgress, renderLanes) { + var nextProps = workInProgress.pendingProps, suspenseContext = suspenseStackCursor.current, - nextDidTimeout = !1, + showFallback = !1, JSCompiler_temp; - (JSCompiler_temp = 0 !== (workInProgress.effectTag & 64)) || + (JSCompiler_temp = 0 !== (workInProgress.flags & 64)) || (JSCompiler_temp = - 0 !== (suspenseContext & 2) && - (null === current || null !== current.memoizedState)); + null !== current && null === current.memoizedState + ? !1 + : 0 !== (suspenseContext & 2)); JSCompiler_temp - ? ((nextDidTimeout = !0), (workInProgress.effectTag &= -65)) + ? ((showFallback = !0), (workInProgress.flags &= -65)) : (null !== current && null === current.memoizedState) || void 0 === nextProps.fallback || !0 === nextProps.unstable_avoidThisFallback || (suspenseContext |= 1); push(suspenseStackCursor, suspenseContext & 1); if (null === current) { - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + current = nextProps.children; + suspenseContext = nextProps.fallback; + if (showFallback) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + current ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - mode = nextProps.children; - workInProgress.memoizedState = null; - return (workInProgress.child = mountChildFibers( - workInProgress, - null, - mode, - renderExpirationTime - )); + if ("number" === typeof nextProps.unstable_expectedLoadTime) + return ( + (current = mountSuspenseFallbackChildren( + workInProgress, + current, + suspenseContext, + renderLanes + )), + (workInProgress.child.memoizedState = { baseLanes: renderLanes }), + (workInProgress.memoizedState = SUSPENDED_MARKER), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432), + current + ); + renderLanes = createFiberFromOffscreen( + { mode: "visible", children: current }, + workInProgress.mode, + renderLanes, + null + ); + renderLanes.return = workInProgress; + return (workInProgress.child = renderLanes); } if (null !== current.memoizedState) { - current = current.child; - mode = current.sibling; - if (nextDidTimeout) { - nextProps = nextProps.fallback; - renderExpirationTime = createWorkInProgress( - current, - current.pendingProps + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - if ( - 0 === (workInProgress.mode & 2) && - ((nextDidTimeout = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child), - nextDidTimeout !== current.child) - ) - for ( - renderExpirationTime.child = nextDidTimeout; - null !== nextDidTimeout; - - ) - (nextDidTimeout.return = renderExpirationTime), - (nextDidTimeout = nextDidTimeout.sibling); - if (workInProgress.mode & 8) { - nextDidTimeout = 0; - for (current = renderExpirationTime.child; null !== current; ) - (nextDidTimeout += current.treeBaseDuration), - (current = current.sibling); - renderExpirationTime.treeBaseDuration = nextDidTimeout; - } - mode = createWorkInProgress(mode, nextProps); - mode.return = workInProgress; - renderExpirationTime.sibling = mode; - renderExpirationTime.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = renderExpirationTime; - return mode; - } - renderExpirationTime = reconcileChildFibers( + renderLanes = updateSuspensePrimaryChildren( + current, workInProgress, - current.child, nextProps.children, - renderExpirationTime + renderLanes ); workInProgress.memoizedState = null; - return (workInProgress.child = renderExpirationTime); + return renderLanes; } - current = current.child; - if (nextDidTimeout) { - nextDidTimeout = nextProps.fallback; - nextProps = createFiberFromFragment(null, mode, 0, null); - nextProps.return = workInProgress; - nextProps.child = current; - null !== current && (current.return = nextProps); - if (0 === (workInProgress.mode & 2)) - for ( - current = - null !== workInProgress.memoizedState - ? workInProgress.child.child - : workInProgress.child, - nextProps.child = current; - null !== current; - - ) - (current.return = nextProps), (current = current.sibling); - if (workInProgress.mode & 8) { - current = 0; - for (suspenseContext = nextProps.child; null !== suspenseContext; ) - (current += suspenseContext.treeBaseDuration), - (suspenseContext = suspenseContext.sibling); - nextProps.treeBaseDuration = current; - } - renderExpirationTime = createFiberFromFragment( - nextDidTimeout, - mode, - renderExpirationTime, - null + if (showFallback) + return ( + (nextProps = updateSuspenseFallbackChildren( + current, + workInProgress, + nextProps.children, + nextProps.fallback, + renderLanes + )), + (showFallback = workInProgress.child), + (suspenseContext = current.child.memoizedState), + (showFallback.memoizedState = + null === suspenseContext + ? { baseLanes: renderLanes } + : { baseLanes: suspenseContext.baseLanes | renderLanes }), + (showFallback.childLanes = current.childLanes & ~renderLanes), + (workInProgress.memoizedState = SUSPENDED_MARKER), + nextProps ); - renderExpirationTime.return = workInProgress; - nextProps.sibling = renderExpirationTime; - renderExpirationTime.effectTag |= 2; - nextProps.childExpirationTime = 0; - workInProgress.memoizedState = SUSPENDED_MARKER; - workInProgress.child = nextProps; - return renderExpirationTime; - } - workInProgress.memoizedState = null; - return (workInProgress.child = reconcileChildFibers( - workInProgress, + renderLanes = updateSuspensePrimaryChildren( current, + workInProgress, nextProps.children, - renderExpirationTime - )); + renderLanes + ); + workInProgress.memoizedState = null; + return renderLanes; } -function scheduleWorkOnFiber(fiber, renderExpirationTime) { - fiber.expirationTime < renderExpirationTime && - (fiber.expirationTime = renderExpirationTime); +function mountSuspenseFallbackChildren( + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + progressedPrimaryFragment = workInProgress.child; + primaryChildren = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && null !== progressedPrimaryFragment + ? ((progressedPrimaryFragment.childLanes = 0), + (progressedPrimaryFragment.pendingProps = primaryChildren), + workInProgress.mode & 8 && + ((progressedPrimaryFragment.actualDuration = 0), + (progressedPrimaryFragment.actualStartTime = -1), + (progressedPrimaryFragment.selfBaseDuration = 0), + (progressedPrimaryFragment.treeBaseDuration = 0))) + : (progressedPrimaryFragment = createFiberFromOffscreen( + primaryChildren, + mode, + 0, + null + )); + fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + ); + progressedPrimaryFragment.return = workInProgress; + fallbackChildren.return = workInProgress; + progressedPrimaryFragment.sibling = fallbackChildren; + workInProgress.child = progressedPrimaryFragment; + return fallbackChildren; +} +function updateSuspensePrimaryChildren( + current, + workInProgress, + primaryChildren, + renderLanes +) { + var currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + primaryChildren = createWorkInProgress(currentPrimaryChildFragment, { + mode: "visible", + children: primaryChildren + }); + 0 === (workInProgress.mode & 2) && (primaryChildren.lanes = renderLanes); + primaryChildren.return = workInProgress; + primaryChildren.sibling = null; + null !== current && + ((current.nextEffect = null), + (current.flags = 8), + (workInProgress.firstEffect = workInProgress.lastEffect = current)); + return (workInProgress.child = primaryChildren); +} +function updateSuspenseFallbackChildren( + current, + workInProgress, + primaryChildren, + fallbackChildren, + renderLanes +) { + var mode = workInProgress.mode, + currentPrimaryChildFragment = current.child; + current = currentPrimaryChildFragment.sibling; + var primaryChildProps = { mode: "hidden", children: primaryChildren }; + 0 === (mode & 2) && workInProgress.child !== currentPrimaryChildFragment + ? ((primaryChildren = workInProgress.child), + (primaryChildren.childLanes = 0), + (primaryChildren.pendingProps = primaryChildProps), + workInProgress.mode & 8 && + ((primaryChildren.actualDuration = 0), + (primaryChildren.actualStartTime = -1), + (primaryChildren.selfBaseDuration = + currentPrimaryChildFragment.selfBaseDuration), + (primaryChildren.treeBaseDuration = + currentPrimaryChildFragment.treeBaseDuration)), + (currentPrimaryChildFragment = primaryChildren.lastEffect), + null !== currentPrimaryChildFragment + ? ((workInProgress.firstEffect = primaryChildren.firstEffect), + (workInProgress.lastEffect = currentPrimaryChildFragment), + (currentPrimaryChildFragment.nextEffect = null)) + : (workInProgress.firstEffect = workInProgress.lastEffect = null)) + : (primaryChildren = createWorkInProgress( + currentPrimaryChildFragment, + primaryChildProps + )); + null !== current + ? (fallbackChildren = createWorkInProgress(current, fallbackChildren)) + : ((fallbackChildren = createFiberFromFragment( + fallbackChildren, + mode, + renderLanes, + null + )), + (fallbackChildren.flags |= 2)); + fallbackChildren.return = workInProgress; + primaryChildren.return = workInProgress; + primaryChildren.sibling = fallbackChildren; + workInProgress.child = primaryChildren; + return fallbackChildren; +} +function scheduleWorkOnFiber(fiber, renderLanes) { + fiber.lanes |= renderLanes; var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < renderExpirationTime && - (alternate.expirationTime = renderExpirationTime); - scheduleWorkOnParentPath(fiber.return, renderExpirationTime); + null !== alternate && (alternate.lanes |= renderLanes); + scheduleWorkOnParentPath(fiber.return, renderLanes); } function initSuspenseListRenderState( workInProgress, @@ -4355,7 +4715,6 @@ function initSuspenseListRenderState( renderingStartTime: 0, last: lastContentRow, tail: tail, - tailExpiration: 0, tailMode: tailMode, lastEffect: lastEffectBeforeRendering }) @@ -4364,35 +4723,24 @@ function initSuspenseListRenderState( (renderState.renderingStartTime = 0), (renderState.last = lastContentRow), (renderState.tail = tail), - (renderState.tailExpiration = 0), (renderState.tailMode = tailMode), (renderState.lastEffect = lastEffectBeforeRendering)); } -function updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime -) { +function updateSuspenseListComponent(current, workInProgress, renderLanes) { var nextProps = workInProgress.pendingProps, revealOrder = nextProps.revealOrder, tailMode = nextProps.tail; - reconcileChildren( - current, - workInProgress, - nextProps.children, - renderExpirationTime - ); + reconcileChildren(current, workInProgress, nextProps.children, renderLanes); nextProps = suspenseStackCursor.current; if (0 !== (nextProps & 2)) - (nextProps = (nextProps & 1) | 2), (workInProgress.effectTag |= 64); + (nextProps = (nextProps & 1) | 2), (workInProgress.flags |= 64); else { - if (null !== current && 0 !== (current.effectTag & 64)) + if (null !== current && 0 !== (current.flags & 64)) a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderExpirationTime); - else if (19 === current.tag) - scheduleWorkOnFiber(current, renderExpirationTime); + scheduleWorkOnFiber(current, renderLanes); + else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -4414,30 +4762,29 @@ function updateSuspenseListComponent( else switch (revealOrder) { case "forwards": - renderExpirationTime = workInProgress.child; - for (revealOrder = null; null !== renderExpirationTime; ) - (current = renderExpirationTime.alternate), + renderLanes = workInProgress.child; + for (revealOrder = null; null !== renderLanes; ) + (current = renderLanes.alternate), null !== current && null === findFirstSuspended(current) && - (revealOrder = renderExpirationTime), - (renderExpirationTime = renderExpirationTime.sibling); - renderExpirationTime = revealOrder; - null === renderExpirationTime + (revealOrder = renderLanes), + (renderLanes = renderLanes.sibling); + renderLanes = revealOrder; + null === renderLanes ? ((revealOrder = workInProgress.child), (workInProgress.child = null)) - : ((revealOrder = renderExpirationTime.sibling), - (renderExpirationTime.sibling = null)); + : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null)); initSuspenseListRenderState( workInProgress, !1, revealOrder, - renderExpirationTime, + renderLanes, tailMode, workInProgress.lastEffect ); break; case "backwards": - renderExpirationTime = null; + renderLanes = null; revealOrder = workInProgress.child; for (workInProgress.child = null; null !== revealOrder; ) { current = revealOrder.alternate; @@ -4446,14 +4793,14 @@ function updateSuspenseListComponent( break; } current = revealOrder.sibling; - revealOrder.sibling = renderExpirationTime; - renderExpirationTime = revealOrder; + revealOrder.sibling = renderLanes; + renderLanes = revealOrder; revealOrder = current; } initSuspenseListRenderState( workInProgress, !0, - renderExpirationTime, + renderLanes, null, tailMode, workInProgress.lastEffect @@ -4474,36 +4821,29 @@ function updateSuspenseListComponent( } return workInProgress.child; } -function bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime -) { +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { null !== current && (workInProgress.dependencies = current.dependencies); profilerStartTime = -1; - var updateExpirationTime = workInProgress.expirationTime; - 0 !== updateExpirationTime && markUnprocessedUpdateTime(updateExpirationTime); - if (workInProgress.childExpirationTime < renderExpirationTime) return null; - if (null !== current && workInProgress.child !== current.child) - throw Error("Resuming work not yet implemented."); - if (null !== workInProgress.child) { - current = workInProgress.child; - renderExpirationTime = createWorkInProgress(current, current.pendingProps); - workInProgress.child = renderExpirationTime; - for ( - renderExpirationTime.return = workInProgress; - null !== current.sibling; - - ) - (current = current.sibling), - (renderExpirationTime = renderExpirationTime.sibling = createWorkInProgress( - current, - current.pendingProps - )), - (renderExpirationTime.return = workInProgress); - renderExpirationTime.sibling = null; + workInProgressRootSkippedLanes |= workInProgress.lanes; + if (0 !== (renderLanes & workInProgress.childLanes)) { + if (null !== current && workInProgress.child !== current.child) + throw Error("Resuming work not yet implemented."); + if (null !== workInProgress.child) { + current = workInProgress.child; + renderLanes = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes; + for (renderLanes.return = workInProgress; null !== current.sibling; ) + (current = current.sibling), + (renderLanes = renderLanes.sibling = createWorkInProgress( + current, + current.pendingProps + )), + (renderLanes.return = workInProgress); + renderLanes.sibling = null; + } + return workInProgress.child; } - return workInProgress.child; + return null; } var appendAllChildren, updateHostContainer, @@ -4531,10 +4871,10 @@ updateHostComponent$1 = function(current, workInProgress, type, newProps) { current.memoizedProps !== newProps && (requiredContext(contextStackCursor$1.current), (workInProgress.updateQueue = UPDATE_SIGNAL)) && - (workInProgress.effectTag |= 4); + (workInProgress.flags |= 4); }; updateHostText$1 = function(current, workInProgress, oldText, newText) { - oldText !== newText && (workInProgress.effectTag |= 4); + oldText !== newText && (workInProgress.flags |= 4); }; function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { switch (renderState.tailMode) { @@ -4550,17 +4890,17 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var _lastTailNode = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (_lastTailNode = lastTailNode), + for (var lastTailNode$65 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$65 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === _lastTailNode + null === lastTailNode$65 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (_lastTailNode.sibling = null); + : (lastTailNode$65.sibling = null); } } -function completeWork(current, workInProgress, renderExpirationTime) { +function completeWork(current, workInProgress, renderLanes) { var newProps = workInProgress.pendingProps; switch (workInProgress.tag) { case 2: @@ -4581,10 +4921,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { popHostContainer(), pop(didPerformWorkStackCursor), pop(contextStackCursor), - (current = workInProgress.stateNode), - current.pendingContext && - ((current.context = current.pendingContext), - (current.pendingContext = null)), + resetWorkInProgressVersions(), + (newProps = workInProgress.stateNode), + newProps.pendingContext && + ((newProps.context = newProps.pendingContext), + (newProps.pendingContext = null)), + (null !== current && null !== current.child) || + newProps.hydrate || + (workInProgress.flags |= 256), updateHostContainer(workInProgress), null ); @@ -4593,17 +4937,16 @@ function completeWork(current, workInProgress, renderExpirationTime) { var rootContainerInstance = requiredContext( rootInstanceStackCursor.current ); - renderExpirationTime = workInProgress.type; + renderLanes = workInProgress.type; if (null !== current && null != workInProgress.stateNode) updateHostComponent$1( current, workInProgress, - renderExpirationTime, + renderLanes, newProps, rootContainerInstance ), - current.ref !== workInProgress.ref && - (workInProgress.effectTag |= 128); + current.ref !== workInProgress.ref && (workInProgress.flags |= 128); else { if (!newProps) { if (null === workInProgress.stateNode) @@ -4614,22 +4957,22 @@ function completeWork(current, workInProgress, renderExpirationTime) { } requiredContext(contextStackCursor$1.current); current = allocateTag(); - renderExpirationTime = getViewConfigForType(renderExpirationTime); + renderLanes = getViewConfigForType(renderLanes); var updatePayload = diffProperties( null, emptyObject, newProps, - renderExpirationTime.validAttributes + renderLanes.validAttributes ); ReactNativePrivateInterface.UIManager.createView( current, - renderExpirationTime.uiViewClassName, + renderLanes.uiViewClassName, rootContainerInstance, updatePayload ); rootContainerInstance = new ReactNativeFiberHostComponent( current, - renderExpirationTime, + renderLanes, workInProgress ); instanceCache.set(current, workInProgress); @@ -4637,8 +4980,8 @@ function completeWork(current, workInProgress, renderExpirationTime) { appendAllChildren(rootContainerInstance, workInProgress, !1, !1); workInProgress.stateNode = rootContainerInstance; finalizeInitialChildren(rootContainerInstance) && - (workInProgress.effectTag |= 4); - null !== workInProgress.ref && (workInProgress.effectTag |= 128); + (workInProgress.flags |= 4); + null !== workInProgress.ref && (workInProgress.flags |= 128); } return null; case 6: @@ -4673,52 +5016,40 @@ function completeWork(current, workInProgress, renderExpirationTime) { case 13: pop(suspenseStackCursor); newProps = workInProgress.memoizedState; - if (0 !== (workInProgress.effectTag & 64)) + if (0 !== (workInProgress.flags & 64)) return ( - (workInProgress.expirationTime = renderExpirationTime), workInProgress + (workInProgress.lanes = renderLanes), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), + workInProgress ); newProps = null !== newProps; rootContainerInstance = !1; null !== current && - ((renderExpirationTime = current.memoizedState), - (rootContainerInstance = null !== renderExpirationTime), - newProps || - null === renderExpirationTime || - ((renderExpirationTime = current.child.sibling), - null !== renderExpirationTime && - ((updatePayload = workInProgress.firstEffect), - null !== updatePayload - ? ((workInProgress.firstEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = updatePayload)) - : ((workInProgress.firstEffect = workInProgress.lastEffect = renderExpirationTime), - (renderExpirationTime.nextEffect = null)), - (renderExpirationTime.effectTag = 8)))); + (rootContainerInstance = null !== current.memoizedState); if (newProps && !rootContainerInstance && 0 !== (workInProgress.mode & 2)) if ( (null === current && !0 !== workInProgress.memoizedProps.unstable_avoidThisFallback) || 0 !== (suspenseStackCursor.current & 1) ) - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootSuspended); + 0 === workInProgressRootExitStatus && + (workInProgressRootExitStatus = 3); else { if ( - workInProgressRootExitStatus === RootIncomplete || - workInProgressRootExitStatus === RootSuspended + 0 === workInProgressRootExitStatus || + 3 === workInProgressRootExitStatus ) - workInProgressRootExitStatus = RootSuspendedWithDelay; - 0 !== workInProgressRootNextUnprocessedUpdateTime && - null !== workInProgressRoot && - (markRootSuspendedAtTime( - workInProgressRoot, - renderExpirationTime$1 - ), - markRootUpdatedAtTime( + workInProgressRootExitStatus = 4; + null === workInProgressRoot || + (0 === (workInProgressRootSkippedLanes & 134217727) && + 0 === (workInProgressRootUpdatedLanes & 134217727)) || + markRootSuspended$1( workInProgressRoot, - workInProgressRootNextUnprocessedUpdateTime - )); + workInProgressRootRenderLanes + ); } - if (newProps || rootContainerInstance) workInProgress.effectTag |= 4; + if (newProps || rootContainerInstance) workInProgress.flags |= 4; return null; case 4: return popHostContainer(), updateHostContainer(workInProgress), null; @@ -4730,71 +5061,70 @@ function completeWork(current, workInProgress, renderExpirationTime) { pop(suspenseStackCursor); newProps = workInProgress.memoizedState; if (null === newProps) return null; - rootContainerInstance = 0 !== (workInProgress.effectTag & 64); + rootContainerInstance = 0 !== (workInProgress.flags & 64); updatePayload = newProps.rendering; if (null === updatePayload) if (rootContainerInstance) cutOffTailIfNeeded(newProps, !1); else { if ( - workInProgressRootExitStatus !== RootIncomplete || - (null !== current && 0 !== (current.effectTag & 64)) + 0 !== workInProgressRootExitStatus || + (null !== current && 0 !== (current.flags & 64)) ) for (current = workInProgress.child; null !== current; ) { updatePayload = findFirstSuspended(current); if (null !== updatePayload) { - workInProgress.effectTag |= 64; + workInProgress.flags |= 64; cutOffTailIfNeeded(newProps, !1); current = updatePayload.updateQueue; null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)); + (workInProgress.flags |= 4)); null === newProps.lastEffect && (workInProgress.firstEffect = null); workInProgress.lastEffect = newProps.lastEffect; - current = renderExpirationTime; + current = renderLanes; for (newProps = workInProgress.child; null !== newProps; ) (rootContainerInstance = newProps), (updatePayload = current), - (rootContainerInstance.effectTag &= 2), + (rootContainerInstance.flags &= 2), (rootContainerInstance.nextEffect = null), (rootContainerInstance.firstEffect = null), (rootContainerInstance.lastEffect = null), - (renderExpirationTime = rootContainerInstance.alternate), - null === renderExpirationTime - ? ((rootContainerInstance.childExpirationTime = 0), - (rootContainerInstance.expirationTime = updatePayload), + (renderLanes = rootContainerInstance.alternate), + null === renderLanes + ? ((rootContainerInstance.childLanes = 0), + (rootContainerInstance.lanes = updatePayload), (rootContainerInstance.child = null), (rootContainerInstance.memoizedProps = null), (rootContainerInstance.memoizedState = null), (rootContainerInstance.updateQueue = null), (rootContainerInstance.dependencies = null), + (rootContainerInstance.stateNode = null), (rootContainerInstance.selfBaseDuration = 0), (rootContainerInstance.treeBaseDuration = 0)) - : ((rootContainerInstance.childExpirationTime = - renderExpirationTime.childExpirationTime), - (rootContainerInstance.expirationTime = - renderExpirationTime.expirationTime), - (rootContainerInstance.child = - renderExpirationTime.child), + : ((rootContainerInstance.childLanes = + renderLanes.childLanes), + (rootContainerInstance.lanes = renderLanes.lanes), + (rootContainerInstance.child = renderLanes.child), (rootContainerInstance.memoizedProps = - renderExpirationTime.memoizedProps), + renderLanes.memoizedProps), (rootContainerInstance.memoizedState = - renderExpirationTime.memoizedState), + renderLanes.memoizedState), (rootContainerInstance.updateQueue = - renderExpirationTime.updateQueue), - (updatePayload = renderExpirationTime.dependencies), + renderLanes.updateQueue), + (rootContainerInstance.type = renderLanes.type), + (updatePayload = renderLanes.dependencies), (rootContainerInstance.dependencies = null === updatePayload ? null : { - expirationTime: updatePayload.expirationTime, - firstContext: updatePayload.firstContext, - responders: updatePayload.responders + lanes: updatePayload.lanes, + firstContext: updatePayload.firstContext }), (rootContainerInstance.selfBaseDuration = - renderExpirationTime.selfBaseDuration), + renderLanes.selfBaseDuration), (rootContainerInstance.treeBaseDuration = - renderExpirationTime.treeBaseDuration)), + renderLanes.treeBaseDuration)), (newProps = newProps.sibling); push( suspenseStackCursor, @@ -4804,6 +5134,13 @@ function completeWork(current, workInProgress, renderExpirationTime) { } current = current.sibling; } + null !== newProps.tail && + now() > workInProgressRootRenderTargetTime && + ((workInProgress.flags |= 64), + (rootContainerInstance = !0), + cutOffTailIfNeeded(newProps, !1), + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); } else { if (!rootContainerInstance) @@ -4811,12 +5148,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { ((current = findFirstSuspended(updatePayload)), null !== current) ) { if ( - ((workInProgress.effectTag |= 64), + ((workInProgress.flags |= 64), (rootContainerInstance = !0), (current = current.updateQueue), null !== current && ((workInProgress.updateQueue = current), - (workInProgress.effectTag |= 4)), + (workInProgress.flags |= 4)), cutOffTailIfNeeded(newProps, !0), null === newProps.tail && "hidden" === newProps.tailMode && @@ -4829,16 +5166,14 @@ function completeWork(current, workInProgress, renderExpirationTime) { null ); } else - 2 * now() - newProps.renderingStartTime > newProps.tailExpiration && - 1 < renderExpirationTime && - ((workInProgress.effectTag |= 64), + 2 * now() - newProps.renderingStartTime > + workInProgressRootRenderTargetTime && + 1073741824 !== renderLanes && + ((workInProgress.flags |= 64), (rootContainerInstance = !0), cutOffTailIfNeeded(newProps, !1), - (current = renderExpirationTime - 1), - (workInProgress.expirationTime = workInProgress.childExpirationTime = current), - null === spawnedWorkDuringRender - ? (spawnedWorkDuringRender = [current]) - : spawnedWorkDuringRender.push(current)); + (workInProgress.lanes = 33554432), + markSpawnedWork(33554432)); newProps.isBackwards ? ((updatePayload.sibling = workInProgress.child), (workInProgress.child = updatePayload)) @@ -4849,9 +5184,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { (newProps.last = updatePayload)); } return null !== newProps.tail - ? (0 === newProps.tailExpiration && - (newProps.tailExpiration = now() + 500), - (current = newProps.tail), + ? ((current = newProps.tail), (newProps.rendering = current), (newProps.tail = current.sibling), (newProps.lastEffect = workInProgress.lastEffect), @@ -4866,6 +5199,17 @@ function completeWork(current, workInProgress, renderExpirationTime) { ), current) : null; + case 22: + case 23: + return ( + popRenderLanes(), + null !== current && + (null !== current.memoizedState) !== + (null !== workInProgress.memoizedState) && + "unstable-defer-without-hiding" !== newProps.mode && + (workInProgress.flags |= 4), + null + ); } throw Error( "Unknown unit of work tag (" + @@ -4877,30 +5221,35 @@ function unwindWork(workInProgress) { switch (workInProgress.tag) { case 1: isContextProvider(workInProgress.type) && popContext(); - var effectTag = workInProgress.effectTag; - return effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + var flags = workInProgress.flags; + return flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), workInProgress) : null; case 3: popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); - effectTag = workInProgress.effectTag; - if (0 !== (effectTag & 64)) + resetWorkInProgressVersions(); + flags = workInProgress.flags; + if (0 !== (flags & 64)) throw Error( "The root failed to unmount after an error. This is likely a bug in React. Please file an issue." ); - workInProgress.effectTag = (effectTag & -4097) | 64; + workInProgress.flags = (flags & -8193) | 64; return workInProgress; case 5: return popHostContext(workInProgress), null; case 13: return ( pop(suspenseStackCursor), - (effectTag = workInProgress.effectTag), - effectTag & 4096 - ? ((workInProgress.effectTag = (effectTag & -4097) | 64), + (flags = workInProgress.flags), + flags & 8192 + ? ((workInProgress.flags = (flags & -8193) | 64), + 0 !== (workInProgress.mode & 8) && + transferActualDuration(workInProgress), workInProgress) : null ); @@ -4910,6 +5259,9 @@ function unwindWork(workInProgress) { return popHostContainer(), null; case 10: return popProvider(workInProgress), null; + case 22: + case 23: + return popRenderLanes(), null; default: return null; } @@ -4928,51 +5280,61 @@ if ( throw Error( "Expected ReactFiberErrorDialog.showErrorDialog to be a function." ); -function logCapturedError(capturedError) { - !1 !== - ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog( - capturedError - ) && console.error(capturedError.error); -} -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; -function logError(boundary, errorInfo) { - var source = errorInfo.source, - stack = errorInfo.stack; - null === stack && - null !== source && - (stack = getStackByFiberInDevAndProd(source)); - errorInfo = { - componentName: null !== source ? getComponentName(source.type) : null, - componentStack: null !== stack ? stack : "", - error: errorInfo.value, - errorBoundary: null, - errorBoundaryName: null, - errorBoundaryFound: !1, - willRetry: !1 - }; - null !== boundary && - 1 === boundary.tag && - ((errorInfo.errorBoundary = boundary.stateNode), - (errorInfo.errorBoundaryName = getComponentName(boundary.type)), - (errorInfo.errorBoundaryFound = !0), - (errorInfo.willRetry = !0)); +function logCapturedError(boundary, errorInfo) { try { - logCapturedError(errorInfo); + !1 !== + ReactNativePrivateInterface.ReactFiberErrorDialog.showErrorDialog({ + componentStack: null !== errorInfo.stack ? errorInfo.stack : "", + error: errorInfo.value, + errorBoundary: + null !== boundary && 1 === boundary.tag ? boundary.stateNode : null + }) && console.error(errorInfo.value); } catch (e) { setTimeout(function() { throw e; }); } } -function safelyCallComponentWillUnmount(current, instance) { - try { - (instance.props = current.memoizedProps), - (instance.state = current.memoizedState), - instance.componentWillUnmount(); - } catch (unmountError) { - captureCommitPhaseError(current, unmountError); +var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; +function createRootErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + lane.payload = { element: null }; + var error = errorInfo.value; + lane.callback = function() { + hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); + logCapturedError(fiber, errorInfo); + }; + return lane; +} +function createClassErrorUpdate(fiber, errorInfo, lane) { + lane = createUpdate(-1, lane); + lane.tag = 3; + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if ("function" === typeof getDerivedStateFromError) { + var error = errorInfo.value; + lane.payload = function() { + logCapturedError(fiber, errorInfo); + return getDerivedStateFromError(error); + }; } + var inst = fiber.stateNode; + null !== inst && + "function" === typeof inst.componentDidCatch && + (lane.callback = function() { + "function" !== typeof getDerivedStateFromError && + (null === legacyErrorBoundariesThatAlreadyFailed + ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) + : legacyErrorBoundariesThatAlreadyFailed.add(this), + logCapturedError(fiber, errorInfo)); + var stack = errorInfo.stack; + this.componentDidCatch(errorInfo.value, { + componentStack: null !== stack ? stack : "" + }); + }); + return lane; } +var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; function safelyDetachRef(current) { var ref = current.ref; if (null !== ref) @@ -4989,10 +5351,9 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { case 0: case 11: case 15: - case 22: return; case 1: - if (finishedWork.effectTag & 256 && null !== current) { + if (finishedWork.flags & 256 && null !== current) { var prevProps = current.memoizedProps, prevState = current.memoizedState; current = finishedWork.stateNode; @@ -5006,6 +5367,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { } return; case 3: + return; case 5: case 6: case 4: @@ -5016,58 +5378,56 @@ function commitBeforeMutationLifeCycles(current, finishedWork) { "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitHookEffectListUnmount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var destroy = effect.destroy; - effect.destroy = void 0; - void 0 !== destroy && destroy(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} -function commitHookEffectListMount(tag, finishedWork) { - finishedWork = finishedWork.updateQueue; - finishedWork = null !== finishedWork ? finishedWork.lastEffect : null; - if (null !== finishedWork) { - var effect = (finishedWork = finishedWork.next); - do { - if ((effect.tag & tag) === tag) { - var create = effect.create; - effect.destroy = create(); - } - effect = effect.next; - } while (effect !== finishedWork); - } -} function commitLifeCycles(finishedRoot, current, finishedWork) { switch (finishedWork.tag) { case 0: case 11: case 15: - case 22: - commitHookEffectListMount(3, finishedWork); + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + if (3 === (finishedRoot.tag & 3)) { + var create$82 = finishedRoot.create; + finishedRoot.destroy = create$82(); + } + finishedRoot = finishedRoot.next; + } while (finishedRoot !== current); + } + current = finishedWork.updateQueue; + current = null !== current ? current.lastEffect : null; + if (null !== current) { + finishedRoot = current = current.next; + do { + var _effect = finishedRoot; + create$82 = _effect.next; + _effect = _effect.tag; + 0 !== (_effect & 4) && + 0 !== (_effect & 1) && + (enqueuePendingPassiveHookEffectUnmount(finishedWork, finishedRoot), + enqueuePendingPassiveHookEffectMount(finishedWork, finishedRoot)); + finishedRoot = create$82; + } while (finishedRoot !== current); + } return; case 1: finishedRoot = finishedWork.stateNode; - if (finishedWork.effectTag & 4) - if (null === current) finishedRoot.componentDidMount(); - else { - var prevProps = - finishedWork.elementType === finishedWork.type - ? current.memoizedProps - : resolveDefaultProps(finishedWork.type, current.memoizedProps); - finishedRoot.componentDidUpdate( - prevProps, - current.memoizedState, - finishedRoot.__reactInternalSnapshotBeforeUpdate - ); - } + finishedWork.flags & 4 && + (null === current + ? finishedRoot.componentDidMount() + : ((create$82 = + finishedWork.elementType === finishedWork.type + ? current.memoizedProps + : resolveDefaultProps( + finishedWork.type, + current.memoizedProps + )), + finishedRoot.componentDidUpdate( + create$82, + current.memoizedState, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ))); current = finishedWork.updateQueue; null !== current && commitUpdateQueue(finishedWork, current, finishedRoot); @@ -5094,16 +5454,16 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 4: return; case 12: - prevProps = finishedWork.memoizedProps.onRender; - var commitTime$jscomp$0 = commitTime; - "function" === typeof prevProps && - prevProps( + create$82 = finishedWork.memoizedProps.onRender; + _effect = commitTime; + "function" === typeof create$82 && + create$82( finishedWork.memoizedProps.id, null === current ? "mount" : "update", finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, - commitTime$jscomp$0, + _effect, finishedRoot.memoizedInteractions ); return; @@ -5113,78 +5473,137 @@ function commitLifeCycles(finishedRoot, current, finishedWork) { case 17: case 20: case 21: + case 22: + case 23: return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } -function commitUnmount(finishedRoot, current$jscomp$0, renderPriorityLevel) { - "function" === typeof onCommitFiberUnmount && - onCommitFiberUnmount(current$jscomp$0); - switch (current$jscomp$0.tag) { +function hideOrUnhideAllChildren(finishedWork, isHidden) { + for (var node = finishedWork; ; ) { + if (5 === node.tag) { + var instance = node.stateNode; + if (isHidden) { + var viewConfig = instance.viewConfig; + var updatePayload = diffProperties( + null, + emptyObject, + { style: { display: "none" } }, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } else { + instance = node.stateNode; + updatePayload = node.memoizedProps; + viewConfig = instance.viewConfig; + var prevProps = Object.assign({}, updatePayload, { + style: [updatePayload.style, { display: "none" }] + }); + updatePayload = diffProperties( + null, + prevProps, + updatePayload, + viewConfig.validAttributes + ); + ReactNativePrivateInterface.UIManager.updateView( + instance._nativeTag, + viewConfig.uiViewClassName, + updatePayload + ); + } + } else { + if (6 === node.tag) throw Error("Not yet implemented."); + if ( + ((22 !== node.tag && 23 !== node.tag) || + null === node.memoizedState || + node === finishedWork) && + null !== node.child + ) { + node.child.return = node; + node = node.child; + continue; + } + } + if (node === finishedWork) break; + for (; null === node.sibling; ) { + if (null === node.return || node.return === finishedWork) return; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } +} +function commitUnmount(finishedRoot, current) { + if (injectedHook && "function" === typeof injectedHook.onCommitFiberUnmount) + try { + injectedHook.onCommitFiberUnmount(rendererID, current); + } catch (err) {} + switch (current.tag) { case 0: case 11: case 14: case 15: - case 22: - finishedRoot = current$jscomp$0.updateQueue; + finishedRoot = current.updateQueue; if ( null !== finishedRoot && ((finishedRoot = finishedRoot.lastEffect), null !== finishedRoot) ) { - var firstEffect = finishedRoot.next; - runWithPriority( - 97 < renderPriorityLevel ? 97 : renderPriorityLevel, - function() { - var effect = firstEffect; - do { - var _destroy = effect.destroy; - if (void 0 !== _destroy) { - var current = current$jscomp$0; - try { - _destroy(); - } catch (error) { - captureCommitPhaseError(current, error); - } + var effect = (finishedRoot = finishedRoot.next); + do { + var _effect2 = effect, + destroy = _effect2.destroy; + _effect2 = _effect2.tag; + if (void 0 !== destroy) + if (0 !== (_effect2 & 4)) + enqueuePendingPassiveHookEffectUnmount(current, effect); + else { + _effect2 = current; + try { + destroy(); + } catch (error) { + captureCommitPhaseError(_effect2, error); } - effect = effect.next; - } while (effect !== firstEffect); - } - ); + } + effect = effect.next; + } while (effect !== finishedRoot); } break; case 1: - safelyDetachRef(current$jscomp$0); - renderPriorityLevel = current$jscomp$0.stateNode; - "function" === typeof renderPriorityLevel.componentWillUnmount && - safelyCallComponentWillUnmount(current$jscomp$0, renderPriorityLevel); + safelyDetachRef(current); + finishedRoot = current.stateNode; + if ("function" === typeof finishedRoot.componentWillUnmount) + try { + (finishedRoot.props = current.memoizedProps), + (finishedRoot.state = current.memoizedState), + finishedRoot.componentWillUnmount(); + } catch (unmountError) { + captureCommitPhaseError(current, unmountError); + } break; case 5: - safelyDetachRef(current$jscomp$0); + safelyDetachRef(current); break; case 4: - unmountHostComponents( - finishedRoot, - current$jscomp$0, - renderPriorityLevel - ); + unmountHostComponents(finishedRoot, current); } } -function detachFiber(current) { - var alternate = current.alternate; - current.return = null; - current.child = null; - current.memoizedState = null; - current.updateQueue = null; - current.dependencies = null; - current.alternate = null; - current.firstEffect = null; - current.lastEffect = null; - current.pendingProps = null; - current.memoizedProps = null; - current.stateNode = null; - null !== alternate && detachFiber(alternate); +function detachFiberMutation(fiber) { + fiber.alternate = null; + fiber.child = null; + fiber.dependencies = null; + fiber.firstEffect = null; + fiber.lastEffect = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.return = null; + fiber.updateQueue = null; } function isHostParent(fiber) { return 5 === fiber.tag || 3 === fiber.tag || 4 === fiber.tag; @@ -5192,16 +5611,14 @@ function isHostParent(fiber) { function commitPlacement(finishedWork) { a: { for (var parent = finishedWork.return; null !== parent; ) { - if (isHostParent(parent)) { - var parentFiber = parent; - break a; - } + if (isHostParent(parent)) break a; parent = parent.return; } throw Error( "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue." ); } + var parentFiber = parent; parent = parentFiber.stateNode; switch (parentFiber.tag) { case 5: @@ -5220,7 +5637,7 @@ function commitPlacement(finishedWork) { "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue." ); } - parentFiber.effectTag & 16 && (parentFiber.effectTag &= -17); + parentFiber.flags & 16 && (parentFiber.flags &= -17); a: b: for (parentFiber = finishedWork; ; ) { for (; null === parentFiber.sibling; ) { if (null === parentFiber.return || isHostParent(parentFiber.return)) { @@ -5235,13 +5652,13 @@ function commitPlacement(finishedWork) { 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { - if (parentFiber.effectTag & 2) continue b; + if (parentFiber.flags & 2) continue b; if (null === parentFiber.child || 4 === parentFiber.tag) continue b; else (parentFiber.child.return = parentFiber), (parentFiber = parentFiber.child); } - if (!(parentFiber.effectTag & 2)) { + if (!(parentFiber.flags & 2)) { parentFiber = parentFiber.stateNode; break a; } @@ -5336,11 +5753,7 @@ function insertOrAppendPlacementNode(node, before, parent) { ) insertOrAppendPlacementNode(node, before, parent), (node = node.sibling); } -function unmountHostComponents( - finishedRoot$jscomp$0, - current, - renderPriorityLevel$jscomp$0 -) { +function unmountHostComponents(finishedRoot$jscomp$0, current) { for ( var node = current, currentParentIsValid = !1, @@ -5378,13 +5791,12 @@ function unmountHostComponents( a: for ( var finishedRoot = finishedRoot$jscomp$0, root = node, - renderPriorityLevel = renderPriorityLevel$jscomp$0, node$jscomp$0 = root; ; ) if ( - (commitUnmount(finishedRoot, node$jscomp$0, renderPriorityLevel), + (commitUnmount(finishedRoot, node$jscomp$0), null !== node$jscomp$0.child && 4 !== node$jscomp$0.tag) ) (node$jscomp$0.child.return = node$jscomp$0), @@ -5411,18 +5823,18 @@ function unmountHostComponents( [0] )) : ((finishedRoot = currentParent), - (renderPriorityLevel = node.stateNode), - recursivelyUncacheFiberNode(renderPriorityLevel), + (node$jscomp$0 = node.stateNode), + recursivelyUncacheFiberNode(node$jscomp$0), (root = finishedRoot._children), - (renderPriorityLevel = root.indexOf(renderPriorityLevel)), - root.splice(renderPriorityLevel, 1), + (node$jscomp$0 = root.indexOf(node$jscomp$0)), + root.splice(node$jscomp$0, 1), ReactNativePrivateInterface.UIManager.manageChildren( finishedRoot._nativeTag, [], [], [], [], - [renderPriorityLevel] + [node$jscomp$0] )); } else if (4 === node.tag) { if (null !== node.child) { @@ -5433,8 +5845,7 @@ function unmountHostComponents( continue; } } else if ( - (commitUnmount(finishedRoot$jscomp$0, node, renderPriorityLevel$jscomp$0), - null !== node.child) + (commitUnmount(finishedRoot$jscomp$0, node), null !== node.child) ) { node.child.return = node; node = node.child; @@ -5456,32 +5867,42 @@ function commitWork(current, finishedWork) { case 11: case 14: case 15: - case 22: - commitHookEffectListUnmount(3, finishedWork); + var updateQueue = finishedWork.updateQueue; + updateQueue = null !== updateQueue ? updateQueue.lastEffect : null; + if (null !== updateQueue) { + var effect = (updateQueue = updateQueue.next); + do + 3 === (effect.tag & 3) && + ((finishedWork = effect.destroy), + (effect.destroy = void 0), + void 0 !== finishedWork && finishedWork()), + (effect = effect.next); + while (effect !== updateQueue); + } return; case 1: return; case 5: - var instance = finishedWork.stateNode; - if (null != instance) { - var newProps = finishedWork.memoizedProps; - current = null !== current ? current.memoizedProps : newProps; + updateQueue = finishedWork.stateNode; + if (null != updateQueue) { + effect = finishedWork.memoizedProps; + current = null !== current ? current.memoizedProps : effect; var updatePayload = finishedWork.updateQueue; finishedWork.updateQueue = null; null !== updatePayload && - ((finishedWork = instance.viewConfig), - instanceProps.set(instance._nativeTag, newProps), - (newProps = diffProperties( + ((finishedWork = updateQueue.viewConfig), + instanceProps.set(updateQueue._nativeTag, effect), + (effect = diffProperties( null, current, - newProps, + effect, finishedWork.validAttributes )), - null != newProps && + null != effect && ReactNativePrivateInterface.UIManager.updateView( - instance._nativeTag, + updateQueue._nativeTag, finishedWork.uiViewClassName, - newProps + effect )); } return; @@ -5501,72 +5922,9 @@ function commitWork(current, finishedWork) { case 12: return; case 13: - instance = finishedWork; - null === finishedWork.memoizedState - ? (newProps = !1) - : ((newProps = !0), - (instance = finishedWork.child), - (globalMostRecentFallbackTime = now())); - if (null !== instance) - a: for (current = instance; ; ) { - if (5 === current.tag) - if (((updatePayload = current.stateNode), newProps)) { - var viewConfig = updatePayload.viewConfig; - var updatePayload$jscomp$0 = diffProperties( - null, - emptyObject, - { style: { display: "none" } }, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - updatePayload._nativeTag, - viewConfig.uiViewClassName, - updatePayload$jscomp$0 - ); - } else { - updatePayload = current.stateNode; - updatePayload$jscomp$0 = current.memoizedProps; - viewConfig = updatePayload.viewConfig; - var prevProps = Object.assign({}, updatePayload$jscomp$0, { - style: [updatePayload$jscomp$0.style, { display: "none" }] - }); - updatePayload$jscomp$0 = diffProperties( - null, - prevProps, - updatePayload$jscomp$0, - viewConfig.validAttributes - ); - ReactNativePrivateInterface.UIManager.updateView( - updatePayload._nativeTag, - viewConfig.uiViewClassName, - updatePayload$jscomp$0 - ); - } - else { - if (6 === current.tag) throw Error("Not yet implemented."); - if ( - 13 === current.tag && - null !== current.memoizedState && - null === current.memoizedState.dehydrated - ) { - updatePayload = current.child.sibling; - updatePayload.return = current; - current = updatePayload; - continue; - } else if (null !== current.child) { - current.child.return = current; - current = current.child; - continue; - } - } - if (current === instance) break; - for (; null === current.sibling; ) { - if (null === current.return || current.return === instance) break a; - current = current.return; - } - current.sibling.return = current.return; - current = current.sibling; - } + null !== finishedWork.memoizedState && + ((globalMostRecentFallbackTime = now()), + hideOrUnhideAllChildren(finishedWork.child, !0)); attachSuspenseRetryListeners(finishedWork); return; case 19: @@ -5574,93 +5932,61 @@ function commitWork(current, finishedWork) { return; case 17: return; + case 22: + case 23: + hideOrUnhideAllChildren( + finishedWork, + null !== finishedWork.memoizedState + ); + return; } throw Error( "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." ); } function attachSuspenseRetryListeners(finishedWork) { - var thenables = finishedWork.updateQueue; - if (null !== thenables) { + var wakeables = finishedWork.updateQueue; + if (null !== wakeables) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); - thenables.forEach(function(thenable) { - var retry = resolveRetryThenable.bind(null, finishedWork, thenable); - retryCache.has(thenable) || - (!0 !== thenable.__reactDoNotTraceInteractions && + wakeables.forEach(function(wakeable) { + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + retryCache.has(wakeable) || + (!0 !== wakeable.__reactDoNotTraceInteractions && (retry = tracing.unstable_wrap(retry)), - retryCache.add(thenable), - thenable.then(retry, retry)); + retryCache.add(wakeable), + wakeable.then(retry, retry)); }); } } -var PossiblyWeakMap = "function" === typeof WeakMap ? WeakMap : Map; -function createRootErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - expirationTime.payload = { element: null }; - var error = errorInfo.value; - expirationTime.callback = function() { - hasUncaughtError || ((hasUncaughtError = !0), (firstUncaughtError = error)); - logError(fiber, errorInfo); - }; - return expirationTime; -} -function createClassErrorUpdate(fiber, errorInfo, expirationTime) { - expirationTime = createUpdate(expirationTime, null); - expirationTime.tag = 3; - var getDerivedStateFromError = fiber.type.getDerivedStateFromError; - if ("function" === typeof getDerivedStateFromError) { - var error = errorInfo.value; - expirationTime.payload = function() { - logError(fiber, errorInfo); - return getDerivedStateFromError(error); - }; - } - var inst = fiber.stateNode; - null !== inst && - "function" === typeof inst.componentDidCatch && - (expirationTime.callback = function() { - "function" !== typeof getDerivedStateFromError && - (null === legacyErrorBoundariesThatAlreadyFailed - ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this])) - : legacyErrorBoundariesThatAlreadyFailed.add(this), - logError(fiber, errorInfo)); - var stack = errorInfo.stack; - this.componentDidCatch(errorInfo.value, { - componentStack: null !== stack ? stack : "" - }); - }); - return expirationTime; +function isSuspenseBoundaryBeingHidden(current, finishedWork) { + return null !== current && + ((current = current.memoizedState), + null === current || null !== current.dehydrated) + ? ((finishedWork = finishedWork.memoizedState), + null !== finishedWork && null === finishedWork.dehydrated) + : !1; } var ceil = Math.ceil, - ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, + ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, - NoContext = 0, - LegacyUnbatchedContext = 8, - RenderContext = 16, - CommitContext = 32, - RootIncomplete = 0, - RootFatalErrored = 1, - RootErrored = 2, - RootSuspended = 3, - RootSuspendedWithDelay = 4, - RootCompleted = 5, - executionContext = NoContext, + executionContext = 0, workInProgressRoot = null, workInProgress = null, - renderExpirationTime$1 = 0, - workInProgressRootExitStatus = RootIncomplete, + workInProgressRootRenderLanes = 0, + subtreeRenderLanes = 0, + subtreeRenderLanesCursor = createCursor(0), + workInProgressRootExitStatus = 0, workInProgressRootFatalError = null, - workInProgressRootLatestProcessedExpirationTime = 1073741823, - workInProgressRootLatestSuspenseTimeout = 1073741823, - workInProgressRootCanSuspendUsingConfig = null, - workInProgressRootNextUnprocessedUpdateTime = 0, - workInProgressRootHasPendingPing = !1, + workInProgressRootIncludedLanes = 0, + workInProgressRootSkippedLanes = 0, + workInProgressRootUpdatedLanes = 0, + workInProgressRootPingedLanes = 0, + mostRecentlyUpdatedRoot = null, globalMostRecentFallbackTime = 0, - FALLBACK_THROTTLE_MS = 500, + workInProgressRootRenderTargetTime = Infinity, nextEffect = null, hasUncaughtError = !1, firstUncaughtError = null, @@ -5668,201 +5994,192 @@ var ceil = Math.ceil, rootDoesHavePassiveEffects = !1, rootWithPendingPassiveEffects = null, pendingPassiveEffectsRenderPriority = 90, - pendingPassiveEffectsExpirationTime = 0, + pendingPassiveEffectsLanes = 0, + pendingPassiveHookEffectsMount = [], + pendingPassiveHookEffectsUnmount = [], rootsWithPendingDiscreteUpdates = null, nestedUpdateCount = 0, rootWithNestedUpdates = null, spawnedWorkDuringRender = null, - currentEventTime = 0; -function requestCurrentTimeForUpdate() { - return (executionContext & (RenderContext | CommitContext)) !== NoContext - ? 1073741821 - ((now() / 10) | 0) - : 0 !== currentEventTime + currentEventTime = -1, + currentEventWipLanes = 0, + currentEventPendingLanes = 0, + focusedInstanceHandle = null, + shouldFireAfterActiveInstanceBlur = !1; +function requestEventTime() { + return 0 !== (executionContext & 48) + ? now() + : -1 !== currentEventTime ? currentEventTime - : (currentEventTime = 1073741821 - ((now() / 10) | 0)); + : (currentEventTime = now()); } -function computeExpirationForFiber(currentTime, fiber, suspenseConfig) { +function requestUpdateLane(fiber) { fiber = fiber.mode; - if (0 === (fiber & 2)) return 1073741823; - var priorityLevel = getCurrentPriorityLevel(); - if (0 === (fiber & 4)) return 99 === priorityLevel ? 1073741823 : 1073741822; - if ((executionContext & RenderContext) !== NoContext) - return renderExpirationTime$1; - if (null !== suspenseConfig) - currentTime = - 1073741821 - - 25 * - ((((1073741821 - - currentTime + - (suspenseConfig.timeoutMs | 0 || 5e3) / 10) / - 25) | - 0) + - 1); - else - switch (priorityLevel) { - case 99: - currentTime = 1073741823; - break; - case 98: - currentTime = - 1073741821 - 10 * ((((1073741821 - currentTime + 15) / 10) | 0) + 1); - break; - case 97: - case 96: - currentTime = - 1073741821 - 25 * ((((1073741821 - currentTime + 500) / 25) | 0) + 1); - break; - case 95: - currentTime = 2; - break; - default: - throw Error("Expected a valid priority level"); - } - null !== workInProgressRoot && - currentTime === renderExpirationTime$1 && - --currentTime; - return currentTime; -} -function scheduleWork(fiber, expirationTime) { + if (0 === (fiber & 2)) return 1; + if (0 === (fiber & 4)) return 99 === getCurrentPriorityLevel() ? 1 : 2; + 0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes); + if (0 !== ReactCurrentBatchConfig.transition) { + 0 !== currentEventPendingLanes && + (currentEventPendingLanes = + null !== mostRecentlyUpdatedRoot + ? mostRecentlyUpdatedRoot.pendingLanes + : 0); + fiber = currentEventWipLanes; + var lane = 4186112 & ~currentEventPendingLanes; + lane &= -lane; + 0 === lane && + ((fiber = 4186112 & ~fiber), + (lane = fiber & -fiber), + 0 === lane && (lane = 8192)); + return lane; + } + fiber = getCurrentPriorityLevel(); + 0 !== (executionContext & 4) && 98 === fiber + ? (fiber = findUpdateLane(12, currentEventWipLanes)) + : ((fiber = schedulerPriorityToLanePriority(fiber)), + (fiber = findUpdateLane(fiber, currentEventWipLanes))); + return fiber; +} +function scheduleUpdateOnFiber(fiber, lane, eventTime) { if (50 < nestedUpdateCount) throw ((nestedUpdateCount = 0), (rootWithNestedUpdates = null), Error( "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." )); - fiber = markUpdateTimeFromFiberToRoot(fiber, expirationTime); - if (null !== fiber) { - var priorityLevel = getCurrentPriorityLevel(); - 1073741823 === expirationTime - ? (executionContext & LegacyUnbatchedContext) !== NoContext && - (executionContext & (RenderContext | CommitContext)) === NoContext - ? (schedulePendingInteractions(fiber, expirationTime), - performSyncWorkOnRoot(fiber)) - : (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, expirationTime), - executionContext === NoContext && flushSyncCallbackQueue()) - : (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, expirationTime)); - (executionContext & 4) === NoContext || - (98 !== priorityLevel && 99 !== priorityLevel) || - (null === rootsWithPendingDiscreteUpdates - ? (rootsWithPendingDiscreteUpdates = new Map([[fiber, expirationTime]])) - : ((priorityLevel = rootsWithPendingDiscreteUpdates.get(fiber)), - (void 0 === priorityLevel || priorityLevel > expirationTime) && - rootsWithPendingDiscreteUpdates.set(fiber, expirationTime))); - } -} -function markUpdateTimeFromFiberToRoot(fiber, expirationTime) { - fiber.expirationTime < expirationTime && - (fiber.expirationTime = expirationTime); - var alternate = fiber.alternate; - null !== alternate && - alternate.expirationTime < expirationTime && - (alternate.expirationTime = expirationTime); - var node = fiber.return, - root = null; - if (null === node && 3 === fiber.tag) root = fiber.stateNode; - else - for (; null !== node; ) { - alternate = node.alternate; - node.childExpirationTime < expirationTime && - (node.childExpirationTime = expirationTime); - null !== alternate && - alternate.childExpirationTime < expirationTime && - (alternate.childExpirationTime = expirationTime); - if (null === node.return && 3 === node.tag) { - root = node.stateNode; - break; + fiber = markUpdateLaneFromFiberToRoot(fiber, lane); + if (null === fiber) return null; + markRootUpdated(fiber, lane, eventTime); + fiber === workInProgressRoot && + ((workInProgressRootUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(fiber, workInProgressRootRenderLanes)); + var priorityLevel = getCurrentPriorityLevel(); + 1 === lane + ? 0 !== (executionContext & 8) && 0 === (executionContext & 48) + ? (schedulePendingInteractions(fiber, lane), performSyncWorkOnRoot(fiber)) + : (ensureRootIsScheduled(fiber, eventTime), + schedulePendingInteractions(fiber, lane), + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue())) + : (0 === (executionContext & 4) || + (98 !== priorityLevel && 99 !== priorityLevel) || + (null === rootsWithPendingDiscreteUpdates + ? (rootsWithPendingDiscreteUpdates = new Set([fiber])) + : rootsWithPendingDiscreteUpdates.add(fiber)), + ensureRootIsScheduled(fiber, eventTime), + schedulePendingInteractions(fiber, lane)); + mostRecentlyUpdatedRoot = fiber; +} +function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { + sourceFiber.lanes |= lane; + var alternate = sourceFiber.alternate; + null !== alternate && (alternate.lanes |= lane); + alternate = sourceFiber; + for (sourceFiber = sourceFiber.return; null !== sourceFiber; ) + (sourceFiber.childLanes |= lane), + (alternate = sourceFiber.alternate), + null !== alternate && (alternate.childLanes |= lane), + (alternate = sourceFiber), + (sourceFiber = sourceFiber.return); + return 3 === alternate.tag ? alternate.stateNode : null; +} +function ensureRootIsScheduled(root, currentTime) { + for ( + var existingCallbackNode = root.callbackNode, + suspendedLanes = root.suspendedLanes, + pingedLanes = root.pingedLanes, + expirationTimes = root.expirationTimes, + lanes = root.pendingLanes; + 0 < lanes; + + ) { + var index$7 = 31 - clz32(lanes), + lane = 1 << index$7, + expirationTime = expirationTimes[index$7]; + if (-1 === expirationTime) { + if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) { + expirationTime = currentTime; + getHighestPriorityLanes(lane); + var priority = return_highestLanePriority; + expirationTimes[index$7] = + 10 <= priority + ? expirationTime + 250 + : 6 <= priority + ? expirationTime + 5e3 + : -1; } - node = node.return; - } - null !== root && - (workInProgressRoot === root && - (markUnprocessedUpdateTime(expirationTime), - workInProgressRootExitStatus === RootSuspendedWithDelay && - markRootSuspendedAtTime(root, renderExpirationTime$1)), - markRootUpdatedAtTime(root, expirationTime)); - return root; -} -function getNextRootExpirationTimeToWorkOn(root) { - var lastExpiredTime = root.lastExpiredTime; - if (0 !== lastExpiredTime) return lastExpiredTime; - lastExpiredTime = root.firstPendingTime; - if (!isRootSuspendedAtTime(root, lastExpiredTime)) return lastExpiredTime; - var lastPingedTime = root.lastPingedTime; - root = root.nextKnownPendingLevel; - root = lastPingedTime > root ? lastPingedTime : root; - return 2 >= root && lastExpiredTime !== root ? 0 : root; -} -function ensureRootIsScheduled(root) { - if (0 !== root.lastExpiredTime) - (root.callbackExpirationTime = 1073741823), - (root.callbackPriority = 99), - (root.callbackNode = scheduleSyncCallback( - performSyncWorkOnRoot.bind(null, root) - )); + } else expirationTime <= currentTime && (root.expiredLanes |= lane); + lanes &= ~lane; + } + suspendedLanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + currentTime = return_highestLanePriority; + if (0 === suspendedLanes) + null !== existingCallbackNode && + (existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode), + (root.callbackNode = null), + (root.callbackPriority = 0)); else { - var expirationTime = getNextRootExpirationTimeToWorkOn(root), - existingCallbackNode = root.callbackNode; - if (0 === expirationTime) - null !== existingCallbackNode && - ((root.callbackNode = null), - (root.callbackExpirationTime = 0), - (root.callbackPriority = 90)); - else { - var currentTime = requestCurrentTimeForUpdate(); - currentTime = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - if (null !== existingCallbackNode) { - var existingCallbackPriority = root.callbackPriority; - if ( - root.callbackExpirationTime === expirationTime && - existingCallbackPriority >= currentTime - ) - return; - existingCallbackNode !== fakeCallbackNode && - Scheduler_cancelCallback(existingCallbackNode); - } - root.callbackExpirationTime = expirationTime; - root.callbackPriority = currentTime; - expirationTime = - 1073741823 === expirationTime - ? scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)) - : scheduleCallback( - currentTime, - performConcurrentWorkOnRoot.bind(null, root), - { timeout: 10 * (1073741821 - expirationTime) - now() } - ); - root.callbackNode = expirationTime; + if (null !== existingCallbackNode) { + if (root.callbackPriority === currentTime) return; + existingCallbackNode !== fakeCallbackNode && + Scheduler_cancelCallback(existingCallbackNode); } + 15 === currentTime + ? ((existingCallbackNode = performSyncWorkOnRoot.bind(null, root)), + null === syncQueue + ? ((syncQueue = [existingCallbackNode]), + (immediateQueueCallbackNode = Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueueImpl + ))) + : syncQueue.push(existingCallbackNode), + (existingCallbackNode = fakeCallbackNode)) + : 14 === currentTime + ? (existingCallbackNode = scheduleCallback( + 99, + performSyncWorkOnRoot.bind(null, root) + )) + : ((existingCallbackNode = lanePriorityToSchedulerPriority(currentTime)), + (existingCallbackNode = scheduleCallback( + existingCallbackNode, + performConcurrentWorkOnRoot.bind(null, root) + ))); + root.callbackPriority = currentTime; + root.callbackNode = existingCallbackNode; } } -function performConcurrentWorkOnRoot(root, didTimeout) { - currentEventTime = 0; - if (didTimeout) { - didTimeout = requestCurrentTimeForUpdate(); - var lastExpiredTime = root.lastExpiredTime; - if (0 === lastExpiredTime || lastExpiredTime > didTimeout) - root.lastExpiredTime = didTimeout; - ensureRootIsScheduled(root); - return null; - } - lastExpiredTime = getNextRootExpirationTimeToWorkOn(root); - if (0 === lastExpiredTime) return null; - didTimeout = root.callbackNode; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) +function performConcurrentWorkOnRoot(root) { + currentEventTime = -1; + currentEventPendingLanes = currentEventWipLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - flushPassiveEffects(); - var expirationTime = lastExpiredTime, - prevExecutionContext = executionContext; - executionContext |= RenderContext; - var exitStatus = pushDispatcher(); - if (root !== workInProgressRoot || expirationTime !== renderExpirationTime$1) - prepareFreshStack(root, expirationTime), - startWorkOnPendingInteractions(root, expirationTime); - expirationTime = pushInteractions(root); + var originalCallbackNode = root.callbackNode; + if (flushPassiveEffects() && root.callbackNode !== originalCallbackNode) + return null; + var lanes = getNextLanes( + root, + root === workInProgressRoot ? workInProgressRootRenderLanes : 0 + ); + if (0 === lanes) return null; + var lanes$jscomp$0 = lanes; + var exitStatus = executionContext; + executionContext |= 16; + var prevDispatcher = pushDispatcher(); + if ( + workInProgressRoot !== root || + workInProgressRootRenderLanes !== lanes$jscomp$0 + ) + (workInProgressRootRenderTargetTime = now() + 500), + prepareFreshStack(root, lanes$jscomp$0), + startWorkOnPendingInteractions(root, lanes$jscomp$0); + lanes$jscomp$0 = pushInteractions(root); do try { workLoopConcurrent(); @@ -5872,205 +6189,164 @@ function performConcurrentWorkOnRoot(root, didTimeout) { } while (1); resetContextDependencies(); - tracing.__interactionsRef.current = expirationTime; - ReactCurrentDispatcher$1.current = exitStatus; - executionContext = prevExecutionContext; + tracing.__interactionsRef.current = lanes$jscomp$0; + ReactCurrentDispatcher$2.current = prevDispatcher; + executionContext = exitStatus; null !== workInProgress - ? (exitStatus = RootIncomplete) + ? (exitStatus = 0) : ((workInProgressRoot = null), + (workInProgressRootRenderLanes = 0), (exitStatus = workInProgressRootExitStatus)); - if (exitStatus !== RootIncomplete) { - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) - throw ((didTimeout = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), - didTimeout); - prevExecutionContext = root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + if (0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes)) + prepareFreshStack(root, 0); + else if (0 !== exitStatus) { + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && (root.hydrate = !1), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) + throw ((originalCallbackNode = workInProgressRootFatalError), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), + originalCallbackNode); + root.finishedWork = root.current.alternate; + root.finishedLanes = lanes; switch (exitStatus) { - case RootIncomplete: - case RootFatalErrored: + case 0: + case 1: throw Error("Root did not complete. This is a bug in React."); - case RootErrored: + case 2: commitRoot(root); break; - case RootSuspended: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - prevExecutionContext - )); + case 3: + markRootSuspended$1(root, lanes); if ( - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - ((prevExecutionContext = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now()), - 10 < prevExecutionContext) + (lanes & 62914560) === lanes && + ((exitStatus = globalMostRecentFallbackTime + 500 - now()), + 10 < exitStatus) ) { - if ( - workInProgressRootHasPendingPing && - ((expirationTime = root.lastPingedTime), - 0 === expirationTime || expirationTime >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - expirationTime = getNextRootExpirationTimeToWorkOn(root); - if (0 !== expirationTime && expirationTime !== lastExpiredTime) break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; + if (0 !== getNextLanes(root, 0)) break; + prevDispatcher = root.suspendedLanes; + if ((prevDispatcher & lanes) !== lanes) { + requestEventTime(); + root.pingedLanes |= root.suspendedLanes & prevDispatcher; break; } root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - prevExecutionContext + exitStatus ); break; } commitRoot(root); break; - case RootSuspendedWithDelay: - markRootSuspendedAtTime(root, lastExpiredTime); - exitStatus = root.lastSuspendedTime; - lastExpiredTime === exitStatus && - (root.nextKnownPendingLevel = getRemainingExpirationTime( - prevExecutionContext - )); - if ( - workInProgressRootHasPendingPing && - ((prevExecutionContext = root.lastPingedTime), - 0 === prevExecutionContext || prevExecutionContext >= lastExpiredTime) - ) { - root.lastPingedTime = lastExpiredTime; - prepareFreshStack(root, lastExpiredTime); - break; - } - prevExecutionContext = getNextRootExpirationTimeToWorkOn(root); - if ( - 0 !== prevExecutionContext && - prevExecutionContext !== lastExpiredTime - ) - break; - if (0 !== exitStatus && exitStatus !== lastExpiredTime) { - root.lastPingedTime = exitStatus; - break; + case 4: + markRootSuspended$1(root, lanes); + if ((lanes & 4186112) === lanes) break; + exitStatus = root.eventTimes; + for (prevDispatcher = -1; 0 < lanes; ) { + var index$6 = 31 - clz32(lanes); + lanes$jscomp$0 = 1 << index$6; + index$6 = exitStatus[index$6]; + index$6 > prevDispatcher && (prevDispatcher = index$6); + lanes &= ~lanes$jscomp$0; } - 1073741823 !== workInProgressRootLatestSuspenseTimeout - ? (prevExecutionContext = - 10 * (1073741821 - workInProgressRootLatestSuspenseTimeout) - - now()) - : 1073741823 === workInProgressRootLatestProcessedExpirationTime - ? (prevExecutionContext = 0) - : ((prevExecutionContext = - 10 * - (1073741821 - workInProgressRootLatestProcessedExpirationTime) - - 5e3), - (exitStatus = now()), - (lastExpiredTime = - 10 * (1073741821 - lastExpiredTime) - exitStatus), - (prevExecutionContext = exitStatus - prevExecutionContext), - 0 > prevExecutionContext && (prevExecutionContext = 0), - (prevExecutionContext = - (120 > prevExecutionContext - ? 120 - : 480 > prevExecutionContext - ? 480 - : 1080 > prevExecutionContext - ? 1080 - : 1920 > prevExecutionContext - ? 1920 - : 3e3 > prevExecutionContext - ? 3e3 - : 4320 > prevExecutionContext - ? 4320 - : 1960 * ceil(prevExecutionContext / 1960)) - - prevExecutionContext), - lastExpiredTime < prevExecutionContext && - (prevExecutionContext = lastExpiredTime)); - if (10 < prevExecutionContext) { + lanes = prevDispatcher; + lanes = now() - lanes; + lanes = + (120 > lanes + ? 120 + : 480 > lanes + ? 480 + : 1080 > lanes + ? 1080 + : 1920 > lanes + ? 1920 + : 3e3 > lanes + ? 3e3 + : 4320 > lanes + ? 4320 + : 1960 * ceil(lanes / 1960)) - lanes; + if (10 < lanes) { root.timeoutHandle = scheduleTimeout( commitRoot.bind(null, root), - prevExecutionContext + lanes ); break; } commitRoot(root); break; - case RootCompleted: - if ( - 1073741823 !== workInProgressRootLatestProcessedExpirationTime && - null !== workInProgressRootCanSuspendUsingConfig - ) { - expirationTime = workInProgressRootLatestProcessedExpirationTime; - var suspenseConfig = workInProgressRootCanSuspendUsingConfig; - prevExecutionContext = suspenseConfig.busyMinDurationMs | 0; - 0 >= prevExecutionContext - ? (prevExecutionContext = 0) - : ((exitStatus = suspenseConfig.busyDelayMs | 0), - (expirationTime = - now() - - (10 * (1073741821 - expirationTime) - - (suspenseConfig.timeoutMs | 0 || 5e3))), - (prevExecutionContext = - expirationTime <= exitStatus - ? 0 - : exitStatus + prevExecutionContext - expirationTime)); - if (10 < prevExecutionContext) { - markRootSuspendedAtTime(root, lastExpiredTime); - root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), - prevExecutionContext - ); - break; - } - } + case 5: commitRoot(root); break; default: throw Error("Unknown root exit status."); } } - ensureRootIsScheduled(root); - return root.callbackNode === didTimeout + ensureRootIsScheduled(root, now()); + return root.callbackNode === originalCallbackNode ? performConcurrentWorkOnRoot.bind(null, root) : null; } +function markRootSuspended$1(root, suspendedLanes) { + suspendedLanes &= ~workInProgressRootPingedLanes; + suspendedLanes &= ~workInProgressRootUpdatedLanes; + root.suspendedLanes |= suspendedLanes; + root.pingedLanes &= ~suspendedLanes; + for (root = root.expirationTimes; 0 < suspendedLanes; ) { + var index$11 = 31 - clz32(suspendedLanes), + lane = 1 << index$11; + root[index$11] = -1; + suspendedLanes &= ~lane; + } +} function performSyncWorkOnRoot(root) { - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); flushPassiveEffects(); - var lastExpiredTime = root.lastExpiredTime; - lastExpiredTime = - 0 !== lastExpiredTime - ? root === workInProgressRoot && renderExpirationTime$1 >= lastExpiredTime - ? renderExpirationTime$1 - : lastExpiredTime - : 1073741823; - var exitStatus = renderRootSync(root, lastExpiredTime); + if ( + root === workInProgressRoot && + 0 !== (root.expiredLanes & workInProgressRootRenderLanes) + ) { + var lanes = workInProgressRootRenderLanes; + var exitStatus = renderRootSync(root, lanes); + 0 !== (workInProgressRootIncludedLanes & workInProgressRootUpdatedLanes) && + ((lanes = getNextLanes(root, lanes)), + (exitStatus = renderRootSync(root, lanes))); + } else + (lanes = getNextLanes(root, 0)), (exitStatus = renderRootSync(root, lanes)); 0 !== root.tag && - exitStatus === RootErrored && - ((lastExpiredTime = 2 < lastExpiredTime ? 2 : lastExpiredTime), - (exitStatus = renderRootSync(root, lastExpiredTime))); - if (exitStatus === RootFatalErrored) + 2 === exitStatus && + ((executionContext |= 64), + root.hydrate && (root.hydrate = !1), + (lanes = getLanesToRetrySynchronouslyOnError(root)), + 0 !== lanes && (exitStatus = renderRootSync(root, lanes))); + if (1 === exitStatus) throw ((exitStatus = workInProgressRootFatalError), - prepareFreshStack(root, lastExpiredTime), - markRootSuspendedAtTime(root, lastExpiredTime), - ensureRootIsScheduled(root), + prepareFreshStack(root, 0), + markRootSuspended$1(root, lanes), + ensureRootIsScheduled(root, now()), exitStatus); root.finishedWork = root.current.alternate; - root.finishedExpirationTime = lastExpiredTime; + root.finishedLanes = lanes; commitRoot(root); - ensureRootIsScheduled(root); + ensureRootIsScheduled(root, now()); return null; } -function prepareFreshStack(root, expirationTime) { +function pushRenderLanes(fiber, lanes) { + push(subtreeRenderLanesCursor, subtreeRenderLanes); + subtreeRenderLanes |= lanes; + workInProgressRootIncludedLanes |= lanes; +} +function popRenderLanes() { + subtreeRenderLanes = subtreeRenderLanesCursor.current; + pop(subtreeRenderLanesCursor); +} +function prepareFreshStack(root, lanes) { root.finishedWork = null; - root.finishedExpirationTime = 0; + root.finishedLanes = 0; var timeoutHandle = root.timeoutHandle; -1 !== timeoutHandle && ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle)); @@ -6088,6 +6364,7 @@ function prepareFreshStack(root, expirationTime) { popHostContainer(); pop(didPerformWorkStackCursor); pop(contextStackCursor); + resetWorkInProgressVersions(); break; case 5: popHostContext(interruptedWork); @@ -6103,26 +6380,28 @@ function prepareFreshStack(root, expirationTime) { break; case 10: popProvider(interruptedWork); + break; + case 22: + case 23: + popRenderLanes(); } timeoutHandle = timeoutHandle.return; } workInProgressRoot = root; workInProgress = createWorkInProgress(root.current, null); - renderExpirationTime$1 = expirationTime; - workInProgressRootExitStatus = RootIncomplete; + workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; + workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootLatestSuspenseTimeout = workInProgressRootLatestProcessedExpirationTime = 1073741823; - workInProgressRootCanSuspendUsingConfig = null; - workInProgressRootNextUnprocessedUpdateTime = 0; - workInProgressRootHasPendingPing = !1; + workInProgressRootPingedLanes = workInProgressRootUpdatedLanes = workInProgressRootSkippedLanes = 0; spawnedWorkDuringRender = null; } function handleError(root$jscomp$0, thrownValue) { do { + var erroredWork = workInProgress; try { resetContextDependencies(); - ReactCurrentDispatcher.current = ContextOnlyDispatcher; - if (didScheduleRenderPhaseUpdate) + ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + if (didScheduleRenderPhaseUpdate) { for ( var hook = currentlyRenderingFiber$1.memoizedState; null !== hook; @@ -6132,51 +6411,54 @@ function handleError(root$jscomp$0, thrownValue) { null !== queue && (queue.pending = null); hook = hook.next; } - renderExpirationTime = 0; + didScheduleRenderPhaseUpdate = !1; + } + renderLanes = 0; workInProgressHook = currentHook = currentlyRenderingFiber$1 = null; - didScheduleRenderPhaseUpdate = !1; - if (null === workInProgress || null === workInProgress.return) - return ( - (workInProgressRootExitStatus = RootFatalErrored), - (workInProgressRootFatalError = thrownValue), - (workInProgress = null) - ); - workInProgress.mode & 8 && - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !0); + didScheduleRenderPhaseUpdateDuringThisPass = !1; + ReactCurrentOwner$2.current = null; + if (null === erroredWork || null === erroredWork.return) { + workInProgressRootExitStatus = 1; + workInProgressRootFatalError = thrownValue; + workInProgress = null; + break; + } + erroredWork.mode & 8 && + stopProfilerTimerIfRunningAndRecordDelta(erroredWork, !0); a: { var root = root$jscomp$0, - returnFiber = workInProgress.return, - sourceFiber = workInProgress, + returnFiber = erroredWork.return, + sourceFiber = erroredWork, value = thrownValue; - thrownValue = renderExpirationTime$1; - sourceFiber.effectTag |= 2048; + thrownValue = workInProgressRootRenderLanes; + sourceFiber.flags |= 4096; sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( null !== value && "object" === typeof value && "function" === typeof value.then ) { - var thenable = value; + var wakeable = value; if (0 === (sourceFiber.mode & 2)) { var currentSource = sourceFiber.alternate; currentSource ? ((sourceFiber.updateQueue = currentSource.updateQueue), (sourceFiber.memoizedState = currentSource.memoizedState), - (sourceFiber.expirationTime = currentSource.expirationTime)) + (sourceFiber.lanes = currentSource.lanes)) : ((sourceFiber.updateQueue = null), (sourceFiber.memoizedState = null)); } var hasInvisibleParentBoundary = 0 !== (suspenseStackCursor.current & 1), - _workInProgress = returnFiber; + workInProgress$77 = returnFiber; do { var JSCompiler_temp; - if ((JSCompiler_temp = 13 === _workInProgress.tag)) { - var nextState = _workInProgress.memoizedState; + if ((JSCompiler_temp = 13 === workInProgress$77.tag)) { + var nextState = workInProgress$77.memoizedState; if (null !== nextState) JSCompiler_temp = null !== nextState.dehydrated ? !0 : !1; else { - var props = _workInProgress.memoizedProps; + var props = workInProgress$77.memoizedProps; JSCompiler_temp = void 0 === props.fallback ? !1 @@ -6188,23 +6470,24 @@ function handleError(root$jscomp$0, thrownValue) { } } if (JSCompiler_temp) { - var thenables = _workInProgress.updateQueue; - if (null === thenables) { + var wakeables = workInProgress$77.updateQueue; + if (null === wakeables) { var updateQueue = new Set(); - updateQueue.add(thenable); - _workInProgress.updateQueue = updateQueue; - } else thenables.add(thenable); - if (0 === (_workInProgress.mode & 2)) { - _workInProgress.effectTag |= 64; - sourceFiber.effectTag &= -2981; + updateQueue.add(wakeable); + workInProgress$77.updateQueue = updateQueue; + } else wakeables.add(wakeable); + if (0 === (workInProgress$77.mode & 2)) { + workInProgress$77.flags |= 64; + sourceFiber.flags |= 32768; + sourceFiber.flags &= -5029; if (1 === sourceFiber.tag) if (null === sourceFiber.alternate) sourceFiber.tag = 17; else { - var update = createUpdate(1073741823, null); + var update = createUpdate(-1, 1); update.tag = 2; enqueueUpdate(sourceFiber, update); } - sourceFiber.expirationTime = 1073741823; + sourceFiber.lanes |= 1; break a; } value = void 0; @@ -6213,86 +6496,90 @@ function handleError(root$jscomp$0, thrownValue) { null === pingCache ? ((pingCache = root.pingCache = new PossiblyWeakMap()), (value = new Set()), - pingCache.set(thenable, value)) - : ((value = pingCache.get(thenable)), + pingCache.set(wakeable, value)) + : ((value = pingCache.get(wakeable)), void 0 === value && - ((value = new Set()), pingCache.set(thenable, value))); + ((value = new Set()), pingCache.set(wakeable, value))); if (!value.has(sourceFiber)) { value.add(sourceFiber); var ping = pingSuspendedRoot.bind( null, root, - thenable, + wakeable, sourceFiber ); - thenable.then(ping, ping); + wakeable.then(ping, ping); } - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; + workInProgress$77.flags |= 8192; + workInProgress$77.lanes = thrownValue; break a; } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$77 = workInProgress$77.return; + } while (null !== workInProgress$77); value = Error( (getComponentName(sourceFiber.type) || "A React component") + - " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." + - getStackByFiberInDevAndProd(sourceFiber) + " suspended while rendering, but no fallback UI was specified.\n\nAdd a component higher in the tree to provide a loading indicator or placeholder to display." ); } - workInProgressRootExitStatus !== RootCompleted && - (workInProgressRootExitStatus = RootErrored); + 5 !== workInProgressRootExitStatus && + (workInProgressRootExitStatus = 2); value = createCapturedValue(value, sourceFiber); - _workInProgress = returnFiber; + workInProgress$77 = returnFiber; do { - switch (_workInProgress.tag) { + switch (workInProgress$77.tag) { case 3: - thenable = value; - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update = createRootErrorUpdate( - _workInProgress, - thenable, + root = value; + workInProgress$77.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$77.lanes |= thrownValue; + var update$78 = createRootErrorUpdate( + workInProgress$77, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update); + enqueueCapturedUpdate(workInProgress$77, update$78); break a; case 1: - thenable = value; - var ctor = _workInProgress.type, - instance = _workInProgress.stateNode; + root = value; + var ctor = workInProgress$77.type, + instance = workInProgress$77.stateNode; if ( - 0 === (_workInProgress.effectTag & 64) && + 0 === (workInProgress$77.flags & 64) && ("function" === typeof ctor.getDerivedStateFromError || (null !== instance && "function" === typeof instance.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) ) { - _workInProgress.effectTag |= 4096; - _workInProgress.expirationTime = thrownValue; - var _update2 = createClassErrorUpdate( - _workInProgress, - thenable, + workInProgress$77.flags |= 8192; + thrownValue &= -thrownValue; + workInProgress$77.lanes |= thrownValue; + var update$81 = createClassErrorUpdate( + workInProgress$77, + root, thrownValue ); - enqueueCapturedUpdate(_workInProgress, _update2); + enqueueCapturedUpdate(workInProgress$77, update$81); break a; } } - _workInProgress = _workInProgress.return; - } while (null !== _workInProgress); + workInProgress$77 = workInProgress$77.return; + } while (null !== workInProgress$77); } - workInProgress = completeUnitOfWork(workInProgress); + completeUnitOfWork(erroredWork); } catch (yetAnotherThrownValue) { thrownValue = yetAnotherThrownValue; + workInProgress === erroredWork && + null !== erroredWork && + (workInProgress = erroredWork = erroredWork.return); continue; } break; } while (1); } function pushDispatcher() { - var prevDispatcher = ReactCurrentDispatcher$1.current; - ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; + var prevDispatcher = ReactCurrentDispatcher$2.current; + ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher; } function pushInteractions(root) { @@ -6300,28 +6587,13 @@ function pushInteractions(root) { tracing.__interactionsRef.current = root.memoizedInteractions; return prevInteractions; } -function markRenderEventTimeAndConfig(expirationTime, suspenseConfig) { - expirationTime < workInProgressRootLatestProcessedExpirationTime && - 2 < expirationTime && - (workInProgressRootLatestProcessedExpirationTime = expirationTime); - null !== suspenseConfig && - expirationTime < workInProgressRootLatestSuspenseTimeout && - 2 < expirationTime && - ((workInProgressRootLatestSuspenseTimeout = expirationTime), - (workInProgressRootCanSuspendUsingConfig = suspenseConfig)); -} -function markUnprocessedUpdateTime(expirationTime) { - expirationTime > workInProgressRootNextUnprocessedUpdateTime && - (workInProgressRootNextUnprocessedUpdateTime = expirationTime); -} -function renderRootSync(root, expirationTime) { +function renderRootSync(root, lanes) { var prevExecutionContext = executionContext; - executionContext |= RenderContext; + executionContext |= 16; var prevDispatcher = pushDispatcher(); - if (root !== workInProgressRoot || expirationTime !== renderExpirationTime$1) - prepareFreshStack(root, expirationTime), - startWorkOnPendingInteractions(root, expirationTime); - expirationTime = pushInteractions(root); + if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) + prepareFreshStack(root, lanes), startWorkOnPendingInteractions(root, lanes); + lanes = pushInteractions(root); do try { workLoopSync(); @@ -6331,187 +6603,197 @@ function renderRootSync(root, expirationTime) { } while (1); resetContextDependencies(); - tracing.__interactionsRef.current = expirationTime; + tracing.__interactionsRef.current = lanes; executionContext = prevExecutionContext; - ReactCurrentDispatcher$1.current = prevDispatcher; + ReactCurrentDispatcher$2.current = prevDispatcher; if (null !== workInProgress) throw Error( "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." ); workInProgressRoot = null; + workInProgressRootRenderLanes = 0; return workInProgressRootExitStatus; } function workLoopSync() { - for (; null !== workInProgress; ) - workInProgress = performUnitOfWork(workInProgress); + for (; null !== workInProgress; ) performUnitOfWork(workInProgress); } function workLoopConcurrent() { for (; null !== workInProgress && !Scheduler_shouldYield(); ) - workInProgress = performUnitOfWork(workInProgress); + performUnitOfWork(workInProgress); } function performUnitOfWork(unitOfWork) { var current = unitOfWork.alternate; 0 !== (unitOfWork.mode & 8) ? ((profilerStartTime = now$1()), 0 > unitOfWork.actualStartTime && (unitOfWork.actualStartTime = now$1()), - (current = beginWork$1(current, unitOfWork, renderExpirationTime$1)), + (current = beginWork$1(current, unitOfWork, subtreeRenderLanes)), stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, !0)) - : (current = beginWork$1(current, unitOfWork, renderExpirationTime$1)); + : (current = beginWork$1(current, unitOfWork, subtreeRenderLanes)); unitOfWork.memoizedProps = unitOfWork.pendingProps; - null === current && (current = completeUnitOfWork(unitOfWork)); + null === current + ? completeUnitOfWork(unitOfWork) + : (workInProgress = current); ReactCurrentOwner$2.current = null; - return current; } function completeUnitOfWork(unitOfWork) { - workInProgress = unitOfWork; + var completedWork = unitOfWork; do { - var current = workInProgress.alternate; - unitOfWork = workInProgress.return; - if (0 === (workInProgress.effectTag & 2048)) { - if (0 === (workInProgress.mode & 8)) - current = completeWork(current, workInProgress, renderExpirationTime$1); + var current = completedWork.alternate; + unitOfWork = completedWork.return; + if (0 === (completedWork.flags & 4096)) { + if (0 === (completedWork.mode & 8)) + current = completeWork(current, completedWork, subtreeRenderLanes); else { - var fiber = workInProgress; + var fiber = completedWork; profilerStartTime = now$1(); 0 > fiber.actualStartTime && (fiber.actualStartTime = now$1()); - current = completeWork(current, workInProgress, renderExpirationTime$1); - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !1); + current = completeWork(current, completedWork, subtreeRenderLanes); + stopProfilerTimerIfRunningAndRecordDelta(completedWork, !1); } - fiber = workInProgress; - if (1 === renderExpirationTime$1 || 1 !== fiber.childExpirationTime) { - var newChildExpirationTime = 0; - if (0 !== (fiber.mode & 8)) { + if (null !== current) { + workInProgress = current; + return; + } + current = completedWork; + if ( + (23 !== current.tag && 22 !== current.tag) || + null === current.memoizedState || + 0 !== (subtreeRenderLanes & 1073741824) || + 0 === (current.mode & 4) + ) { + fiber = 0; + if (0 !== (current.mode & 8)) { for ( - var actualDuration = fiber.actualDuration, - treeBaseDuration = fiber.selfBaseDuration, + var actualDuration = current.actualDuration, + treeBaseDuration = current.selfBaseDuration, shouldBubbleActualDurations = - null === fiber.alternate || - fiber.child !== fiber.alternate.child, - child = fiber.child; + null === current.alternate || + current.child !== current.alternate.child, + child = current.child; null !== child; - ) { - var childUpdateExpirationTime = child.expirationTime, - childChildExpirationTime = child.childExpirationTime; - childUpdateExpirationTime > newChildExpirationTime && - (newChildExpirationTime = childUpdateExpirationTime); - childChildExpirationTime > newChildExpirationTime && - (newChildExpirationTime = childChildExpirationTime); - shouldBubbleActualDurations && - (actualDuration += child.actualDuration); - treeBaseDuration += child.treeBaseDuration; - child = child.sibling; - } - fiber.actualDuration = actualDuration; - fiber.treeBaseDuration = treeBaseDuration; + ) + (fiber |= child.lanes | child.childLanes), + shouldBubbleActualDurations && + (actualDuration += child.actualDuration), + (treeBaseDuration += child.treeBaseDuration), + (child = child.sibling); + 13 === current.tag && + null !== current.memoizedState && + ((shouldBubbleActualDurations = current.child), + null !== shouldBubbleActualDurations && + (treeBaseDuration -= + shouldBubbleActualDurations.treeBaseDuration)); + current.actualDuration = actualDuration; + current.treeBaseDuration = treeBaseDuration; } else - for (actualDuration = fiber.child; null !== actualDuration; ) - (treeBaseDuration = actualDuration.expirationTime), - (shouldBubbleActualDurations = - actualDuration.childExpirationTime), - treeBaseDuration > newChildExpirationTime && - (newChildExpirationTime = treeBaseDuration), - shouldBubbleActualDurations > newChildExpirationTime && - (newChildExpirationTime = shouldBubbleActualDurations), + for (actualDuration = current.child; null !== actualDuration; ) + (fiber |= actualDuration.lanes | actualDuration.childLanes), (actualDuration = actualDuration.sibling); - fiber.childExpirationTime = newChildExpirationTime; + current.childLanes = fiber; } - if (null !== current) return current; null !== unitOfWork && - 0 === (unitOfWork.effectTag & 2048) && + 0 === (unitOfWork.flags & 4096) && (null === unitOfWork.firstEffect && - (unitOfWork.firstEffect = workInProgress.firstEffect), - null !== workInProgress.lastEffect && + (unitOfWork.firstEffect = completedWork.firstEffect), + null !== completedWork.lastEffect && (null !== unitOfWork.lastEffect && - (unitOfWork.lastEffect.nextEffect = workInProgress.firstEffect), - (unitOfWork.lastEffect = workInProgress.lastEffect)), - 1 < workInProgress.effectTag && + (unitOfWork.lastEffect.nextEffect = completedWork.firstEffect), + (unitOfWork.lastEffect = completedWork.lastEffect)), + 1 < completedWork.flags && (null !== unitOfWork.lastEffect - ? (unitOfWork.lastEffect.nextEffect = workInProgress) - : (unitOfWork.firstEffect = workInProgress), - (unitOfWork.lastEffect = workInProgress))); + ? (unitOfWork.lastEffect.nextEffect = completedWork) + : (unitOfWork.firstEffect = completedWork), + (unitOfWork.lastEffect = completedWork))); } else { - current = unwindWork(workInProgress); - if (0 !== (workInProgress.mode & 8)) { - stopProfilerTimerIfRunningAndRecordDelta(workInProgress, !1); - fiber = workInProgress.actualDuration; - for ( - newChildExpirationTime = workInProgress.child; - null !== newChildExpirationTime; - - ) - (fiber += newChildExpirationTime.actualDuration), - (newChildExpirationTime = newChildExpirationTime.sibling); - workInProgress.actualDuration = fiber; + current = unwindWork(completedWork); + if (null !== current) { + current.flags &= 4095; + workInProgress = current; + return; + } + if (0 !== (completedWork.mode & 8)) { + stopProfilerTimerIfRunningAndRecordDelta(completedWork, !1); + current = completedWork.actualDuration; + for (fiber = completedWork.child; null !== fiber; ) + (current += fiber.actualDuration), (fiber = fiber.sibling); + completedWork.actualDuration = current; } - if (null !== current) return (current.effectTag &= 2047), current; null !== unitOfWork && ((unitOfWork.firstEffect = unitOfWork.lastEffect = null), - (unitOfWork.effectTag |= 2048)); + (unitOfWork.flags |= 4096)); } - current = workInProgress.sibling; - if (null !== current) return current; - workInProgress = unitOfWork; - } while (null !== workInProgress); - workInProgressRootExitStatus === RootIncomplete && - (workInProgressRootExitStatus = RootCompleted); - return null; -} -function getRemainingExpirationTime(fiber) { - var updateExpirationTime = fiber.expirationTime; - fiber = fiber.childExpirationTime; - return updateExpirationTime > fiber ? updateExpirationTime : fiber; + completedWork = completedWork.sibling; + if (null !== completedWork) { + workInProgress = completedWork; + return; + } + workInProgress = completedWork = unitOfWork; + } while (null !== completedWork); + 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } function commitRoot(root) { var renderPriorityLevel = getCurrentPriorityLevel(); runWithPriority(99, commitRootImpl.bind(null, root, renderPriorityLevel)); return null; } -function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { +function commitRootImpl(root, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + if (0 !== (executionContext & 48)) throw Error("Should not already be working."); - var finishedWork = root$jscomp$0.finishedWork, - expirationTime = root$jscomp$0.finishedExpirationTime; + var finishedWork = root.finishedWork, + lanes = root.finishedLanes; if (null === finishedWork) return null; - root$jscomp$0.finishedWork = null; - root$jscomp$0.finishedExpirationTime = 0; - if (finishedWork === root$jscomp$0.current) + root.finishedWork = null; + root.finishedLanes = 0; + if (finishedWork === root.current) throw Error( "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue." ); - root$jscomp$0.callbackNode = null; - root$jscomp$0.callbackExpirationTime = 0; - root$jscomp$0.callbackPriority = 90; - root$jscomp$0.nextKnownPendingLevel = 0; - var remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( - finishedWork - ); - root$jscomp$0.firstPendingTime = remainingExpirationTimeBeforeCommit; - expirationTime <= root$jscomp$0.lastSuspendedTime - ? (root$jscomp$0.firstSuspendedTime = root$jscomp$0.lastSuspendedTime = root$jscomp$0.nextKnownPendingLevel = 0) - : expirationTime <= root$jscomp$0.firstSuspendedTime && - (root$jscomp$0.firstSuspendedTime = expirationTime - 1); - expirationTime <= root$jscomp$0.lastPingedTime && - (root$jscomp$0.lastPingedTime = 0); - expirationTime <= root$jscomp$0.lastExpiredTime && - (root$jscomp$0.lastExpiredTime = 0); - root$jscomp$0 === workInProgressRoot && + root.callbackNode = null; + var remainingLanes = finishedWork.lanes | finishedWork.childLanes, + remainingLanes$jscomp$0 = remainingLanes, + noLongerPendingLanes = root.pendingLanes & ~remainingLanes$jscomp$0; + root.pendingLanes = remainingLanes$jscomp$0; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.expiredLanes &= remainingLanes$jscomp$0; + root.mutableReadLanes &= remainingLanes$jscomp$0; + root.entangledLanes &= remainingLanes$jscomp$0; + remainingLanes$jscomp$0 = root.entanglements; + for ( + var eventTimes = root.eventTimes, expirationTimes = root.expirationTimes; + 0 < noLongerPendingLanes; + + ) { + var index$12 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$12; + remainingLanes$jscomp$0[index$12] = 0; + eventTimes[index$12] = -1; + expirationTimes[index$12] = -1; + noLongerPendingLanes &= ~lane; + } + null !== rootsWithPendingDiscreteUpdates && + 0 === (remainingLanes & 24) && + rootsWithPendingDiscreteUpdates.has(root) && + rootsWithPendingDiscreteUpdates.delete(root); + root === workInProgressRoot && ((workInProgress = workInProgressRoot = null), - (renderExpirationTime$1 = 0)); - 1 < finishedWork.effectTag + (workInProgressRootRenderLanes = 0)); + 1 < finishedWork.flags ? null !== finishedWork.lastEffect ? ((finishedWork.lastEffect.nextEffect = finishedWork), - (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect)) - : (remainingExpirationTimeBeforeCommit = finishedWork) - : (remainingExpirationTimeBeforeCommit = finishedWork.firstEffect); - if (null !== remainingExpirationTimeBeforeCommit) { - var prevExecutionContext = executionContext; - executionContext |= CommitContext; - var prevInteractions = pushInteractions(root$jscomp$0); - ReactCurrentOwner$2.current = null; - nextEffect = remainingExpirationTimeBeforeCommit; + (remainingLanes = finishedWork.firstEffect)) + : (remainingLanes = finishedWork) + : (remainingLanes = finishedWork.firstEffect); + if (null !== remainingLanes) { + remainingLanes$jscomp$0 = executionContext; + executionContext |= 32; + eventTimes = pushInteractions(root); + focusedInstanceHandle = ReactCurrentOwner$2.current = null; + shouldFireAfterActiveInstanceBlur = !1; + nextEffect = remainingLanes; do try { commitBeforeMutationEffects(); @@ -6521,18 +6803,14 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); + focusedInstanceHandle = null; commitTime = now$1(); - nextEffect = remainingExpirationTimeBeforeCommit; + nextEffect = remainingLanes; do try { - for ( - var root = root$jscomp$0, - renderPriorityLevel = renderPriorityLevel$jscomp$0; - null !== nextEffect; - - ) { - var effectTag = nextEffect.effectTag; - if (effectTag & 128) { + for (expirationTimes = root; null !== nextEffect; ) { + var flags = nextEffect.flags; + if (flags & 128) { var current = nextEffect.alternate; if (null !== current) { var currentRef = current.ref; @@ -6542,52 +6820,50 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { : (currentRef.current = null)); } } - switch (effectTag & 1038) { + switch (flags & 1038) { case 2: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; break; case 6: commitPlacement(nextEffect); - nextEffect.effectTag &= -3; + nextEffect.flags &= -3; commitWork(nextEffect.alternate, nextEffect); break; case 1024: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; break; case 1028: - nextEffect.effectTag &= -1025; + nextEffect.flags &= -1025; commitWork(nextEffect.alternate, nextEffect); break; case 4: commitWork(nextEffect.alternate, nextEffect); break; case 8: - var current$jscomp$0 = nextEffect; - unmountHostComponents( - root, - current$jscomp$0, - renderPriorityLevel - ); - detachFiber(current$jscomp$0); + noLongerPendingLanes = nextEffect; + unmountHostComponents(expirationTimes, noLongerPendingLanes); + var alternate = noLongerPendingLanes.alternate; + detachFiberMutation(noLongerPendingLanes); + null !== alternate && detachFiberMutation(alternate); } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$91) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$91); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); - root$jscomp$0.current = finishedWork; - nextEffect = remainingExpirationTimeBeforeCommit; + root.current = finishedWork; + nextEffect = remainingLanes; do try { - for (effectTag = root$jscomp$0; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(effectTag, nextEffect.alternate, nextEffect); - if (effectTag$jscomp$0 & 128) { + for (flags = root; null !== nextEffect; ) { + var flags$jscomp$0 = nextEffect.flags; + flags$jscomp$0 & 36 && + commitLifeCycles(flags, nextEffect.alternate, nextEffect); + if (flags$jscomp$0 & 128) { current = void 0; var ref = nextEffect.ref; if (null !== ref) { @@ -6606,73 +6882,85 @@ function commitRootImpl(root$jscomp$0, renderPriorityLevel$jscomp$0) { } nextEffect = nextEffect.nextEffect; } - } catch (error) { + } catch (error$92) { if (null === nextEffect) throw Error("Should be working on an effect."); - captureCommitPhaseError(nextEffect, error); + captureCommitPhaseError(nextEffect, error$92); nextEffect = nextEffect.nextEffect; } while (null !== nextEffect); nextEffect = null; requestPaint(); - tracing.__interactionsRef.current = prevInteractions; - executionContext = prevExecutionContext; - } else (root$jscomp$0.current = finishedWork), (commitTime = now$1()); - if ((effectTag$jscomp$0 = rootDoesHavePassiveEffects)) + tracing.__interactionsRef.current = eventTimes; + executionContext = remainingLanes$jscomp$0; + } else (root.current = finishedWork), (commitTime = now$1()); + if ((flags$jscomp$0 = rootDoesHavePassiveEffects)) (rootDoesHavePassiveEffects = !1), - (rootWithPendingPassiveEffects = root$jscomp$0), - (pendingPassiveEffectsExpirationTime = expirationTime), - (pendingPassiveEffectsRenderPriority = renderPriorityLevel$jscomp$0); + (rootWithPendingPassiveEffects = root), + (pendingPassiveEffectsLanes = lanes), + (pendingPassiveEffectsRenderPriority = renderPriorityLevel); else - for ( - nextEffect = remainingExpirationTimeBeforeCommit; - null !== nextEffect; - - ) - (renderPriorityLevel$jscomp$0 = nextEffect.nextEffect), + for (nextEffect = remainingLanes; null !== nextEffect; ) + (ref = nextEffect.nextEffect), (nextEffect.nextEffect = null), - (nextEffect = renderPriorityLevel$jscomp$0); - renderPriorityLevel$jscomp$0 = root$jscomp$0.firstPendingTime; - if (0 !== renderPriorityLevel$jscomp$0) { + nextEffect.flags & 8 && + ((instance = nextEffect), + (instance.sibling = null), + (instance.stateNode = null)), + (nextEffect = ref); + remainingLanes = root.pendingLanes; + if (0 !== remainingLanes) { if (null !== spawnedWorkDuringRender) for ( - remainingExpirationTimeBeforeCommit = spawnedWorkDuringRender, + ref = spawnedWorkDuringRender, spawnedWorkDuringRender = null, - ref = 0; - ref < remainingExpirationTimeBeforeCommit.length; - ref++ + instance = 0; + instance < ref.length; + instance++ ) - scheduleInteractions( - root$jscomp$0, - remainingExpirationTimeBeforeCommit[ref], - root$jscomp$0.memoizedInteractions - ); - schedulePendingInteractions(root$jscomp$0, renderPriorityLevel$jscomp$0); + scheduleInteractions(root, ref[instance], root.memoizedInteractions); + schedulePendingInteractions(root, remainingLanes); } else legacyErrorBoundariesThatAlreadyFailed = null; - effectTag$jscomp$0 || - finishPendingInteractions(root$jscomp$0, expirationTime); - 1073741823 === renderPriorityLevel$jscomp$0 - ? root$jscomp$0 === rootWithNestedUpdates + flags$jscomp$0 || finishPendingInteractions(root, lanes); + 1 === remainingLanes + ? root === rootWithNestedUpdates ? nestedUpdateCount++ - : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root$jscomp$0)) + : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root)) : (nestedUpdateCount = 0); - "function" === typeof onCommitFiberRoot && - onCommitFiberRoot(finishedWork.stateNode, expirationTime); - ensureRootIsScheduled(root$jscomp$0); + finishedWork = finishedWork.stateNode; + if (injectedHook && "function" === typeof injectedHook.onCommitFiberRoot) + try { + injectedHook.onCommitFiberRoot( + rendererID, + finishedWork, + renderPriorityLevel, + 64 === (finishedWork.current.flags & 64) + ); + } catch (err) {} + ensureRootIsScheduled(root, now()); if (hasUncaughtError) throw ((hasUncaughtError = !1), - (root$jscomp$0 = firstUncaughtError), + (root = firstUncaughtError), (firstUncaughtError = null), - root$jscomp$0); - if ((executionContext & LegacyUnbatchedContext) !== NoContext) return null; + root); + if (0 !== (executionContext & 8)) return null; flushSyncCallbackQueue(); return null; } function commitBeforeMutationEffects() { for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - 0 !== (effectTag & 256) && - commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect); - 0 === (effectTag & 512) || + var current = nextEffect.alternate; + shouldFireAfterActiveInstanceBlur || + null === focusedInstanceHandle || + (0 !== (nextEffect.flags & 8) + ? doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0) + : 13 === nextEffect.tag && + isSuspenseBoundaryBeingHidden(current, nextEffect) && + doesFiberContain(nextEffect, focusedInstanceHandle) && + (shouldFireAfterActiveInstanceBlur = !0)); + var flags = nextEffect.flags; + 0 !== (flags & 256) && commitBeforeMutationLifeCycles(current, nextEffect); + 0 === (flags & 512) || rootDoesHavePassiveEffects || ((rootDoesHavePassiveEffects = !0), scheduleCallback(97, function() { @@ -6691,56 +6979,87 @@ function flushPassiveEffects() { pendingPassiveEffectsRenderPriority = 90; return runWithPriority(priorityLevel, flushPassiveEffectsImpl); } + return !1; +} +function enqueuePendingPassiveHookEffectMount(fiber, effect) { + pendingPassiveHookEffectsMount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); +} +function enqueuePendingPassiveHookEffectUnmount(fiber, effect) { + pendingPassiveHookEffectsUnmount.push(effect, fiber); + rootDoesHavePassiveEffects || + ((rootDoesHavePassiveEffects = !0), + scheduleCallback(97, function() { + flushPassiveEffects(); + return null; + })); } function flushPassiveEffectsImpl() { if (null === rootWithPendingPassiveEffects) return !1; var root = rootWithPendingPassiveEffects, - expirationTime = pendingPassiveEffectsExpirationTime; + lanes = pendingPassiveEffectsLanes; rootWithPendingPassiveEffects = null; - pendingPassiveEffectsExpirationTime = 0; - if ((executionContext & (RenderContext | CommitContext)) !== NoContext) + pendingPassiveEffectsLanes = 0; + if (0 !== (executionContext & 48)) throw Error("Cannot flush passive effects while already rendering."); var prevExecutionContext = executionContext; - executionContext |= CommitContext; - for ( - var prevInteractions = pushInteractions(root), - _effect2 = root.current.firstEffect; - null !== _effect2; - - ) { + executionContext |= 32; + var prevInteractions = pushInteractions(root), + unmountEffects = pendingPassiveHookEffectsUnmount; + pendingPassiveHookEffectsUnmount = []; + for (var i = 0; i < unmountEffects.length; i += 2) { + var effect$97 = unmountEffects[i], + fiber = unmountEffects[i + 1], + destroy = effect$97.destroy; + effect$97.destroy = void 0; + if ("function" === typeof destroy) + try { + destroy(); + } catch (error) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error); + } + } + unmountEffects = pendingPassiveHookEffectsMount; + pendingPassiveHookEffectsMount = []; + for (i = 0; i < unmountEffects.length; i += 2) { + effect$97 = unmountEffects[i]; + fiber = unmountEffects[i + 1]; try { - var finishedWork = _effect2; - if (0 !== (finishedWork.effectTag & 512)) - switch (finishedWork.tag) { - case 0: - case 11: - case 15: - case 22: - commitHookEffectListUnmount(5, finishedWork), - commitHookEffectListMount(5, finishedWork); - } - } catch (error) { - if (null === _effect2) throw Error("Should be working on an effect."); - captureCommitPhaseError(_effect2, error); + var create$101 = effect$97.create; + effect$97.destroy = create$101(); + } catch (error$102) { + if (null === fiber) throw Error("Should be working on an effect."); + captureCommitPhaseError(fiber, error$102); } - finishedWork = _effect2.nextEffect; - _effect2.nextEffect = null; - _effect2 = finishedWork; } + for (unmountEffects = root.current.firstEffect; null !== unmountEffects; ) + (create$101 = unmountEffects.nextEffect), + (unmountEffects.nextEffect = null), + unmountEffects.flags & 8 && + ((unmountEffects.sibling = null), (unmountEffects.stateNode = null)), + (unmountEffects = create$101); tracing.__interactionsRef.current = prevInteractions; - finishPendingInteractions(root, expirationTime); + finishPendingInteractions(root, lanes); executionContext = prevExecutionContext; flushSyncCallbackQueue(); return !0; } function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1073741823); + sourceFiber = createRootErrorUpdate(rootFiber, sourceFiber, 1); enqueueUpdate(rootFiber, sourceFiber); - rootFiber = markUpdateTimeFromFiberToRoot(rootFiber, 1073741823); + sourceFiber = requestEventTime(); + rootFiber = markUpdateLaneFromFiberToRoot(rootFiber, 1); null !== rootFiber && - (ensureRootIsScheduled(rootFiber), - schedulePendingInteractions(rootFiber, 1073741823)); + (markRootUpdated(rootFiber, 1, sourceFiber), + ensureRootIsScheduled(rootFiber, sourceFiber), + schedulePendingInteractions(rootFiber, 1)); } function captureCommitPhaseError(sourceFiber, error) { if (3 === sourceFiber.tag) @@ -6759,158 +7078,176 @@ function captureCommitPhaseError(sourceFiber, error) { !legacyErrorBoundariesThatAlreadyFailed.has(instance))) ) { sourceFiber = createCapturedValue(error, sourceFiber); - sourceFiber = createClassErrorUpdate(fiber, sourceFiber, 1073741823); - enqueueUpdate(fiber, sourceFiber); - fiber = markUpdateTimeFromFiberToRoot(fiber, 1073741823); - null !== fiber && - (ensureRootIsScheduled(fiber), - schedulePendingInteractions(fiber, 1073741823)); + var update = createClassErrorUpdate(fiber, sourceFiber, 1); + enqueueUpdate(fiber, update); + update = requestEventTime(); + fiber = markUpdateLaneFromFiberToRoot(fiber, 1); + if (null !== fiber) + markRootUpdated(fiber, 1, update), + ensureRootIsScheduled(fiber, update), + schedulePendingInteractions(fiber, 1); + else if ( + "function" === typeof instance.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(instance)) + ) + try { + instance.componentDidCatch(error, sourceFiber); + } catch (errorToIgnore) {} break; } } fiber = fiber.return; } } -function pingSuspendedRoot(root, thenable, suspendedTime) { +function pingSuspendedRoot(root, wakeable, pingedLanes) { var pingCache = root.pingCache; - null !== pingCache && pingCache.delete(thenable); - workInProgressRoot === root && renderExpirationTime$1 === suspendedTime - ? workInProgressRootExitStatus === RootSuspendedWithDelay || - (workInProgressRootExitStatus === RootSuspended && - 1073741823 === workInProgressRootLatestProcessedExpirationTime && - now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) - ? prepareFreshStack(root, renderExpirationTime$1) - : (workInProgressRootHasPendingPing = !0) - : isRootSuspendedAtTime(root, suspendedTime) && - ((thenable = root.lastPingedTime), - (0 !== thenable && thenable < suspendedTime) || - ((root.lastPingedTime = suspendedTime), - ensureRootIsScheduled(root), - schedulePendingInteractions(root, suspendedTime))); -} -function resolveRetryThenable(boundaryFiber, thenable) { + null !== pingCache && pingCache.delete(wakeable); + wakeable = requestEventTime(); + root.pingedLanes |= root.suspendedLanes & pingedLanes; + workInProgressRoot === root && + (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && + (4 === workInProgressRootExitStatus || + (3 === workInProgressRootExitStatus && + (workInProgressRootRenderLanes & 62914560) === + workInProgressRootRenderLanes && + 500 > now() - globalMostRecentFallbackTime) + ? prepareFreshStack(root, 0) + : (workInProgressRootPingedLanes |= pingedLanes)); + ensureRootIsScheduled(root, wakeable); + schedulePendingInteractions(root, pingedLanes); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { var retryCache = boundaryFiber.stateNode; - null !== retryCache && retryCache.delete(thenable); - thenable = 0; - 0 === thenable && - ((thenable = requestCurrentTimeForUpdate()), - (thenable = computeExpirationForFiber(thenable, boundaryFiber, null))); - boundaryFiber = markUpdateTimeFromFiberToRoot(boundaryFiber, thenable); + null !== retryCache && retryCache.delete(wakeable); + wakeable = 0; + 0 === wakeable && + ((wakeable = boundaryFiber.mode), + 0 === (wakeable & 2) + ? (wakeable = 1) + : 0 === (wakeable & 4) + ? (wakeable = 99 === getCurrentPriorityLevel() ? 1 : 2) + : (0 === currentEventWipLanes && + (currentEventWipLanes = workInProgressRootIncludedLanes), + (wakeable = getHighestPriorityLane(62914560 & ~currentEventWipLanes)), + 0 === wakeable && (wakeable = 4194304))); + retryCache = requestEventTime(); + boundaryFiber = markUpdateLaneFromFiberToRoot(boundaryFiber, wakeable); null !== boundaryFiber && - (ensureRootIsScheduled(boundaryFiber), - schedulePendingInteractions(boundaryFiber, thenable)); + (markRootUpdated(boundaryFiber, wakeable, retryCache), + ensureRootIsScheduled(boundaryFiber, retryCache), + schedulePendingInteractions(boundaryFiber, wakeable)); } var beginWork$1; -beginWork$1 = function(current, workInProgress, renderExpirationTime) { - var updateExpirationTime = workInProgress.expirationTime; +beginWork$1 = function(current, workInProgress, renderLanes) { + var updateLanes = workInProgress.lanes; if (null !== current) if ( current.memoizedProps !== workInProgress.pendingProps || didPerformWorkStackCursor.current ) didReceiveUpdate = !0; + else if (0 !== (renderLanes & updateLanes)) + didReceiveUpdate = 0 !== (current.flags & 32768) ? !0 : !1; else { - if (updateExpirationTime < renderExpirationTime) { - didReceiveUpdate = !1; - switch (workInProgress.tag) { - case 3: - pushHostRootContext(workInProgress); - break; - case 5: - pushHostContext(workInProgress); - break; - case 1: - isContextProvider(workInProgress.type) && - pushContextProvider(workInProgress); - break; - case 4: - pushHostContainer( + didReceiveUpdate = !1; + switch (workInProgress.tag) { + case 3: + pushHostRootContext(workInProgress); + break; + case 5: + pushHostContext(workInProgress); + break; + case 1: + isContextProvider(workInProgress.type) && + pushContextProvider(workInProgress); + break; + case 4: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ); + break; + case 10: + updateLanes = workInProgress.memoizedProps.value; + var context = workInProgress.type._context; + push(valueCursor, context._currentValue); + context._currentValue = updateLanes; + break; + case 12: + 0 !== (renderLanes & workInProgress.childLanes) && + (workInProgress.flags |= 4); + updateLanes = workInProgress.stateNode; + updateLanes.effectDuration = 0; + updateLanes.passiveEffectDuration = 0; + break; + case 13: + if (null !== workInProgress.memoizedState) { + if (0 !== (renderLanes & workInProgress.child.childLanes)) + return updateSuspenseComponent( + current, + workInProgress, + renderLanes + ); + push(suspenseStackCursor, suspenseStackCursor.current & 1); + workInProgress = bailoutOnAlreadyFinishedWork( + current, workInProgress, - workInProgress.stateNode.containerInfo + renderLanes ); - break; - case 10: - updateExpirationTime = workInProgress.memoizedProps.value; - var context = workInProgress.type._context; - push(valueCursor, context._currentValue); - context._currentValue = updateExpirationTime; - break; - case 12: - workInProgress.childExpirationTime >= renderExpirationTime && - (workInProgress.effectTag |= 4); - updateExpirationTime = workInProgress.stateNode; - updateExpirationTime.effectDuration = 0; - updateExpirationTime.passiveEffectDuration = 0; - break; - case 13: - if (null !== workInProgress.memoizedState) { - updateExpirationTime = workInProgress.child.childExpirationTime; - if ( - 0 !== updateExpirationTime && - updateExpirationTime >= renderExpirationTime - ) - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); - push(suspenseStackCursor, suspenseStackCursor.current & 1); - workInProgress = bailoutOnAlreadyFinishedWork( + return null !== workInProgress ? workInProgress.sibling : null; + } + push(suspenseStackCursor, suspenseStackCursor.current & 1); + break; + case 19: + updateLanes = 0 !== (renderLanes & workInProgress.childLanes); + if (0 !== (current.flags & 64)) { + if (updateLanes) + return updateSuspenseListComponent( current, workInProgress, - renderExpirationTime + renderLanes ); - return null !== workInProgress ? workInProgress.sibling : null; - } - push(suspenseStackCursor, suspenseStackCursor.current & 1); - break; - case 19: - updateExpirationTime = - workInProgress.childExpirationTime >= renderExpirationTime; - if (0 !== (current.effectTag & 64)) { - if (updateExpirationTime) - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); - workInProgress.effectTag |= 64; - } - context = workInProgress.memoizedState; - null !== context && - ((context.rendering = null), (context.tail = null)); - push(suspenseStackCursor, suspenseStackCursor.current); - if (!updateExpirationTime) return null; - } - return bailoutOnAlreadyFinishedWork( - current, - workInProgress, - renderExpirationTime - ); + workInProgress.flags |= 64; + } + context = workInProgress.memoizedState; + null !== context && + ((context.rendering = null), + (context.tail = null), + (context.lastEffect = null)); + push(suspenseStackCursor, suspenseStackCursor.current); + if (updateLanes) break; + else return null; + case 22: + case 23: + return ( + (workInProgress.lanes = 0), + updateOffscreenComponent(current, workInProgress, renderLanes) + ); } - didReceiveUpdate = !1; + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); } else didReceiveUpdate = !1; - workInProgress.expirationTime = 0; + workInProgress.lanes = 0; switch (workInProgress.tag) { case 2: - updateExpirationTime = workInProgress.type; + updateLanes = workInProgress.type; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; context = getMaskedContext(workInProgress, contextStackCursor.current); - prepareToReadContext(workInProgress, renderExpirationTime); + prepareToReadContext(workInProgress, renderLanes); context = renderWithHooks( null, workInProgress, - updateExpirationTime, + updateLanes, current, context, - renderExpirationTime + renderLanes ); - workInProgress.effectTag |= 1; + workInProgress.flags |= 1; if ( "object" === typeof context && null !== context && @@ -6920,7 +7257,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress.tag = 1; workInProgress.memoizedState = null; workInProgress.updateQueue = null; - if (isContextProvider(updateExpirationTime)) { + if (isContextProvider(updateLanes)) { var hasContext = !0; pushContextProvider(workInProgress); } else hasContext = !1; @@ -6929,53 +7266,41 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ? context.state : null; initializeUpdateQueue(workInProgress); - var getDerivedStateFromProps = - updateExpirationTime.getDerivedStateFromProps; + var getDerivedStateFromProps = updateLanes.getDerivedStateFromProps; "function" === typeof getDerivedStateFromProps && applyDerivedStateFromProps( workInProgress, - updateExpirationTime, + updateLanes, getDerivedStateFromProps, current ); context.updater = classComponentUpdater; workInProgress.stateNode = context; - context._reactInternalFiber = workInProgress; - mountClassInstance( - workInProgress, - updateExpirationTime, - current, - renderExpirationTime - ); + context._reactInternals = workInProgress; + mountClassInstance(workInProgress, updateLanes, current, renderLanes); workInProgress = finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, hasContext, - renderExpirationTime + renderLanes ); } else (workInProgress.tag = 0), - reconcileChildren( - null, - workInProgress, - context, - renderExpirationTime - ), + reconcileChildren(null, workInProgress, context, renderLanes), (workInProgress = workInProgress.child); return workInProgress; case 16: + context = workInProgress.elementType; a: { - context = workInProgress.elementType; null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)); + (workInProgress.flags |= 2)); current = workInProgress.pendingProps; - initializeLazyComponentType(context); - if (1 !== context._status) throw context._result; - context = context._result; + hasContext = context._init; + context = hasContext(context._payload); workInProgress.type = context; hasContext = workInProgress.tag = resolveLazyComponentTag(context); current = resolveDefaultProps(context, current); @@ -6986,7 +7311,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 1: @@ -6995,7 +7320,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 11: @@ -7004,7 +7329,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, current, - renderExpirationTime + renderLanes ); break a; case 14: @@ -7013,8 +7338,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, resolveDefaultProps(context.type, current), - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); break a; } @@ -7027,126 +7352,106 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return workInProgress; case 0: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateFunctionComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 1: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateClassComponent( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 3: pushHostRootContext(workInProgress); - updateExpirationTime = workInProgress.updateQueue; - if (null === current || null === updateExpirationTime) + updateLanes = workInProgress.updateQueue; + if (null === current || null === updateLanes) throw Error( "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue." ); - updateExpirationTime = workInProgress.pendingProps; + updateLanes = workInProgress.pendingProps; context = workInProgress.memoizedState; context = null !== context ? context.element : null; cloneUpdateQueue(current, workInProgress); - processUpdateQueue( - workInProgress, - updateExpirationTime, - null, - renderExpirationTime - ); - updateExpirationTime = workInProgress.memoizedState.element; - updateExpirationTime === context + processUpdateQueue(workInProgress, updateLanes, null, renderLanes); + updateLanes = workInProgress.memoizedState.element; + updateLanes === context ? (workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes )) - : (reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + : (reconcileChildren(current, workInProgress, updateLanes, renderLanes), (workInProgress = workInProgress.child)); return workInProgress; case 5: return ( pushHostContext(workInProgress), - (updateExpirationTime = workInProgress.pendingProps.children), + (updateLanes = workInProgress.pendingProps.children), markRef(current, workInProgress), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), - (workInProgress = workInProgress.child), - workInProgress + reconcileChildren(current, workInProgress, updateLanes, renderLanes), + workInProgress.child ); case 6: return null; case 13: - return updateSuspenseComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseComponent(current, workInProgress, renderLanes); case 4: return ( pushHostContainer( workInProgress, workInProgress.stateNode.containerInfo ), - (updateExpirationTime = workInProgress.pendingProps), + (updateLanes = workInProgress.pendingProps), null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, null, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes )) : reconcileChildren( current, workInProgress, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ), workInProgress.child ); case 11: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), updateForwardRef( current, workInProgress, - updateExpirationTime, + updateLanes, context, - renderExpirationTime + renderLanes ) ); case 7: @@ -7155,7 +7460,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps, - renderExpirationTime + renderLanes ), workInProgress.child ); @@ -7165,27 +7470,27 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 12: return ( - (workInProgress.effectTag |= 4), - (updateExpirationTime = workInProgress.stateNode), - (updateExpirationTime.effectDuration = 0), - (updateExpirationTime.passiveEffectDuration = 0), + (workInProgress.flags |= 4), + (updateLanes = workInProgress.stateNode), + (updateLanes.effectDuration = 0), + (updateLanes.passiveEffectDuration = 0), reconcileChildren( current, workInProgress, workInProgress.pendingProps.children, - renderExpirationTime + renderLanes ), workInProgress.child ); case 10: a: { - updateExpirationTime = workInProgress.type._context; + updateLanes = workInProgress.type._context; context = workInProgress.pendingProps; getDerivedStateFromProps = workInProgress.memoizedProps; hasContext = context.value; @@ -7197,9 +7502,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ((context$jscomp$0 = getDerivedStateFromProps.value), (hasContext = objectIs(context$jscomp$0, hasContext) ? 0 - : ("function" === - typeof updateExpirationTime._calculateChangedBits - ? updateExpirationTime._calculateChangedBits( + : ("function" === typeof updateLanes._calculateChangedBits + ? updateLanes._calculateChangedBits( context$jscomp$0, hasContext ) @@ -7213,7 +7517,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress = bailoutOnAlreadyFinishedWork( current, workInProgress, - renderExpirationTime + renderLanes ); break a; } @@ -7234,25 +7538,24 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { ) { if ( - dependency.context === updateExpirationTime && + dependency.context === updateLanes && 0 !== (dependency.observedBits & hasContext) ) { 1 === context$jscomp$0.tag && - ((dependency = createUpdate(renderExpirationTime, null)), + ((dependency = createUpdate( + -1, + renderLanes & -renderLanes + )), (dependency.tag = 2), enqueueUpdate(context$jscomp$0, dependency)); - context$jscomp$0.expirationTime < renderExpirationTime && - (context$jscomp$0.expirationTime = renderExpirationTime); + context$jscomp$0.lanes |= renderLanes; dependency = context$jscomp$0.alternate; - null !== dependency && - dependency.expirationTime < renderExpirationTime && - (dependency.expirationTime = renderExpirationTime); + null !== dependency && (dependency.lanes |= renderLanes); scheduleWorkOnParentPath( context$jscomp$0.return, - renderExpirationTime + renderLanes ); - list.expirationTime < renderExpirationTime && - (list.expirationTime = renderExpirationTime); + list.lanes |= renderLanes; break; } dependency = dependency.next; @@ -7290,7 +7593,7 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { current, workInProgress, context.children, - renderExpirationTime + renderLanes ); workInProgress = workInProgress.child; } @@ -7299,17 +7602,12 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { return ( (context = workInProgress.type), (hasContext = workInProgress.pendingProps), - (updateExpirationTime = hasContext.children), - prepareToReadContext(workInProgress, renderExpirationTime), + (updateLanes = hasContext.children), + prepareToReadContext(workInProgress, renderLanes), (context = readContext(context, hasContext.unstable_observedBits)), - (updateExpirationTime = updateExpirationTime(context)), - (workInProgress.effectTag |= 1), - reconcileChildren( - current, - workInProgress, - updateExpirationTime, - renderExpirationTime - ), + (updateLanes = updateLanes(context)), + (workInProgress.flags |= 1), + reconcileChildren(current, workInProgress, updateLanes, renderLanes), workInProgress.child ); case 14: @@ -7325,8 +7623,8 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, context, hasContext, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ) ); case 15: @@ -7335,48 +7633,43 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { workInProgress, workInProgress.type, workInProgress.pendingProps, - updateExpirationTime, - renderExpirationTime + updateLanes, + renderLanes ); case 17: return ( - (updateExpirationTime = workInProgress.type), + (updateLanes = workInProgress.type), (context = workInProgress.pendingProps), (context = - workInProgress.elementType === updateExpirationTime + workInProgress.elementType === updateLanes ? context - : resolveDefaultProps(updateExpirationTime, context)), + : resolveDefaultProps(updateLanes, context)), null !== current && ((current.alternate = null), (workInProgress.alternate = null), - (workInProgress.effectTag |= 2)), + (workInProgress.flags |= 2)), (workInProgress.tag = 1), - isContextProvider(updateExpirationTime) + isContextProvider(updateLanes) ? ((current = !0), pushContextProvider(workInProgress)) : (current = !1), - prepareToReadContext(workInProgress, renderExpirationTime), - constructClassInstance(workInProgress, updateExpirationTime, context), - mountClassInstance( - workInProgress, - updateExpirationTime, - context, - renderExpirationTime - ), + prepareToReadContext(workInProgress, renderLanes), + constructClassInstance(workInProgress, updateLanes, context), + mountClassInstance(workInProgress, updateLanes, context, renderLanes), finishClassComponent( null, workInProgress, - updateExpirationTime, + updateLanes, !0, current, - renderExpirationTime + renderLanes ) ); case 19: - return updateSuspenseListComponent( - current, - workInProgress, - renderExpirationTime - ); + return updateSuspenseListComponent(current, workInProgress, renderLanes); + case 22: + return updateOffscreenComponent(current, workInProgress, renderLanes); + case 23: + return updateOffscreenComponent(current, workInProgress, renderLanes); } throw Error( "Unknown unit of work tag (" + @@ -7384,16 +7677,21 @@ beginWork$1 = function(current, workInProgress, renderExpirationTime) { "). This error is likely caused by a bug in React. Please file an issue." ); }; -function scheduleInteractions(root, expirationTime, interactions) { +function markSpawnedWork(lane) { + null === spawnedWorkDuringRender + ? (spawnedWorkDuringRender = [lane]) + : spawnedWorkDuringRender.push(lane); +} +function scheduleInteractions(root, lane, interactions) { if (0 < interactions.size) { var pendingInteractionMap = root.pendingInteractionMap, - pendingInteractions = pendingInteractionMap.get(expirationTime); + pendingInteractions = pendingInteractionMap.get(lane); null != pendingInteractions ? interactions.forEach(function(interaction) { pendingInteractions.has(interaction) || interaction.__count++; pendingInteractions.add(interaction); }) - : (pendingInteractionMap.set(expirationTime, new Set(interactions)), + : (pendingInteractionMap.set(lane, new Set(interactions)), interactions.forEach(function(interaction) { interaction.__count++; })); @@ -7401,20 +7699,20 @@ function scheduleInteractions(root, expirationTime, interactions) { if (null !== pendingInteractionMap) pendingInteractionMap.onWorkScheduled( interactions, - 1e3 * expirationTime + root.interactionThreadID + 1e3 * lane + root.interactionThreadID ); } } -function schedulePendingInteractions(root, expirationTime) { - scheduleInteractions(root, expirationTime, tracing.__interactionsRef.current); +function schedulePendingInteractions(root, lane) { + scheduleInteractions(root, lane, tracing.__interactionsRef.current); } -function startWorkOnPendingInteractions(root, expirationTime) { +function startWorkOnPendingInteractions(root, lanes) { var interactions = new Set(); root.pendingInteractionMap.forEach(function( scheduledInteractions, - scheduledExpirationTime + scheduledLane ) { - scheduledExpirationTime >= expirationTime && + 0 !== (lanes & scheduledLane) && scheduledInteractions.forEach(function(interaction) { return interactions.add(interaction); }); @@ -7423,7 +7721,7 @@ function startWorkOnPendingInteractions(root, expirationTime) { if (0 < interactions.size) { var subscriber = tracing.__subscriberRef.current; if (null !== subscriber) { - root = 1e3 * expirationTime + root.interactionThreadID; + root = 1e3 * lanes + root.interactionThreadID; try { subscriber.onWorkStarted(interactions, root); } catch (error) { @@ -7434,14 +7732,14 @@ function startWorkOnPendingInteractions(root, expirationTime) { } } } -function finishPendingInteractions(root, committedExpirationTime) { - var earliestRemainingTimeAfterCommit = root.firstPendingTime; +function finishPendingInteractions(root, committedLanes) { + var remainingLanesAfterCommit = root.pendingLanes; try { var subscriber = tracing.__subscriberRef.current; if (null !== subscriber && 0 < root.memoizedInteractions.size) subscriber.onWorkStopped( root.memoizedInteractions, - 1e3 * committedExpirationTime + root.interactionThreadID + 1e3 * committedLanes + root.interactionThreadID ); } catch (error) { scheduleCallback(99, function() { @@ -7449,54 +7747,23 @@ function finishPendingInteractions(root, committedExpirationTime) { }); } finally { var pendingInteractionMap = root.pendingInteractionMap; - pendingInteractionMap.forEach(function( - scheduledInteractions, - scheduledExpirationTime - ) { - scheduledExpirationTime > earliestRemainingTimeAfterCommit && - (pendingInteractionMap.delete(scheduledExpirationTime), + pendingInteractionMap.forEach(function(scheduledInteractions, lane) { + 0 === (remainingLanesAfterCommit & lane) && + (pendingInteractionMap.delete(lane), scheduledInteractions.forEach(function(interaction) { interaction.__count--; if (null !== subscriber && 0 === interaction.__count) try { subscriber.onInteractionScheduledWorkCompleted(interaction); - } catch (error) { + } catch (error$103) { scheduleCallback(99, function() { - throw error; + throw error$103; }); } })); }); } } -var onCommitFiberRoot = null, - onCommitFiberUnmount = null, - isDevToolsPresent = "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__; -function injectInternals(internals) { - if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled || !hook.supportsFiber) return !0; - try { - var rendererID = hook.inject(internals); - onCommitFiberRoot = function(root, expirationTime) { - try { - var didError = 64 === (root.current.effectTag & 64), - currentTime = 1073741821 - ((now() / 10) | 0), - priorityLevel = inferPriorityFromExpirationTime( - currentTime, - expirationTime - ); - hook.onCommitFiberRoot(rendererID, root, priorityLevel, didError); - } catch (err) {} - }; - onCommitFiberUnmount = function(fiber) { - try { - hook.onCommitFiberUnmount(rendererID, fiber); - } catch (err) {} - }; - } catch (err) {} - return !0; -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -7506,14 +7773,17 @@ function FiberNode(tag, pendingProps, key, mode) { this.pendingProps = pendingProps; this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; this.mode = mode; - this.effectTag = 0; + this.flags = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; - this.childExpirationTime = this.expirationTime = 0; + this.childLanes = this.lanes = 0; this.alternate = null; this.actualDuration = 0; this.actualStartTime = -1; this.treeBaseDuration = this.selfBaseDuration = 0; } +function createFiber(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); +} function shouldConstruct(Component) { Component = Component.prototype; return !(!Component || !Component.isReactComponent); @@ -7531,7 +7801,7 @@ function resolveLazyComponentTag(Component) { function createWorkInProgress(current, pendingProps) { var workInProgress = current.alternate; null === workInProgress - ? ((workInProgress = new FiberNode( + ? ((workInProgress = createFiber( current.tag, pendingProps, current.key, @@ -7543,14 +7813,15 @@ function createWorkInProgress(current, pendingProps) { (workInProgress.alternate = current), (current.alternate = workInProgress)) : ((workInProgress.pendingProps = pendingProps), - (workInProgress.effectTag = 0), + (workInProgress.type = current.type), + (workInProgress.flags = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null), (workInProgress.actualDuration = 0), (workInProgress.actualStartTime = -1)); - workInProgress.childExpirationTime = current.childExpirationTime; - workInProgress.expirationTime = current.expirationTime; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -7559,11 +7830,7 @@ function createWorkInProgress(current, pendingProps) { workInProgress.dependencies = null === pendingProps ? null - : { - expirationTime: pendingProps.expirationTime, - firstContext: pendingProps.firstContext, - responders: pendingProps.responders - }; + : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext }; workInProgress.sibling = current.sibling; workInProgress.index = current.index; workInProgress.ref = current.ref; @@ -7577,7 +7844,7 @@ function createFiberFromTypeAndProps( pendingProps, owner, mode, - expirationTime + lanes ) { var fiberTag = 2; owner = type; @@ -7586,15 +7853,10 @@ function createFiberFromTypeAndProps( else a: switch (type) { case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_CONCURRENT_MODE_TYPE: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); + case REACT_DEBUG_TRACING_MODE_TYPE: fiberTag = 8; - mode |= 7; + mode |= 16; break; case REACT_STRICT_MODE_TYPE: fiberTag = 8; @@ -7602,26 +7864,35 @@ function createFiberFromTypeAndProps( break; case REACT_PROFILER_TYPE: return ( - (type = new FiberNode(12, pendingProps, key, mode | 8)), + (type = createFiber(12, pendingProps, key, mode | 8)), (type.elementType = REACT_PROFILER_TYPE), (type.type = REACT_PROFILER_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), (type.stateNode = { effectDuration: 0, passiveEffectDuration: 0 }), type ); case REACT_SUSPENSE_TYPE: return ( - (type = new FiberNode(13, pendingProps, key, mode)), + (type = createFiber(13, pendingProps, key, mode)), (type.type = REACT_SUSPENSE_TYPE), (type.elementType = REACT_SUSPENSE_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), type ); case REACT_SUSPENSE_LIST_TYPE: return ( - (type = new FiberNode(19, pendingProps, key, mode)), + (type = createFiber(19, pendingProps, key, mode)), (type.elementType = REACT_SUSPENSE_LIST_TYPE), - (type.expirationTime = expirationTime), + (type.lanes = lanes), + type + ); + case REACT_OFFSCREEN_TYPE: + return createFiberFromOffscreen(pendingProps, mode, lanes, key); + case REACT_LEGACY_HIDDEN_TYPE: + return ( + (type = createFiber(23, pendingProps, key, mode)), + (type.elementType = REACT_LEGACY_HIDDEN_TYPE), + (type.lanes = lanes), type ); default: @@ -7643,9 +7914,6 @@ function createFiberFromTypeAndProps( fiberTag = 16; owner = null; break a; - case REACT_BLOCK_TYPE: - fiberTag = 22; - break a; } throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + @@ -7653,30 +7921,36 @@ function createFiberFromTypeAndProps( "." ); } - key = new FiberNode(fiberTag, pendingProps, key, mode); + key = createFiber(fiberTag, pendingProps, key, mode); key.elementType = type; key.type = owner; - key.expirationTime = expirationTime; + key.lanes = lanes; return key; } -function createFiberFromFragment(elements, mode, expirationTime, key) { - elements = new FiberNode(7, elements, key, mode); - elements.expirationTime = expirationTime; +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiber(7, elements, key, mode); + elements.lanes = lanes; return elements; } -function createFiberFromText(content, mode, expirationTime) { - content = new FiberNode(6, content, null, mode); - content.expirationTime = expirationTime; +function createFiberFromOffscreen(pendingProps, mode, lanes, key) { + pendingProps = createFiber(22, pendingProps, key, mode); + pendingProps.elementType = REACT_OFFSCREEN_TYPE; + pendingProps.lanes = lanes; + return pendingProps; +} +function createFiberFromText(content, mode, lanes) { + content = createFiber(6, content, null, mode); + content.lanes = lanes; return content; } -function createFiberFromPortal(portal, mode, expirationTime) { - mode = new FiberNode( +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiber( 4, null !== portal.children ? portal.children : [], portal.key, mode ); - mode.expirationTime = expirationTime; + mode.lanes = lanes; mode.stateNode = { containerInfo: portal.containerInfo, pendingChildren: null, @@ -7686,54 +7960,34 @@ function createFiberFromPortal(portal, mode, expirationTime) { } function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; - this.current = null; this.containerInfo = containerInfo; - this.pingCache = this.pendingChildren = null; - this.finishedExpirationTime = 0; - this.finishedWork = null; + this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; this.timeoutHandle = -1; this.pendingContext = this.context = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = 90; - this.lastExpiredTime = this.lastPingedTime = this.nextKnownPendingLevel = this.lastSuspendedTime = this.firstSuspendedTime = this.firstPendingTime = 0; + this.callbackPriority = 0; + this.eventTimes = createLaneMap(0); + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; + this.entanglements = createLaneMap(0); this.interactionThreadID = tracing.unstable_getThreadID(); this.memoizedInteractions = new Set(); this.pendingInteractionMap = new Map(); } -function isRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime; - root = root.lastSuspendedTime; - return ( - 0 !== firstSuspendedTime && - firstSuspendedTime >= expirationTime && - root <= expirationTime - ); -} -function markRootSuspendedAtTime(root, expirationTime) { - var firstSuspendedTime = root.firstSuspendedTime, - lastSuspendedTime = root.lastSuspendedTime; - firstSuspendedTime < expirationTime && - (root.firstSuspendedTime = expirationTime); - if (lastSuspendedTime > expirationTime || 0 === firstSuspendedTime) - root.lastSuspendedTime = expirationTime; - expirationTime <= root.lastPingedTime && (root.lastPingedTime = 0); - expirationTime <= root.lastExpiredTime && (root.lastExpiredTime = 0); -} -function markRootUpdatedAtTime(root, expirationTime) { - expirationTime > root.firstPendingTime && - (root.firstPendingTime = expirationTime); - var firstSuspendedTime = root.firstSuspendedTime; - 0 !== firstSuspendedTime && - (expirationTime >= firstSuspendedTime - ? (root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = 0) - : expirationTime >= root.lastSuspendedTime && - (root.lastSuspendedTime = expirationTime + 1), - expirationTime > root.nextKnownPendingLevel && - (root.nextKnownPendingLevel = expirationTime)); +function createPortal(children, containerInfo, implementation) { + var key = + 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE, + key: null == key ? null : "" + key, + children: children, + containerInfo: containerInfo, + implementation: implementation + }; } function findHostInstance(component) { - var fiber = component._reactInternalFiber; + var fiber = component._reactInternals; if (void 0 === fiber) { if ("function" === typeof component.render) throw Error("Unable to find node on an unmounted component."); @@ -7747,11 +8001,10 @@ function findHostInstance(component) { } function updateContainer(element, container, parentComponent, callback) { var current = container.current, - currentTime = requestCurrentTimeForUpdate(), - suspenseConfig = ReactCurrentBatchConfig.suspense; - currentTime = computeExpirationForFiber(currentTime, current, suspenseConfig); + eventTime = requestEventTime(), + lane = requestUpdateLane(current); a: if (parentComponent) { - parentComponent = parentComponent._reactInternalFiber; + parentComponent = parentComponent._reactInternals; b: { if ( getNearestMountedFiber(parentComponent) !== parentComponent || @@ -7760,22 +8013,23 @@ function updateContainer(element, container, parentComponent, callback) { throw Error( "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." ); - var parentContext = parentComponent; + var JSCompiler_inline_result = parentComponent; do { - switch (parentContext.tag) { + switch (JSCompiler_inline_result.tag) { case 3: - parentContext = parentContext.stateNode.context; + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode.context; break b; case 1: - if (isContextProvider(parentContext.type)) { - parentContext = - parentContext.stateNode + if (isContextProvider(JSCompiler_inline_result.type)) { + JSCompiler_inline_result = + JSCompiler_inline_result.stateNode .__reactInternalMemoizedMergedChildContext; break b; } } - parentContext = parentContext.return; - } while (null !== parentContext); + JSCompiler_inline_result = JSCompiler_inline_result.return; + } while (null !== JSCompiler_inline_result); throw Error( "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." ); @@ -7786,34 +8040,26 @@ function updateContainer(element, container, parentComponent, callback) { parentComponent = processChildContext( parentComponent, Component, - parentContext + JSCompiler_inline_result ); break a; } } - parentComponent = parentContext; + parentComponent = JSCompiler_inline_result; } else parentComponent = emptyContextObject; null === container.context ? (container.context = parentComponent) : (container.pendingContext = parentComponent); - container = createUpdate(currentTime, suspenseConfig); + container = createUpdate(eventTime, lane); container.payload = { element: element }; callback = void 0 === callback ? null : callback; null !== callback && (container.callback = callback); enqueueUpdate(current, container); - scheduleWork(current, currentTime); - return currentTime; + scheduleUpdateOnFiber(current, lane, eventTime); + return lane; } -function createPortal(children, containerInfo, implementation) { - var key = - 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; - return { - $$typeof: REACT_PORTAL_TYPE, - key: null == key ? null : "" + key, - children: children, - containerInfo: containerInfo, - implementation: implementation - }; +function emptyFindFiberByHostInstance() { + return null; } function findNodeHandle(componentOrHandle) { if (null == componentOrHandle) return null; @@ -7842,53 +8088,70 @@ batchedUpdatesImpl = function(fn, a) { return fn(a); } finally { (executionContext = prevExecutionContext), - executionContext === NoContext && flushSyncCallbackQueue(); + 0 === executionContext && + ((workInProgressRootRenderTargetTime = now() + 500), + flushSyncCallbackQueue()); } }; -var roots = new Map(); -(function(devToolsConfig) { - var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; - return injectInternals({ - bundleType: devToolsConfig.bundleType, - version: devToolsConfig.version, - rendererPackageName: devToolsConfig.rendererPackageName, - rendererConfig: devToolsConfig.rendererConfig, - overrideHookState: null, - overrideProps: null, - setSuspenseHandler: null, - scheduleUpdate: null, - currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, - findHostInstanceByFiber: function(fiber) { - fiber = findCurrentHostFiber(fiber); - return null === fiber ? null : fiber.stateNode; - }, - findFiberByHostInstance: function(instance) { - return findFiberByHostInstance ? findFiberByHostInstance(instance) : null; - }, - findHostInstancesForRefresh: null, - scheduleRefresh: null, - scheduleRoot: null, - setRefreshHandler: null, - getCurrentFiber: null - }); -})({ - findFiberByHostInstance: getInstanceFromTag, - bundleType: 0, - version: "16.13.0", - rendererPackageName: "react-native-renderer", - rendererConfig: { - getInspectorDataForViewTag: function() { - throw Error( - "getInspectorDataForViewTag() is not available in production" - ); - }, - getInspectorDataForViewAtPoint: function() { - throw Error( - "getInspectorDataForViewAtPoint() is not available in production." - ); - }.bind(null, findNodeHandle) - } -}); +var roots = new Map(), + devToolsConfig$jscomp$inline_930 = { + findFiberByHostInstance: getInstanceFromTag, + bundleType: 0, + version: "17.0.1-454c2211c", + rendererPackageName: "react-native-renderer", + rendererConfig: { + getInspectorDataForViewTag: function() { + throw Error( + "getInspectorDataForViewTag() is not available in production" + ); + }, + getInspectorDataForViewAtPoint: function() { + throw Error( + "getInspectorDataForViewAtPoint() is not available in production." + ); + }.bind(null, findNodeHandle) + } + }; +var internals$jscomp$inline_1148 = { + bundleType: devToolsConfig$jscomp$inline_930.bundleType, + version: devToolsConfig$jscomp$inline_930.version, + rendererPackageName: devToolsConfig$jscomp$inline_930.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_930.rendererConfig, + overrideHookState: null, + overrideHookStateDeletePath: null, + overrideHookStateRenamePath: null, + overrideProps: null, + overridePropsDeletePath: null, + overridePropsRenamePath: null, + setSuspenseHandler: null, + scheduleUpdate: null, + currentDispatcherRef: ReactSharedInternals.ReactCurrentDispatcher, + findHostInstanceByFiber: function(fiber) { + fiber = findCurrentHostFiber(fiber); + return null === fiber ? null : fiber.stateNode; + }, + findFiberByHostInstance: + devToolsConfig$jscomp$inline_930.findFiberByHostInstance || + emptyFindFiberByHostInstance, + findHostInstancesForRefresh: null, + scheduleRefresh: null, + scheduleRoot: null, + setRefreshHandler: null, + getCurrentFiber: null +}; +if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { + var hook$jscomp$inline_1149 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if ( + !hook$jscomp$inline_1149.isDisabled && + hook$jscomp$inline_1149.supportsFiber + ) + try { + (rendererID = hook$jscomp$inline_1149.inject( + internals$jscomp$inline_1148 + )), + (injectedHook = hook$jscomp$inline_1149); + } catch (err) {} +} exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { computeComponentStackForErrorReporting: function(reactTag) { return (reactTag = getInstanceFromTag(reactTag)) @@ -7935,12 +8198,17 @@ exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { root = new FiberRootNode(containerTag, 0, !1); - var uninitializedFiber = 0; - isDevToolsPresent && (uninitializedFiber |= 8); - uninitializedFiber = new FiberNode(3, null, null, uninitializedFiber); - root.current = uninitializedFiber; - uninitializedFiber.stateNode = root; - initializeUpdateQueue(uninitializedFiber); + var JSCompiler_inline_result = 0; + isDevToolsPresent && (JSCompiler_inline_result |= 8); + JSCompiler_inline_result = createFiber( + 3, + null, + null, + JSCompiler_inline_result + ); + root.current = JSCompiler_inline_result; + JSCompiler_inline_result.stateNode = root; + initializeUpdateQueue(JSCompiler_inline_result); roots.set(containerTag, root); } updateContainer(element, root, null, callback); diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index 2f9876384b8357..552b118556aaf0 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -5,10 +5,15 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict */ -import type {ElementRef, AbstractComponent} from 'react'; +import type { + ElementRef, + ElementType, + MixedElement, + AbstractComponent, +} from 'react'; export type MeasureOnSuccessCallback = ( x: number, @@ -33,49 +38,66 @@ export type MeasureLayoutOnSuccessCallback = ( height: number, ) => void; -type AttributeType = +type AttributeType = | true | $ReadOnly<{| - diff?: (arg1: T, arg2: T) => boolean, - process?: (arg1: any) => any, + diff?: (arg1: T, arg2: T) => boolean, + process?: (arg1: V) => T, |}>; -export type AttributeConfiguration< - TProps = string, - TStyleProps = string, -> = $ReadOnly<{ - [propName: TProps]: AttributeType, - style: $ReadOnly<{[propName: TStyleProps]: AttributeType, ...}>, +// We either force that `diff` and `process` always use mixed, +// or we allow them to define specific types and use this hack +type AnyAttributeType = AttributeType<$FlowFixMe, $FlowFixMe>; + +type AttributeConfiguration = $ReadOnly<{ + [propName: string]: AnyAttributeType, + style: $ReadOnly<{ + [propName: string]: AnyAttributeType, + ..., + }>, + ... +}>; + +type PartialAttributeConfiguration = $ReadOnly<{ + [propName: string]: AnyAttributeType, + style?: $ReadOnly<{ + [propName: string]: AnyAttributeType, + ..., + }>, ... }>; -export type ReactNativeBaseComponentViewConfig< - TProps = string, - TStyleProps = string, -> = $ReadOnly<{| - baseModuleName?: string, +export type ViewConfig = $ReadOnly<{ + Commands?: $ReadOnly<{[commandName: string]: number, ...}>, + Constants?: $ReadOnly<{[name: string]: mixed, ...}>, + Manager?: string, + NativeProps?: $ReadOnly<{[propName: string]: string, ...}>, + baseModuleName?: ?string, bubblingEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| - phasedRegistrationNames: $ReadOnly<{| + [eventName: string]: $ReadOnly<{ + phasedRegistrationNames: $ReadOnly<{ captured: string, bubbled: string, - |}>, - |}>, + }>, + }>, ..., }>, - Commands?: $ReadOnly<{[commandName: string]: number, ...}>, directEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| + [eventName: string]: $ReadOnly<{ registrationName: string, - |}>, + }>, ..., }>, - NativeProps?: $ReadOnly<{[propName: string]: string, ...}>, uiViewClassName: string, - validAttributes: AttributeConfiguration, -|}>; + validAttributes: AttributeConfiguration, +}>; -export type ViewConfigGetter = () => ReactNativeBaseComponentViewConfig<>; +export type PartialViewConfig = $ReadOnly<{ + bubblingEventTypes?: $PropertyType, + directEventTypes?: $PropertyType, + uiViewClassName: string, + validAttributes?: PartialAttributeConfiguration, +}>; export type NativeMethods = { blur(): void, @@ -87,7 +109,7 @@ export type NativeMethods = { onSuccess: MeasureLayoutOnSuccessCallback, onFail?: () => void, ): void, - setNativeProps(nativeProps: Object): void, + setNativeProps(nativeProps: {...}): void, ... }; @@ -111,9 +133,11 @@ type InspectorDataSource = $ReadOnly<{| |}>; type InspectorDataGetter = ( - (componentOrHandle: any) => ?number, + ( + componentOrHandle: ElementRef | number, + ) => ?number, ) => $ReadOnly<{| - measure: Function, + measure: (callback: MeasureOnSuccessCallback) => void, props: InspectorDataProps, source: InspectorDataSource, |}>; @@ -145,52 +169,71 @@ export type TouchedViewDataAtPoint = $ReadOnly<{| * Provide minimal Flow typing for the high-level RN API and call it a day. */ export type ReactNativeType = { - findHostInstance_DEPRECATED( - componentOrHandle: any, + findHostInstance_DEPRECATED( + componentOrHandle: ?(ElementRef | number), ): ?ElementRef>, - findNodeHandle(componentOrHandle: any): ?number, - dispatchCommand(handle: any, command: string, args: Array): void, + findNodeHandle( + componentOrHandle: ?(ElementRef | number), + ): ?number, + dispatchCommand( + handle: ElementRef>, + command: string, + args: Array, + ): void, + sendAccessibilityEvent( + handle: ElementRef>, + eventType: string, + ): void, render( - element: React$Element, - containerTag: any, - callback: ?Function, - ): any, - unmountComponentAtNode(containerTag: number): any, - unmountComponentAtNodeAndRemoveContainer(containerTag: number): any, - // TODO (bvaughn) Add types - unstable_batchedUpdates: any, + element: MixedElement, + containerTag: number, + callback: ?() => void, + ): ?ElementRef, + unmountComponentAtNode(containerTag: number): void, + unmountComponentAtNodeAndRemoveContainer(containerTag: number): void, + unstable_batchedUpdates: (fn: (T) => void, bookkeeping: T) => void, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: SecretInternalsType, ... }; export type ReactFabricType = { - findHostInstance_DEPRECATED( - componentOrHandle: any, + findHostInstance_DEPRECATED( + componentOrHandle: ?(ElementRef | number), ): ?ElementRef>, - findNodeHandle(componentOrHandle: any): ?number, - dispatchCommand(handle: any, command: string, args: Array): void, + findNodeHandle( + componentOrHandle: ?(ElementRef | number), + ): ?number, + dispatchCommand( + handle: ElementRef>, + command: string, + args: Array, + ): void, + sendAccessibilityEvent( + handle: ElementRef>, + eventType: string, + ): void, render( - element: React$Element, - containerTag: any, - callback: ?Function, - ): any, - unmountComponentAtNode(containerTag: number): any, + element: MixedElement, + containerTag: number, + callback: ?() => void, + ): ?ElementRef, + unmountComponentAtNode(containerTag: number): void, ... }; export type ReactNativeEventTarget = { - node: Object, + node: {...}, canonical: { _nativeTag: number, - viewConfig: ReactNativeBaseComponentViewConfig<>, - currentProps: Object, - _internalInstanceHandle: Object, + viewConfig: ViewConfig, + currentProps: {...}, + _internalInstanceHandle: {...}, ... }, ... }; -export type ReactFaricEventTouch = { +export type ReactFabricEventTouch = { identifier: number, locationX: number, locationY: number, @@ -204,10 +247,10 @@ export type ReactFaricEventTouch = { ... }; -export type ReactFaricEvent = { - touches: Array, - changedTouches: Array, - targetTouches: Array, +export type ReactFabricEvent = { + touches: Array, + changedTouches: Array, + targetTouches: Array, target: number, ... }; diff --git a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js index 2c09ddf3caab10..194a91e31ae624 100644 --- a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +++ b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js @@ -8,16 +8,10 @@ * @flow strict-local */ -/* eslint-disable react-internal/invariant-args */ - 'use strict'; -import type { - ReactNativeBaseComponentViewConfig, - ViewConfigGetter, -} from './ReactNativeTypes'; - -const invariant = require('invariant'); +import {type ViewConfig} from './ReactNativeTypes'; +import invariant from 'invariant'; // Event configs const customBubblingEventTypes: { @@ -42,9 +36,7 @@ exports.customDirectEventTypes = customDirectEventTypes; const viewConfigCallbacks = new Map(); const viewConfigs = new Map(); -function processEventTypes( - viewConfig: ReactNativeBaseComponentViewConfig<>, -): void { +function processEventTypes(viewConfig: ViewConfig): void { const {bubblingEventTypes, directEventTypes} = viewConfig; if (__DEV__) { @@ -82,7 +74,7 @@ function processEventTypes( * A callback is provided to load the view config from UIManager. * The callback is deferred until the view is actually rendered. */ -exports.register = function(name: string, callback: ViewConfigGetter): string { +exports.register = function(name: string, callback: () => ViewConfig): string { invariant( !viewConfigCallbacks.has(name), 'Tried to register two views with the same name %s', @@ -103,7 +95,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): ViewConfig { let viewConfig; if (!viewConfigs.has(name)) { const callback = viewConfigCallbacks.get(name); diff --git a/Libraries/Renderer/shims/createReactNativeComponentClass.js b/Libraries/Renderer/shims/createReactNativeComponentClass.js index 86a758d918b483..f8f4c9284e4c32 100644 --- a/Libraries/Renderer/shims/createReactNativeComponentClass.js +++ b/Libraries/Renderer/shims/createReactNativeComponentClass.js @@ -11,8 +11,7 @@ 'use strict'; import {ReactNativeViewConfigRegistry} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; - -import type {ViewConfigGetter} from './ReactNativeTypes'; +import {type ViewConfig} from './ReactNativeTypes'; const {register} = ReactNativeViewConfigRegistry; @@ -26,7 +25,7 @@ const {register} = ReactNativeViewConfigRegistry; */ const createReactNativeComponentClass = function( name: string, - callback: ViewConfigGetter, + callback: () => ViewConfig, ): string { return register(name, callback); }; diff --git a/Libraries/Settings/RCTSettingsManager.mm b/Libraries/Settings/RCTSettingsManager.mm index 2f6645f24d6dd0..585d60aee224b3 100644 --- a/Libraries/Settings/RCTSettingsManager.mm +++ b/Libraries/Settings/RCTSettingsManager.mm @@ -10,7 +10,7 @@ #import #import #import -#import +#import #import #import "RCTSettingsPlugins.h" @@ -24,7 +24,7 @@ @implementation RCTSettingsManager NSUserDefaults *_defaults; } -@synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -72,7 +72,7 @@ - (void)userDefaultsDidChange:(NSNotification *)note #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"settingsUpdated" body:RCTJSONClean([_defaults dictionaryRepresentation])]; #pragma clang diagnostic pop diff --git a/Libraries/Settings/React-RCTSettings.podspec b/Libraries/Settings/React-RCTSettings.podspec index 45c92ba557b623..cfc8ab77c117f5 100644 --- a/Libraries/Settings/React-RCTSettings.podspec +++ b/Libraries/Settings/React-RCTSettings.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/settings" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/Storage/AsyncStorage.js b/Libraries/Storage/AsyncStorage.js index 67f365a0e03896..a4fcfd70a98411 100644 --- a/Libraries/Storage/AsyncStorage.js +++ b/Libraries/Storage/AsyncStorage.js @@ -5,18 +5,32 @@ * LICENSE file in the root directory of this source tree. * * @format - * @noflow - * @flow-weak + * @flow strict * @jsdoc */ 'use strict'; -import NativeAsyncStorage from './NativeAsyncStorage'; +import NativeAsyncLocalStorage from './NativeAsyncLocalStorage'; +import NativeAsyncSQLiteDBStorage from './NativeAsyncSQLiteDBStorage'; import invariant from 'invariant'; // Use SQLite if available, otherwise file storage. -const RCTAsyncStorage = NativeAsyncStorage; +const RCTAsyncStorage = NativeAsyncSQLiteDBStorage || NativeAsyncLocalStorage; + +type GetRequest = { + keys: Array, + callback: ?(errors: ?Array, result: ?Array>) => void, + keyIndex: number, + resolve: ( + result?: + | void + | null + | Promise>> + | Array>, + ) => void, + reject: (error?: mixed) => void, +}; /** * `AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value @@ -26,7 +40,7 @@ const RCTAsyncStorage = NativeAsyncStorage; * See https://reactnative.dev/docs/asyncstorage.html */ const AsyncStorage = { - _getRequests: ([]: Array), + _getRequests: ([]: Array), _getKeys: ([]: Array), _immediate: (null: ?number), @@ -38,7 +52,7 @@ const AsyncStorage = { getItem: function( key: string, callback?: ?(error: ?Error, result: ?string) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiGet([key], function(errors, result) { @@ -64,7 +78,7 @@ const AsyncStorage = { key: string, value: string, callback?: ?(error: ?Error) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiSet([[key, value]], function(errors) { @@ -73,7 +87,7 @@ const AsyncStorage = { if (errs) { reject(errs[0]); } else { - resolve(null); + resolve(); } }); }); @@ -87,7 +101,7 @@ const AsyncStorage = { removeItem: function( key: string, callback?: ?(error: ?Error) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiRemove([key], function(errors) { @@ -96,7 +110,7 @@ const AsyncStorage = { if (errs) { reject(errs[0]); } else { - resolve(null); + resolve(); } }); }); @@ -114,7 +128,7 @@ const AsyncStorage = { key: string, value: string, callback?: ?(error: ?Error) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiMerge([[key, value]], function(errors) { @@ -123,7 +137,7 @@ const AsyncStorage = { if (errs) { reject(errs[0]); } else { - resolve(null); + resolve(); } }); }); @@ -136,7 +150,7 @@ const AsyncStorage = { * * See https://reactnative.dev/docs/asyncstorage.html#clear */ - clear: function(callback?: ?(error: ?Error) => void): Promise { + clear: function(callback?: ?(error: ?Error) => void): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.clear(function(error) { @@ -144,7 +158,7 @@ const AsyncStorage = { if (error && convertError(error)) { reject(convertError(error)); } else { - resolve(null); + resolve(); } }); }); @@ -157,7 +171,7 @@ const AsyncStorage = { */ getAllKeys: function( callback?: ?(error: ?Error, keys: ?Array) => void, - ): Promise { + ): Promise> { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.getAllKeys(function(error, keys) { @@ -228,7 +242,7 @@ const AsyncStorage = { multiGet: function( keys: Array, callback?: ?(errors: ?Array, result: ?Array>) => void, - ): Promise { + ): Promise>> { if (!this._immediate) { this._immediate = setImmediate(() => { this._immediate = null; @@ -236,29 +250,22 @@ const AsyncStorage = { }); } - const getRequest = { - keys: keys, - callback: callback, - // do we need this? - keyIndex: this._getKeys.length, - resolve: null, - reject: null, - }; - - const promiseResult = new Promise((resolve, reject) => { - getRequest.resolve = resolve; - getRequest.reject = reject; - }); - - this._getRequests.push(getRequest); - // avoid fetching duplicates - keys.forEach(key => { - if (this._getKeys.indexOf(key) === -1) { - this._getKeys.push(key); - } + return new Promise>>((resolve, reject) => { + this._getRequests.push({ + keys, + callback, + // do we need this? + keyIndex: this._getKeys.length, + resolve, + reject, + }); + // avoid fetching duplicates + keys.forEach(key => { + if (this._getKeys.indexOf(key) === -1) { + this._getKeys.push(key); + } + }); }); - - return promiseResult; }, /** @@ -270,7 +277,7 @@ const AsyncStorage = { multiSet: function( keyValuePairs: Array>, callback?: ?(errors: ?Array) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiSet(keyValuePairs, function(errors) { @@ -279,7 +286,7 @@ const AsyncStorage = { if (error) { reject(error); } else { - resolve(null); + resolve(); } }); }); @@ -293,7 +300,7 @@ const AsyncStorage = { multiRemove: function( keys: Array, callback?: ?(errors: ?Array) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiRemove(keys, function(errors) { @@ -302,7 +309,7 @@ const AsyncStorage = { if (error) { reject(error); } else { - resolve(null); + resolve(); } }); }); @@ -319,7 +326,7 @@ const AsyncStorage = { multiMerge: function( keyValuePairs: Array>, callback?: ?(errors: ?Array) => void, - ): Promise { + ): Promise { invariant(RCTAsyncStorage, 'RCTAsyncStorage not available'); return new Promise((resolve, reject) => { RCTAsyncStorage.multiMerge(keyValuePairs, function(errors) { @@ -328,7 +335,7 @@ const AsyncStorage = { if (error) { reject(error); } else { - resolve(null); + resolve(); } }); }); @@ -336,24 +343,38 @@ const AsyncStorage = { }; // Not all native implementations support merge. -if (!RCTAsyncStorage.multiMerge) { - delete AsyncStorage.mergeItem; - delete AsyncStorage.multiMerge; +// TODO: Check whether above comment is correct. multiMerge is guaranteed to +// exist in the module spec so we should be able to just remove this check. +if (RCTAsyncStorage && !RCTAsyncStorage.multiMerge) { + // $FlowFixMe[unclear-type] + delete (AsyncStorage: any).mergeItem; + // $FlowFixMe[unclear-type] + delete (AsyncStorage: any).multiMerge; } -function convertErrors(errs) { +function convertErrors( + // NOTE: The native module spec only has the Array case, but the Android + // implementation passes a single object. + errs: ?( + | {message: string, key?: string} + | Array<{message: string, key?: string}> + ), +) { if (!errs) { return null; } return (Array.isArray(errs) ? errs : [errs]).map(e => convertError(e)); } +declare function convertError(void | null): null; +declare function convertError({message: string, key?: string}): Error; function convertError(error) { if (!error) { return null; } const out = new Error(error.message); - out.key = error.key; // flow doesn't like this :( + // $FlowFixMe[unclear-type] + (out: any).key = error.key; return out; } diff --git a/Libraries/Storage/NativeAsyncLocalStorage.js b/Libraries/Storage/NativeAsyncLocalStorage.js new file mode 100644 index 00000000000000..39502dde329545 --- /dev/null +++ b/Libraries/Storage/NativeAsyncLocalStorage.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {}; + +multiGet: ( + keys: Array, + callback: ( + errors: ?Array<{message: string, key?: string}>, + kvPairs: ?Array>, + ) => void, + ) => void; + +multiSet: ( + kvPairs: Array>, + callback: (errors: ?Array<{message: string, key?: string}>) => void, + ) => void; + +multiMerge: ( + kvPairs: Array>, + callback: (errors: ?Array<{message: string, key?: string}>) => void, + ) => void; + +multiRemove: ( + keys: Array, + callback: (errors: ?Array<{message: string, key?: string}>) => void, + ) => void; + +clear: (callback: (error: {message: string, key?: string}) => void) => void; + +getAllKeys: ( + callback: ( + error: ?{message: string, key?: string}, + allKeys: ?Array, + ) => void, + ) => void; +} + +export default (TurboModuleRegistry.get('AsyncLocalStorage'): ?Spec); diff --git a/Libraries/Storage/NativeAsyncStorage.js b/Libraries/Storage/NativeAsyncSQLiteDBStorage.js similarity index 61% rename from Libraries/Storage/NativeAsyncStorage.js rename to Libraries/Storage/NativeAsyncSQLiteDBStorage.js index 539adfd80dc4ee..d3431643370de4 100644 --- a/Libraries/Storage/NativeAsyncStorage.js +++ b/Libraries/Storage/NativeAsyncSQLiteDBStorage.js @@ -14,31 +14,33 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { - +getConstants: () => {||}; + +getConstants: () => {}; +multiGet: ( keys: Array, callback: ( - errors: ?Array<{|message: string|}>, + errors: ?Array<{message: string, key?: string}>, kvPairs: ?Array>, ) => void, ) => void; +multiSet: ( kvPairs: Array>, - callback: (errors: ?Array<{|message: string|}>) => void, + callback: (errors: ?Array<{message: string, key?: string}>) => void, ) => void; +multiMerge: ( kvPairs: Array>, - callback: (errors: ?Array<{|message: string|}>) => void, + callback: (errors: ?Array<{message: string, key?: string}>) => void, ) => void; +multiRemove: ( keys: Array, - callback: (errors: ?Array<{|message: string|}>) => void, + callback: (errors: ?Array<{message: string, key?: string}>) => void, ) => void; - +clear: (callback: (error: {|message: string|}) => void) => void; + +clear: (callback: (error: {message: string, key?: string}) => void) => void; +getAllKeys: ( - callback: (error: ?{|message: string|}, allKeys: ?Array) => void, + callback: ( + error: ?{message: string, key?: string}, + allKeys: ?Array, + ) => void, ) => void; } -export default (TurboModuleRegistry.get('AsyncSQLiteDBStorage') || - TurboModuleRegistry.get('AsyncLocalStorage'): ?Spec); +export default (TurboModuleRegistry.get('AsyncSQLiteDBStorage'): ?Spec); diff --git a/Libraries/StyleSheet/StyleSheetTypes.js b/Libraries/StyleSheet/StyleSheetTypes.js index 95ed2b8a2cced7..5a32873e345643 100644 --- a/Libraries/StyleSheet/StyleSheetTypes.js +++ b/Libraries/StyleSheet/StyleSheetTypes.js @@ -675,3 +675,8 @@ export type ____Styles_Internal = { +[key: string]: $Shape<____DangerouslyImpreciseStyle_Internal>, ..., }; + +export type ____FlattenStyleProp_Internal<+TStyleProp> = $Call< + (GenericStyleProp) => T, + TStyleProp, +>; diff --git a/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js b/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js index 0bb9a1a19940b3..2206b3fa61dcf2 100644 --- a/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js +++ b/Libraries/StyleSheet/__tests__/splitLayoutProps-test.js @@ -10,7 +10,7 @@ 'use strict'; -const splitLayoutProps = require('../splitLayoutProps'); +const splitLayoutProps = require('../splitLayoutProps').default; test('splits style objects', () => { const style = {width: 10, margin: 20, padding: 30, transform: {scaleY: -1}}; @@ -45,3 +45,9 @@ test('does not copy values to both returned objects', () => { } `); }); + +test('returns null values if argument is null', () => { + const {outer, inner} = splitLayoutProps(null); + expect(outer).toBe(null); + expect(inner).toBe(null); +}); diff --git a/Libraries/StyleSheet/flattenStyle.js b/Libraries/StyleSheet/flattenStyle.js index 679e39b3af6643..488ef19d061336 100644 --- a/Libraries/StyleSheet/flattenStyle.js +++ b/Libraries/StyleSheet/flattenStyle.js @@ -10,14 +10,12 @@ 'use strict'; -import type { - DangerouslyImpreciseStyle, - DangerouslyImpreciseStyleProp, -} from './StyleSheet'; +import type {DangerouslyImpreciseStyleProp} from './StyleSheet'; +import type {____FlattenStyleProp_Internal} from './StyleSheetTypes'; -function flattenStyle( - style: ?DangerouslyImpreciseStyleProp, -): ?DangerouslyImpreciseStyle { +function flattenStyle<+TStyleProp: DangerouslyImpreciseStyleProp>( + style: ?TStyleProp, +): ?____FlattenStyleProp_Internal { if (style === null || typeof style !== 'object') { return undefined; } diff --git a/Libraries/StyleSheet/splitLayoutProps.js b/Libraries/StyleSheet/splitLayoutProps.js index 953b3e55f462fd..491da11c45f255 100644 --- a/Libraries/StyleSheet/splitLayoutProps.js +++ b/Libraries/StyleSheet/splitLayoutProps.js @@ -4,61 +4,67 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format * @flow strict-local + * @format */ 'use strict'; -import type {DangerouslyImpreciseStyle} from './StyleSheet'; +import type {____ViewStyle_Internal} from './StyleSheetTypes'; -const OUTER_PROPS = Object.assign(Object.create(null), { - margin: true, - marginHorizontal: true, - marginVertical: true, - marginBottom: true, - marginTop: true, - marginLeft: true, - marginRight: true, - flex: true, - flexGrow: true, - flexShrink: true, - flexBasis: true, - alignSelf: true, - height: true, - minHeight: true, - maxHeight: true, - width: true, - minWidth: true, - maxWidth: true, - position: true, - left: true, - right: true, - bottom: true, - top: true, - transform: true, -}); - -function splitLayoutProps( - props: ?DangerouslyImpreciseStyle, +export default function splitLayoutProps( + props: ?____ViewStyle_Internal, ): { - outer: DangerouslyImpreciseStyle, - inner: DangerouslyImpreciseStyle, - ... + outer: ?____ViewStyle_Internal, + inner: ?____ViewStyle_Internal, } { - const inner = {}; - const outer = {}; - if (props) { - Object.keys(props).forEach(k => { - const value: $ElementType = props[k]; - if (OUTER_PROPS[k]) { - outer[k] = value; - } else { - inner[k] = value; + let outer: ?____ViewStyle_Internal = null; + let inner: ?____ViewStyle_Internal = null; + + if (props != null) { + // $FlowIgnore[incompatible-exact] Will contain a subset of keys from `props`. + // $FlowIgnore[incompatible-type] Values are preserved within a key. + outer = {}; + // $FlowIgnore[incompatible-exact] Will contain a subset of keys from `props`. + // $FlowIgnore[incompatible-type] Values are preserved within a key. + inner = {}; + + for (const prop of Object.keys(props)) { + switch (prop) { + case 'margin': + case 'marginHorizontal': + case 'marginVertical': + case 'marginBottom': + case 'marginTop': + case 'marginLeft': + case 'marginRight': + case 'flex': + case 'flexGrow': + case 'flexShrink': + case 'flexBasis': + case 'alignSelf': + case 'height': + case 'minHeight': + case 'maxHeight': + case 'width': + case 'minWidth': + case 'maxWidth': + case 'position': + case 'left': + case 'right': + case 'bottom': + case 'top': + case 'transform': + // $FlowFixMe[cannot-write] + outer[prop] = props[prop]; + break; + default: + // $FlowFixMe[cannot-write] + inner[prop] = props[prop]; + break; } - }); + } } + return {outer, inner}; } - -module.exports = splitLayoutProps; diff --git a/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm index 1df592edec4b34..8fb752dbb27777 100644 --- a/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm +++ b/Libraries/SurfaceBackedComponent/RCTSurfaceBackedComponent.mm @@ -58,8 +58,10 @@ + (instancetype)newWithBridge:(RCTBridge *)bridge if (options.activityIndicatorComponentFactory == nil || RCTSurfaceStageIsRunning(state.surface.stage)) { component = surfaceHostingComponent; } else { - component = [CKOverlayLayoutComponent newWithComponent:surfaceHostingComponent - overlay:options.activityIndicatorComponentFactory()]; + component = CK::OverlayLayoutComponentBuilder() + .component(surfaceHostingComponent) + .overlay(options.activityIndicatorComponentFactory()) + .build(); } return [super newWithComponent:component]; diff --git a/Libraries/Text/React-RCTText.podspec b/Libraries/Text/React-RCTText.podspec index 6f94706d54e3bc..af8a8f6ec70156 100644 --- a/Libraries/Text/React-RCTText.podspec +++ b/Libraries/Text/React-RCTText.podspec @@ -24,7 +24,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/text" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.source = source s.source_files = "**/*.{h,m}" s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index cce9cb3d9547e0..385164ea4ad116 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -4,297 +4,189 @@ * 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'; - -const DeprecatedTextPropTypes = require('../DeprecatedPropTypes/DeprecatedTextPropTypes'); -const React = require('react'); -const ReactNativeViewAttributes = require('../Components/View/ReactNativeViewAttributes'); -const TextAncestor = require('./TextAncestor'); -const Touchable = require('../Components/Touchable/Touchable'); -const UIManager = require('../ReactNative/UIManager'); - -const createReactNativeComponentClass = require('../Renderer/shims/createReactNativeComponentClass'); -const nullthrows = require('nullthrows'); -const processColor = require('../StyleSheet/processColor'); - -import type {PressEvent} from '../Types/CoreEventTypes'; -import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; -import type {PressRetentionOffset, TextProps} from './TextProps'; - -type ResponseHandlers = $ReadOnly<{| - onStartShouldSetResponder: () => boolean, - onResponderGrant: (event: PressEvent, dispatchID: string) => void, - onResponderMove: (event: PressEvent) => void, - onResponderRelease: (event: PressEvent) => void, - onResponderTerminate: (event: PressEvent) => void, - onResponderTerminationRequest: () => boolean, -|}>; - -type Props = $ReadOnly<{| - ...TextProps, - forwardedRef: ?React.Ref<'RCTText' | 'RCTVirtualText'>, -|}>; - -type State = {| - touchable: {| - touchState: ?string, - responderID: ?number, - |}, - isHighlighted: boolean, - createResponderHandlers: () => ResponseHandlers, - responseHandlers: ?ResponseHandlers, -|}; - -const PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - -const viewConfig = { - validAttributes: { - ...ReactNativeViewAttributes.UIView, - isHighlighted: true, - numberOfLines: true, - ellipsizeMode: true, - allowFontScaling: true, - maxFontSizeMultiplier: true, - disabled: true, - selectable: true, - selectionColor: true, - adjustsFontSizeToFit: true, - minimumFontScale: true, - textBreakStrategy: true, - onTextLayout: true, - onInlineViewLayout: true, - dataDetectorType: true, - android_hyphenationFrequency: true, - }, - directEventTypes: { - topTextLayout: { - registrationName: 'onTextLayout', - }, - topInlineViewLayout: { - registrationName: 'onInlineViewLayout', - }, - }, - uiViewClassName: 'RCTText', -}; +import DeprecatedTextPropTypes from '../DeprecatedPropTypes/DeprecatedTextPropTypes'; +import * as PressabilityDebug from '../Pressability/PressabilityDebug'; +import usePressability from '../Pressability/usePressability'; +import StyleSheet from '../StyleSheet/StyleSheet'; +import processColor from '../StyleSheet/processColor'; +import TextAncestor from './TextAncestor'; +import {NativeText, NativeVirtualText} from './TextNativeComponent'; +import {type TextProps} from './TextProps'; +import * as React from 'react'; +import {useContext, useMemo, useState} from 'react'; /** - * A React component for displaying text. + * Text is the fundamental component for displaying text. * - * See https://reactnative.dev/docs/text.html + * @see https://reactnative.dev/docs/text.html */ -class TouchableText extends React.Component { - static defaultProps = { - accessible: true, - allowFontScaling: true, - ellipsizeMode: 'tail', - }; - - touchableGetPressRectOffset: ?() => PressRetentionOffset; - touchableHandleActivePressIn: ?() => void; - touchableHandleActivePressOut: ?() => void; - touchableHandleLongPress: ?(event: PressEvent) => void; - touchableHandlePress: ?(event: PressEvent) => void; - touchableHandleResponderGrant: ?(event: PressEvent) => void; - touchableHandleResponderMove: ?(event: PressEvent) => void; - touchableHandleResponderRelease: ?(event: PressEvent) => void; - touchableHandleResponderTerminate: ?(event: PressEvent) => void; - touchableHandleResponderTerminationRequest: ?() => boolean; - - state = { - ...Touchable.Mixin.touchableGetInitialState(), - isHighlighted: false, - createResponderHandlers: this._createResponseHandlers.bind(this), - responseHandlers: null, - }; - - static getDerivedStateFromProps( - nextProps: Props, - prevState: State, - ): $Shape | null { - return prevState.responseHandlers == null && isTouchable(nextProps) - ? { - responseHandlers: prevState.createResponderHandlers(), - } - : null; - } - - static viewConfig = viewConfig; - - render(): React.Node { - let props = this.props; - if (isTouchable(props)) { - props = { - ...props, - ...this.state.responseHandlers, - isHighlighted: this.state.isHighlighted, - }; - } - if (props.selectionColor != null) { - props = { - ...props, - selectionColor: processColor(props.selectionColor), - }; - } - if (__DEV__) { - if (Touchable.TOUCH_TARGET_DEBUG && props.onPress != null) { - props = { - ...props, - style: [props.style, {color: 'magenta'}], - }; - } +const Text: React.AbstractComponent< + TextProps, + React.ElementRef, +> = React.forwardRef((props: TextProps, forwardedRef) => { + const { + accessible, + allowFontScaling, + ellipsizeMode, + onLongPress, + onPress, + onResponderGrant, + onResponderMove, + onResponderRelease, + onResponderTerminate, + onResponderTerminationRequest, + onStartShouldSetResponder, + pressRetentionOffset, + suppressHighlighting, + ...restProps + } = props; + + const [isHighlighted, setHighlighted] = useState(false); + + const isPressable = + onPress != null || onLongPress != null || onStartShouldSetResponder != null; + + const initialized = useLazyInitialization(isPressable); + const config = useMemo( + () => + initialized + ? { + disabled: !isPressable, + pressRectOffset: pressRetentionOffset, + onLongPress, + onPress, + onPressIn(event) { + setHighlighted(!suppressHighlighting); + }, + onPressOut(event) { + setHighlighted(false); + }, + onResponderTerminationRequest_DEPRECATED: onResponderTerminationRequest, + onStartShouldSetResponder_DEPRECATED: onStartShouldSetResponder, + } + : null, + [ + initialized, + isPressable, + pressRetentionOffset, + onLongPress, + onPress, + onResponderTerminationRequest, + onStartShouldSetResponder, + suppressHighlighting, + ], + ); + + const eventHandlers = usePressability(config); + const eventHandlersForText = useMemo( + () => + eventHandlers == null + ? null + : { + onResponderGrant(event) { + eventHandlers.onResponderGrant(event); + if (onResponderGrant != null) { + onResponderGrant(event); + } + }, + onResponderMove(event) { + eventHandlers.onResponderMove(event); + if (onResponderMove != null) { + onResponderMove(event); + } + }, + onResponderRelease(event) { + eventHandlers.onResponderRelease(event); + if (onResponderRelease != null) { + onResponderRelease(event); + } + }, + onResponderTerminate(event) { + eventHandlers.onResponderTerminate(event); + if (onResponderTerminate != null) { + onResponderTerminate(event); + } + }, + onResponderTerminationRequest: + eventHandlers.onResponderTerminationRequest, + onStartShouldSetResponder: eventHandlers.onStartShouldSetResponder, + }, + [ + eventHandlers, + onResponderGrant, + onResponderMove, + onResponderRelease, + onResponderTerminate, + ], + ); + + // TODO: Move this processing to the view configuration. + const selectionColor = + restProps.selectionColor == null + ? null + : processColor(restProps.selectionColor); + + let style = restProps.style; + if (__DEV__) { + if (PressabilityDebug.isEnabled() && onPress != null) { + style = StyleSheet.compose(restProps.style, { + color: 'magenta', + }); } - return ( - - {hasTextAncestor => - hasTextAncestor ? ( - - ) : ( - - - - ) - } - - ); } - _createResponseHandlers(): ResponseHandlers { - return { - onStartShouldSetResponder: (): boolean => { - const {onStartShouldSetResponder} = this.props; - const shouldSetResponder = - (onStartShouldSetResponder == null - ? false - : onStartShouldSetResponder()) || isTouchable(this.props); - - if (shouldSetResponder) { - this._attachTouchHandlers(); - } - return shouldSetResponder; - }, - onResponderGrant: (event: PressEvent): void => { - nullthrows(this.touchableHandleResponderGrant)(event); - if (this.props.onResponderGrant != null) { - this.props.onResponderGrant.call(this, event); - } - }, - onResponderMove: (event: PressEvent): void => { - nullthrows(this.touchableHandleResponderMove)(event); - if (this.props.onResponderMove != null) { - this.props.onResponderMove.call(this, event); - } - }, - onResponderRelease: (event: PressEvent): void => { - nullthrows(this.touchableHandleResponderRelease)(event); - if (this.props.onResponderRelease != null) { - this.props.onResponderRelease.call(this, event); - } - }, - onResponderTerminate: (event: PressEvent): void => { - nullthrows(this.touchableHandleResponderTerminate)(event); - if (this.props.onResponderTerminate != null) { - this.props.onResponderTerminate.call(this, event); - } - }, - onResponderTerminationRequest: (): boolean => { - const {onResponderTerminationRequest} = this.props; - if (!nullthrows(this.touchableHandleResponderTerminationRequest)()) { - return false; - } - if (onResponderTerminationRequest == null) { - return true; - } - return onResponderTerminationRequest(); - }, - }; - } + const hasTextAncestor = useContext(TextAncestor); + + return hasTextAncestor ? ( + + ) : ( + + + + ); +}); + +Text.displayName = 'Text'; + +// TODO: Delete this. +Text.propTypes = DeprecatedTextPropTypes; - /** - * Lazily attaches Touchable.Mixin handlers. - */ - _attachTouchHandlers(): void { - if (this.touchableGetPressRectOffset != null) { - return; - } - for (const key in Touchable.Mixin) { - if (typeof Touchable.Mixin[key] === 'function') { - (this: any)[key] = Touchable.Mixin[key].bind(this); - } - } - this.touchableHandleActivePressIn = (): void => { - if (!this.props.suppressHighlighting && isTouchable(this.props)) { - this.setState({isHighlighted: true}); - } - }; - this.touchableHandleActivePressOut = (): void => { - if (!this.props.suppressHighlighting && isTouchable(this.props)) { - this.setState({isHighlighted: false}); - } - }; - this.touchableHandlePress = (event: PressEvent): void => { - if (this.props.onPress != null) { - this.props.onPress(event); - } - }; - this.touchableHandleLongPress = (event: PressEvent): void => { - if (this.props.onLongPress != null) { - this.props.onLongPress(event); - } - }; - this.touchableGetPressRectOffset = (): PressRetentionOffset => - this.props.pressRetentionOffset == null - ? PRESS_RECT_OFFSET - : this.props.pressRetentionOffset; +/** + * Returns false until the first time `newValue` is true, after which this will + * always return true. This is necessary to lazily initialize `Pressability` so + * we do not eagerly create one for every pressable `Text` component. + */ +function useLazyInitialization(newValue: boolean): boolean { + const [oldValue, setValue] = useState(newValue); + if (!oldValue && newValue) { + setValue(newValue); } + return oldValue; } -const isTouchable = (props: Props): boolean => - props.onPress != null || - props.onLongPress != null || - props.onStartShouldSetResponder != null; - -const RCTText = createReactNativeComponentClass( - viewConfig.uiViewClassName, - () => viewConfig, -); - -const RCTVirtualText = - UIManager.getViewManagerConfig('RCTVirtualText') == null - ? RCTText - : createReactNativeComponentClass('RCTVirtualText', () => ({ - validAttributes: { - ...ReactNativeViewAttributes.UIView, - isHighlighted: true, - maxFontSizeMultiplier: true, - }, - uiViewClassName: 'RCTVirtualText', - })); - -const Text = ( - props: TextProps, - forwardedRef: ?React.Ref<'RCTText' | 'RCTVirtualText'>, -) => { - return ; -}; -const TextToExport = React.forwardRef(Text); -TextToExport.displayName = 'Text'; - -// TODO: Deprecate this. -/* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.89 was deployed. To see the error, delete this comment - * and run Flow. */ -TextToExport.propTypes = DeprecatedTextPropTypes; - -type TextStatics = $ReadOnly<{| - propTypes: typeof DeprecatedTextPropTypes, -|}>; - -module.exports = ((TextToExport: any): React.AbstractComponent< - TextProps, - React.ElementRef>, -> & - TextStatics); +// $FlowFixMe[incompatible-cast] - No good way to type a React.AbstractComponent with statics. +module.exports = (Text: typeof Text & + $ReadOnly<{ + propTypes: typeof DeprecatedTextPropTypes, + }>); diff --git a/Libraries/Text/Text/RCTTextView.m b/Libraries/Text/Text/RCTTextView.m index 0c13d038cb3502..bda5f8d078f428 100644 --- a/Libraries/Text/Text/RCTTextView.m +++ b/Libraries/Text/Text/RCTTextView.m @@ -227,7 +227,7 @@ - (void)disableContextMenu - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { // TODO: Adopt showMenuFromRect (necessary for UIKitForMac) -#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC +#if !TARGET_OS_UIKITFORMAC UIMenuController *menuController = [UIMenuController sharedMenuController]; if (menuController.isMenuVisible) { @@ -259,7 +259,6 @@ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender - (void)copy:(id)sender { -#if !TARGET_OS_TV NSAttributedString *attributedText = _textStorage; NSMutableDictionary *item = [NSMutableDictionary new]; @@ -276,7 +275,6 @@ - (void)copy:(id)sender UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.items = @[item]; -#endif } @end diff --git a/Libraries/Text/TextAncestor.js b/Libraries/Text/TextAncestor.js index b791319c80c171..3ea2d65ce91193 100644 --- a/Libraries/Text/TextAncestor.js +++ b/Libraries/Text/TextAncestor.js @@ -15,4 +15,10 @@ const React = require('react'); /** * Whether the current element is the descendant of a element. */ -module.exports = (React.createContext(false): React$Context<$FlowFixMe>); +const TextAncestorContext = (React.createContext( + false, +): React$Context<$FlowFixMe>); +if (__DEV__) { + TextAncestorContext.displayName = 'TextAncestorContext'; +} +module.exports = TextAncestorContext; diff --git a/Libraries/Text/TextInjection.js b/Libraries/Text/TextInjection.js new file mode 100644 index 00000000000000..0297aa2d073ef4 --- /dev/null +++ b/Libraries/Text/TextInjection.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +'use strict'; + +import typeof Text from './Text'; + +export default { + unstable_Text: (null: ?Text), +}; diff --git a/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m b/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m index 6f9696029b049f..7a661b183fa008 100644 --- a/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m +++ b/Libraries/Text/TextInput/Multiline/RCTMultilineTextInputViewManager.m @@ -19,8 +19,6 @@ - (UIView *)view #pragma mark - Multiline (aka TextView) specific properties -#if !TARGET_OS_TV RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) -#endif @end diff --git a/Libraries/Text/TextInput/Multiline/RCTUITextView.m b/Libraries/Text/TextInput/Multiline/RCTUITextView.m index 88d3183f4df345..a417cc11751099 100644 --- a/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -51,15 +51,22 @@ - (instancetype)initWithFrame:(CGRect)frame self.textColor = [UIColor blackColor]; // This line actually removes 5pt (default value) left and right padding in UITextView. self.textContainer.lineFragmentPadding = 0; -#if !TARGET_OS_TV self.scrollsToTop = NO; -#endif self.scrollEnabled = YES; } return self; } +- (void)setDelegate:(id)delegate { + // Delegate is set inside `[RCTBackedTextViewDelegateAdapter initWithTextView]` and + // it cannot be changed from outside. + if (super.delegate) { + return; + } + [super setDelegate:delegate]; +} + #pragma mark - Accessibility - (void)setIsAccessibilityElement:(BOOL)isAccessibilityElement diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.h b/Libraries/Text/TextInput/RCTBaseTextInputView.h index d7fc54bed85dab..d73f082cbd8986 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.h +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.h @@ -13,7 +13,6 @@ #import "RCTBackedTextInputViewProtocol.h" @class RCTBridge; -@class RCTEventDispatcher; @class RCTTextAttributes; @class RCTTextSelection; diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index 9edad515f00861..d619e5b5640a14 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -9,7 +9,7 @@ #import #import -#import +#import #import #import #import @@ -21,7 +21,7 @@ @implementation RCTBaseTextInputView { __weak RCTBridge *_bridge; - __weak RCTEventDispatcher *_eventDispatcher; + __weak id _eventDispatcher; BOOL _hasInputAccesoryView; NSString *_Nullable _predictedText; BOOL _didMoveToWindow; @@ -245,7 +245,7 @@ - (void)setTextContentType:(NSString *)type }; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ - if (@available(iOS 11.0, tvOS 11.0, *)) { + if (@available(iOS 11.0, *)) { NSDictionary * iOS11extras = @{@"username": UITextContentTypeUsername, @"password": UITextContentTypePassword}; @@ -257,7 +257,7 @@ - (void)setTextContentType:(NSString *)type #endif #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 /* __IPHONE_12_0 */ - if (@available(iOS 12.0, tvOS 12.0, *)) { + if (@available(iOS 12.0, *)) { NSDictionary * iOS12extras = @{@"newPassword": UITextContentTypeNewPassword, @"oneTimeCode": UITextContentTypeOneTimeCode}; @@ -572,7 +572,6 @@ - (void)didSetProps:(NSArray *)changedProps - (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID { - #if !TARGET_OS_TV __weak RCTBaseTextInputView *weakSelf = self; [_bridge.uiManager rootViewForReactTag:self.reactTag withCompletion:^(UIView *rootView) { RCTBaseTextInputView *strongSelf = weakSelf; @@ -585,12 +584,10 @@ - (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID } } }]; - #endif /* !TARGET_OS_TV */ } - (void)setDefaultInputAccessoryView { - #if !TARGET_OS_TV UIView *textInputView = self.backedTextInputView; UIKeyboardType keyboardType = textInputView.keyboardType; @@ -629,7 +626,6 @@ - (void)setDefaultInputAccessoryView textInputView.inputAccessoryView = nil; } [self reloadInputViewsIfNecessary]; - #endif /* !TARGET_OS_TV */ } - (void)reloadInputViewsIfNecessary diff --git a/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m b/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m index de77e47bf2d0d7..35db4d308733c4 100644 --- a/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m +++ b/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m @@ -30,7 +30,7 @@ - (instancetype)init _heightConstraint = [_safeAreaContainer.heightAnchor constraintEqualToConstant:0]; _heightConstraint.active = YES; - if (@available(iOS 11.0, tvOS 11.0, *)) { + if (@available(iOS 11.0, *)) { [_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES; [_safeAreaContainer.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES; [_safeAreaContainer.leadingAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leadingAnchor].active = YES; diff --git a/Libraries/Text/TextNativeComponent.js b/Libraries/Text/TextNativeComponent.js new file mode 100644 index 00000000000000..58edbf595ec98b --- /dev/null +++ b/Libraries/Text/TextNativeComponent.js @@ -0,0 +1,71 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import ReactNativeViewAttributes from '../Components/View/ReactNativeViewAttributes'; +import UIManager from '../ReactNative/UIManager'; +import {type HostComponent} from '../Renderer/shims/ReactNativeTypes'; +import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass'; +import {type ProcessedColorValue} from '../StyleSheet/processColor'; +import {type TextProps} from './TextProps'; + +type NativeTextProps = $ReadOnly<{ + ...TextProps, + isHighlighted?: ?boolean, + selectionColor?: ?ProcessedColorValue, +}>; + +export const NativeText: HostComponent = (createReactNativeComponentClass( + 'RCTText', + () => ({ + // $FlowFixMe[incompatible-call] + validAttributes: { + ...ReactNativeViewAttributes.UIView, + isHighlighted: true, + numberOfLines: true, + ellipsizeMode: true, + allowFontScaling: true, + maxFontSizeMultiplier: true, + disabled: true, + selectable: true, + selectionColor: true, + adjustsFontSizeToFit: true, + minimumFontScale: true, + textBreakStrategy: true, + onTextLayout: true, + onInlineViewLayout: true, + dataDetectorType: true, + android_hyphenationFrequency: true, + }, + directEventTypes: { + topTextLayout: { + registrationName: 'onTextLayout', + }, + topInlineViewLayout: { + registrationName: 'onInlineViewLayout', + }, + }, + uiViewClassName: 'RCTText', + }), +): any); + +export const NativeVirtualText: HostComponent = + !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') + ? NativeText + : (createReactNativeComponentClass('RCTVirtualText', () => ({ + // $FlowFixMe[incompatible-call] + validAttributes: { + ...ReactNativeViewAttributes.UIView, + isHighlighted: true, + maxFontSizeMultiplier: true, + }, + uiViewClassName: 'RCTVirtualText', + })): any); diff --git a/Libraries/TurboModule/TurboModuleRegistry.js b/Libraries/TurboModule/TurboModuleRegistry.js index 0e70e6b4610616..4fef584bb1377b 100644 --- a/Libraries/TurboModule/TurboModuleRegistry.js +++ b/Libraries/TurboModule/TurboModuleRegistry.js @@ -16,7 +16,7 @@ import invariant from 'invariant'; const turboModuleProxy = global.__turboModuleProxy; -function requireModule(name: string, schema?: ?$FlowFixMe): ?T { +function requireModule(name: string): ?T { // Bridgeless mode requires TurboModules if (!global.RN$Bridgeless) { // Backward compatibility layer during migration. @@ -27,8 +27,7 @@ function requireModule(name: string, schema?: ?$FlowFixMe): ?T { } if (turboModuleProxy != null) { - const module: ?T = - schema != null ? turboModuleProxy(name, schema) : turboModuleProxy(name); + const module: ?T = turboModuleProxy(name); return module; } @@ -36,31 +35,13 @@ function requireModule(name: string, schema?: ?$FlowFixMe): ?T { } export function get(name: string): ?T { - /** - * What is Schema? - * - * @react-native/babel-plugin-codegen will parse the NativeModule - * spec, and pass in the generated schema as the second argument - * to this function. The schem will then be used to perform method - * dispatch on, and translate arguments/return to and from the Native - * TurboModule object. - */ - const schema = arguments.length === 2 ? arguments[1] : undefined; - return requireModule(name, schema); + // $FlowFixMe[incompatible-call] + return requireModule(name); } export function getEnforcing(name: string): T { - /** - * What is Schema? - * - * @react-native/babel-plugin-codegen will parse the NativeModule - * spec, and pass in the generated schema as the second argument - * to this function. The schem will then be used to perform method - * dispatch on, and translate arguments/return to and from the Native - * TurboModule object. - */ - const schema = arguments.length === 2 ? arguments[1] : undefined; - const module = requireModule(name, schema); + // $FlowFixMe[incompatible-call] + const module = requireModule(name); invariant( module != null, `TurboModuleRegistry.getEnforcing(...): '${name}' could not be found. ` + diff --git a/Libraries/TurboModule/samples/NativeSampleTurboModule.js b/Libraries/TurboModule/samples/NativeSampleTurboModule.js index f9c4c6ef53e393..d240c4ad3ab4a4 100644 --- a/Libraries/TurboModule/samples/NativeSampleTurboModule.js +++ b/Libraries/TurboModule/samples/NativeSampleTurboModule.js @@ -10,6 +10,7 @@ 'use strict'; +import type {UnsafeObject} from '../../Types/CodegenTypes'; import type {RootTag, TurboModule} from '../RCTExport'; import * as TurboModuleRegistry from '../TurboModuleRegistry'; @@ -26,6 +27,7 @@ export interface Spec extends TurboModule { +getString: (arg: string) => string; +getArray: (arg: Array) => Array; +getObject: (arg: Object) => Object; + +getUnsafeObject: (arg: UnsafeObject) => UnsafeObject; +getRootTag: (arg: RootTag) => RootTag; +getValue: (x: number, y: string, z: Object) => Object; +getValueWithCallback: (callback: (value: string) => void) => void; diff --git a/Libraries/TypeSafety/RCTConvertHelpers.h b/Libraries/TypeSafety/RCTConvertHelpers.h index 1b6bf9341e7a86..0b7144b9c8ea2d 100644 --- a/Libraries/TypeSafety/RCTConvertHelpers.h +++ b/Libraries/TypeSafety/RCTConvertHelpers.h @@ -49,6 +49,7 @@ NSArray *RCTConvertOptionalVecToArray(const folly::Optional &vec) bool RCTBridgingToBool(id value); folly::Optional RCTBridgingToOptionalBool(id value); NSString *RCTBridgingToString(id value); +NSString *RCTBridgingToOptionalString(id value); folly::Optional RCTBridgingToOptionalDouble(id value); double RCTBridgingToDouble(id value); NSArray *RCTBridgingToArray(id value); diff --git a/Libraries/TypeSafety/RCTConvertHelpers.mm b/Libraries/TypeSafety/RCTConvertHelpers.mm index 69fb3e4a3de4f4..cd79c41f6fece4 100644 --- a/Libraries/TypeSafety/RCTConvertHelpers.mm +++ b/Libraries/TypeSafety/RCTConvertHelpers.mm @@ -27,6 +27,12 @@ bool RCTBridgingToBool(id value) return [RCTConvert NSString:RCTNilIfNull(value)]; } +NSString *RCTBridgingToOptionalString(id value) +{ + return RCTBridgingToString(value); +} + + folly::Optional RCTBridgingToOptionalDouble(id value) { if (!RCTNilIfNull(value)) { diff --git a/Libraries/TypeSafety/RCTTypeSafety.podspec b/Libraries/TypeSafety/RCTTypeSafety.podspec index 1dd04a8c29a6e8..96d90e6949b1de 100644 --- a/Libraries/TypeSafety/RCTTypeSafety.podspec +++ b/Libraries/TypeSafety/RCTTypeSafety.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags s.source = source s.source_files = "**/*.{c,h,m,mm,cpp}" diff --git a/Libraries/Types/CodegenTypes.js b/Libraries/Types/CodegenTypes.js index 9e33919fdd845f..458cfe80ba88ba 100644 --- a/Libraries/Types/CodegenTypes.js +++ b/Libraries/Types/CodegenTypes.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow strict */ 'use strict'; @@ -28,6 +28,7 @@ export type DirectEventHandler< export type Double = number; export type Float = number; export type Int32 = number; +export type UnsafeObject = $FlowFixMe; // Object is forbidden in strict mode type DefaultTypes = number | boolean | string | $ReadOnlyArray; // Default handling, ignore the unused value diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index 6bf13e0aa7cded..906219cd75dde1 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.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-local + * @flow strict * @format */ diff --git a/Libraries/Utilities/Appearance.js b/Libraries/Utilities/Appearance.js index 314b3eaaad649c..09a385d88e70fc 100644 --- a/Libraries/Utilities/Appearance.js +++ b/Libraries/Utilities/Appearance.js @@ -20,10 +20,18 @@ import invariant from 'invariant'; import {isAsyncDebugging} from './DebugEnvironment'; type AppearanceListener = (preferences: AppearancePreferences) => void; -const eventEmitter = new EventEmitter(); +const eventEmitter = new EventEmitter<{ + change: [AppearancePreferences], +}>(); + +type NativeAppearanceEventDefinitions = { + appearanceChanged: [AppearancePreferences], +}; if (NativeAppearance) { - const nativeEventEmitter = new NativeEventEmitter(NativeAppearance); + const nativeEventEmitter = new NativeEventEmitter( + NativeAppearance, + ); nativeEventEmitter.addListener( 'appearanceChanged', (newAppearance: AppearancePreferences) => { diff --git a/Libraries/Utilities/BackHandler.android.js b/Libraries/Utilities/BackHandler.android.js index e762c1635f93f7..efb07ec5918ea6 100644 --- a/Libraries/Utilities/BackHandler.android.js +++ b/Libraries/Utilities/BackHandler.android.js @@ -35,10 +35,6 @@ RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() { * Android: Detect hardware back button presses, and programmatically invoke the default back button * functionality to exit the app if there are no listeners or if none of the listeners return true. * - * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented: - * programmatically disable menu button handling - * functionality to exit the app if there are no listeners or if none of the listeners return true.) - * * iOS: Not applicable. * * The event subscriptions are called in reverse order (i.e. last registered subscription first), @@ -82,8 +78,7 @@ const BackHandler: TBackHandler = { /** * Adds an event handler. Supported events: * - * - `hardwareBackPress`: Fires when the Android hardware back button is pressed or when the - * tvOS menu button is pressed. + * - `hardwareBackPress`: Fires when the Android hardware back button is pressed. */ addEventListener: function( eventName: BackPressEventName, diff --git a/Libraries/Utilities/BackHandler.ios.js b/Libraries/Utilities/BackHandler.ios.js index 1407a57e95ff0d..2e1e5c4cd2a7ac 100644 --- a/Libraries/Utilities/BackHandler.ios.js +++ b/Libraries/Utilities/BackHandler.ios.js @@ -4,52 +4,18 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict-local * @format + * @flow */ -// On Apple TV, this implements back navigation using the TV remote's menu button. -// On iOS, this just implements a stub. - 'use strict'; -const Platform = require('./Platform'); -const TVEventHandler = require('../Components/AppleTV/TVEventHandler'); +module.exports = require('../Components/UnimplementedViews/UnimplementedView'); type BackPressEventName = 'backPress' | 'hardwareBackPress'; function emptyFunction(): void {} -/** - * Detect hardware button presses for back navigation. - * - * Android: Detect hardware back button presses, and programmatically invoke the default back button - * functionality to exit the app if there are no listeners or if none of the listeners return true. - * - * tvOS: Detect presses of the menu button on the TV remote. (Still to be implemented: - * programmatically disable menu button handling - * functionality to exit the app if there are no listeners or if none of the listeners return true.) - * - * iOS: Not applicable. - * - * The event subscriptions are called in reverse order (i.e. last registered subscription first), - * and if one subscription returns true then subscriptions registered earlier will not be called. - * - * Example: - * - * ```javascript - * BackHandler.addEventListener('hardwareBackPress', function() { - * // this.onMainScreen and this.goBack are just examples, you need to use your own implementation here - * // Typically you would use the navigator here to go to the last state. - * - * if (!this.onMainScreen()) { - * this.goBack(); - * return true; - * } - * return false; - * }); - * ``` - */ type TBackHandler = {| +exitApp: () => void, +addEventListener: ( @@ -62,65 +28,14 @@ type TBackHandler = {| ) => void, |}; -let BackHandler: TBackHandler; - -if (Platform.isTV) { - const _tvEventHandler = new TVEventHandler(); - const _backPressSubscriptions = new Set(); - - _tvEventHandler.enable(this, function(cmp, evt) { - if (evt && evt.eventType === 'menu') { - let invokeDefault = true; - const subscriptions = Array.from( - _backPressSubscriptions.values(), - ).reverse(); - - for (let i = 0; i < subscriptions.length; ++i) { - if (subscriptions[i]()) { - invokeDefault = false; - break; - } - } - - if (invokeDefault) { - BackHandler.exitApp(); - } - } - }); - - BackHandler = { - exitApp: emptyFunction, - - addEventListener: function( - eventName: BackPressEventName, - handler: () => ?boolean, - ): {remove: () => void, ...} { - _backPressSubscriptions.add(handler); - return { - remove: () => BackHandler.removeEventListener(eventName, handler), - }; - }, - - removeEventListener: function( - eventName: BackPressEventName, - handler: () => ?boolean, - ): void { - _backPressSubscriptions.delete(handler); - }, - }; -} else { - BackHandler = { - exitApp: emptyFunction, - addEventListener(_eventName: BackPressEventName, _handler: () => ?boolean) { - return { - remove: emptyFunction, - }; - }, - removeEventListener( - _eventName: BackPressEventName, - _handler: () => ?boolean, - ) {}, - }; -} +let BackHandler: TBackHandler = { + exitApp: emptyFunction, + addEventListener(_eventName: BackPressEventName, _handler: Function) { + return { + remove: emptyFunction, + }; + }, + removeEventListener(_eventName: BackPressEventName, _handler: Function) {}, +}; module.exports = BackHandler; diff --git a/Libraries/Utilities/DebugEnvironment.js b/Libraries/Utilities/DebugEnvironment.js index c2b3e8ff57ef2c..3ec4eeaa491926 100644 --- a/Libraries/Utilities/DebugEnvironment.js +++ b/Libraries/Utilities/DebugEnvironment.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow strict */ 'use strict'; diff --git a/Libraries/Utilities/DevSettings.js b/Libraries/Utilities/DevSettings.js index 58494938ec6536..0a95bed8f70fcb 100644 --- a/Libraries/Utilities/DevSettings.js +++ b/Libraries/Utilities/DevSettings.js @@ -17,7 +17,12 @@ interface IDevSettings { onFastRefresh(): void; } -class DevSettings extends NativeEventEmitter implements IDevSettings { +type DevSettingsEventDefinitions = { + didPressMenuItem: [{title: string}], +}; + +class DevSettings extends NativeEventEmitter + implements IDevSettings { _menuItems: Map mixed>; constructor() { diff --git a/Libraries/Utilities/Dimensions.js b/Libraries/Utilities/Dimensions.js index b3e5822c401bb3..d07cdddd625b85 100644 --- a/Libraries/Utilities/Dimensions.js +++ b/Libraries/Utilities/Dimensions.js @@ -24,7 +24,9 @@ type DimensionsValue = { ... }; -const eventEmitter = new EventEmitter(); +const eventEmitter = new EventEmitter<{ + change: [DimensionsValue], +}>(); let dimensionsInitialized = false; let dimensions: DimensionsValue; diff --git a/Libraries/Utilities/GlobalPerformanceLogger.js b/Libraries/Utilities/GlobalPerformanceLogger.js index 32ca41728bc141..a186af3ecb7136 100644 --- a/Libraries/Utilities/GlobalPerformanceLogger.js +++ b/Libraries/Utilities/GlobalPerformanceLogger.js @@ -9,8 +9,8 @@ */ 'use strict'; -const createPerformanceLogger = require('./createPerformanceLogger'); +import createPerformanceLogger from './createPerformanceLogger'; import type {IPerformanceLogger} from './createPerformanceLogger'; /** diff --git a/Libraries/Utilities/PerformanceLoggerContext.js b/Libraries/Utilities/PerformanceLoggerContext.js index 5bc3560f0fe1b9..e32f6c249e731b 100644 --- a/Libraries/Utilities/PerformanceLoggerContext.js +++ b/Libraries/Utilities/PerformanceLoggerContext.js @@ -23,4 +23,7 @@ import type {IPerformanceLogger} from './createPerformanceLogger'; const PerformanceLoggerContext: React.Context = React.createContext( GlobalPerformanceLogger, ); +if (__DEV__) { + PerformanceLoggerContext.displayName = 'PerformanceLoggerContext'; +} module.exports = PerformanceLoggerContext; diff --git a/Libraries/Utilities/Platform.android.js b/Libraries/Utilities/Platform.android.js index ab3bc9b345c5b2..0ed8a36eaff97b 100644 --- a/Libraries/Utilities/Platform.android.js +++ b/Libraries/Utilities/Platform.android.js @@ -63,10 +63,13 @@ const Platform = { }, select: (spec: PlatformSelectSpec): A | N | D => 'android' in spec - ? spec.android + ? // $FlowFixMe[incompatible-return] + spec.android : 'native' in spec - ? spec.native - : spec.default, + ? // $FlowFixMe[incompatible-return] + spec.native + : // $FlowFixMe[incompatible-return] + spec.default, }; module.exports = Platform; diff --git a/Libraries/Utilities/Platform.ios.js b/Libraries/Utilities/Platform.ios.js index afb39c5aad8b06..fef93470ae1e08 100644 --- a/Libraries/Utilities/Platform.ios.js +++ b/Libraries/Utilities/Platform.ios.js @@ -68,6 +68,7 @@ const Platform = { return false; }, select: (spec: PlatformSelectSpec): D | N | I => + // $FlowFixMe[incompatible-return] 'ios' in spec ? spec.ios : 'native' in spec ? spec.native : spec.default, }; diff --git a/Libraries/Utilities/__tests__/PerformanceLogger-test.js b/Libraries/Utilities/__tests__/PerformanceLogger-test.js index 9af931852397ab..79981ad2671a7b 100644 --- a/Libraries/Utilities/__tests__/PerformanceLogger-test.js +++ b/Libraries/Utilities/__tests__/PerformanceLogger-test.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow strict-local */ 'use strict'; @@ -14,30 +15,78 @@ import createPerformanceLogger from '../createPerformanceLogger'; import type {IPerformanceLogger} from '../createPerformanceLogger'; const TIMESPAN_1 = ''; -const TIMESPAN_2 = ''; -const TIMESPAN_2_DURATION = 123; const EXTRA_KEY = ''; const EXTRA_VALUE = ''; const EXTRA_VALUE_2 = ''; const POINT = ''; const POINT_TIMESTAMP = 99; const POINT_TIMESTAMP_2 = 999; +const POINT_ANNOTATION_1 = {extra: 'value1'}; +const POINT_ANNOTATION_2 = {extra: 'value2'}; describe('PerformanceLogger', () => { beforeEach(() => { GlobalPerformanceLogger.clear(); }); + describe('close() ', () => { + let perfLogger; + beforeEach(() => { + perfLogger = createPerformanceLogger(); + }); + + it('does not markPoint', () => { + perfLogger.close(); + perfLogger.markPoint(POINT, POINT_TIMESTAMP); + expect(perfLogger.getPoints()).toEqual({}); + }); + it('does not startTimespan', () => { + perfLogger.close(); + perfLogger.startTimespan(TIMESPAN_1); + expect(perfLogger.getTimespans()).toEqual({}); + }); + it('does not setExtra', () => { + perfLogger.close(); + perfLogger.setExtra('extra', 'an extra value'); + expect(perfLogger.getTimespans()).toEqual({}); + }); - it('starts & stops and adds a timespan', () => { + it('does not stopTimespan', () => { + perfLogger.startTimespan(TIMESPAN_1); + perfLogger.close(); + let timespan = perfLogger.getTimespans()[TIMESPAN_1]; + expect(timespan?.endTime).toBeUndefined(); + expect(timespan?.totalTime).toBeUndefined(); + perfLogger.stopTimespan(TIMESPAN_1); + timespan = perfLogger.getTimespans()[TIMESPAN_1]; + expect(timespan?.endTime).toBeUndefined(); + expect(timespan?.totalTime).toBeUndefined(); + }); + }); + + it('starts & stops a timespan', () => { let perfLogger = createPerformanceLogger(); perfLogger.startTimespan(TIMESPAN_1); perfLogger.stopTimespan(TIMESPAN_1); - perfLogger.addTimeAnnotation(TIMESPAN_2, TIMESPAN_2_DURATION); expect(perfLogger.hasTimespan(TIMESPAN_1)).toBe(true); - expect(perfLogger.hasTimespan(TIMESPAN_2)).toBe(true); - expect(perfLogger.getTimespans()[TIMESPAN_2].totalTime).toBe( - TIMESPAN_2_DURATION, - ); + expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual({ + startTime: expect.any(Number), + endTime: expect.any(Number), + totalTime: expect.any(Number), + }); + }); + + it('starts & stops a timespan with custom timestamps', () => { + let perfLogger = createPerformanceLogger(); + const startTime = 25; + const endTime = 35; + perfLogger.startTimespan(TIMESPAN_1, startTime); + perfLogger.stopTimespan(TIMESPAN_1, endTime); + expect(perfLogger.hasTimespan(TIMESPAN_1)).toBe(true); + expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual({ + startTime, + endTime, + totalTime: expect.any(Number), + }); }); it('does not override a timespan', () => { @@ -46,18 +95,14 @@ describe('PerformanceLogger', () => { let old = perfLogger.getTimespans()[TIMESPAN_1]; perfLogger.startTimespan(TIMESPAN_1); expect(perfLogger.getTimespans()[TIMESPAN_1]).toBe(old); - perfLogger.addTimeAnnotation(TIMESPAN_1, 1); - expect(perfLogger.getTimespans()[TIMESPAN_1]).toBe(old); }); it('adds a timespan with start and end timestamps', () => { let perfLogger = createPerformanceLogger(); const startTime = 0; const endTime = 100; - const description = 'description'; - perfLogger.addTimespan(TIMESPAN_1, startTime, endTime, description); + perfLogger.addTimespan(TIMESPAN_1, startTime, endTime); expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual({ - description, startTime, endTime, totalTime: endTime - startTime, @@ -69,7 +114,7 @@ describe('PerformanceLogger', () => { perfLogger.startTimespan(TIMESPAN_1); perfLogger.stopTimespan(TIMESPAN_1); const existing = perfLogger.getTimespans()[TIMESPAN_1]; - perfLogger.addTimespan(TIMESPAN_1, 0, 100, 'overriding'); + perfLogger.addTimespan(TIMESPAN_1, 0, 100); expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual(existing); }); @@ -172,4 +217,98 @@ describe('PerformanceLogger', () => { checkLogger(localPerformanceLogger2, true); checkLogger(GlobalPerformanceLogger, true); }); + + it('records extras for a timespan', () => { + let perfLogger = createPerformanceLogger(); + perfLogger.startTimespan(TIMESPAN_1, undefined, POINT_ANNOTATION_1); + perfLogger.stopTimespan(TIMESPAN_1, undefined, POINT_ANNOTATION_2); + expect(perfLogger.getTimespans()[TIMESPAN_1]?.startExtras).toEqual( + POINT_ANNOTATION_1, + ); + expect(perfLogger.getTimespans()[TIMESPAN_1]?.endExtras).toEqual( + POINT_ANNOTATION_2, + ); + }); + + it('records extras for a point', () => { + let perfLogger = createPerformanceLogger(); + perfLogger.markPoint(POINT, POINT_TIMESTAMP, POINT_ANNOTATION_1); + + expect(Object.keys(perfLogger.getPointExtras())).toEqual([POINT]); + expect(perfLogger.getPointExtras()[POINT]).toEqual(POINT_ANNOTATION_1); + }); + + it('should allow extended logger to stopTimespan', () => { + const loggerA = createPerformanceLogger(); + loggerA.startTimespan('loggerA_timespan'); + const loggerB = createPerformanceLogger(); + loggerB.append(loggerA); + loggerB.stopTimespan('loggerA_timespan'); + const timespan = loggerB.getTimespans().loggerA_timespan; + expect(timespan?.startTime).not.toBeUndefined(); + expect(timespan?.endTime).not.toBeUndefined(); + expect(timespan?.totalTime).not.toBeUndefined(); + expect(loggerA.isClosed()).toBe(false); + }); + + it('should append logger', () => { + const loggerA = createPerformanceLogger(); + loggerA.addTimespan('loggerA_timespan1', 0, 10); + loggerA.addTimespan( + 'loggerA_timespan2', + 2, + 8, + {loggerA_timespan2_start: 100}, + {loggerA_timespan2_end: 200}, + ); + loggerA.markPoint('loggerA_point', 5, {loggerA_pointExtra: true}); + loggerA.setExtra('loggerA_extra', true); + + const loggerB = createPerformanceLogger(); + loggerB.append(loggerA); + loggerB.addTimespan('loggerB_timespan', 0, 10); + loggerB.markPoint('loggerB_point', 3); + + expect(loggerA.isClosed()).toBe(false); + + expect(loggerB.getTimespans()).toEqual({ + loggerA_timespan1: { + endExtras: undefined, + endTime: 10, + startExtras: undefined, + startTime: 0, + totalTime: 10, + }, + loggerA_timespan2: { + endExtras: { + loggerA_timespan2_end: 200, + }, + endTime: 8, + startExtras: { + loggerA_timespan2_start: 100, + }, + startTime: 2, + totalTime: 6, + }, + loggerB_timespan: { + endExtras: undefined, + endTime: 10, + startExtras: undefined, + startTime: 0, + totalTime: 10, + }, + }); + expect(loggerB.getPoints()).toEqual({ + loggerA_point: 5, + loggerB_point: 3, + }); + expect(loggerB.getPointExtras()).toEqual({ + loggerA_point: { + loggerA_pointExtra: true, + }, + }); + expect(loggerB.getExtras()).toEqual({ + loggerA_extra: true, + }); + }); }); diff --git a/Libraries/Utilities/__tests__/verifyComponentAttributeEquivalence-test.js b/Libraries/Utilities/__tests__/verifyComponentAttributeEquivalence-test.js index 58acd17758cab8..43a507335d39cb 100644 --- a/Libraries/Utilities/__tests__/verifyComponentAttributeEquivalence-test.js +++ b/Libraries/Utilities/__tests__/verifyComponentAttributeEquivalence-test.js @@ -10,12 +10,13 @@ 'use strict'; -const getNativeComponentAttributes = require('../../ReactNative/getNativeComponentAttributes'); +jest.dontMock('../verifyComponentAttributeEquivalence'); + const verifyComponentAttributeEquivalence = require('../verifyComponentAttributeEquivalence') .default; -jest.dontMock('../verifyComponentAttributeEquivalence'); -jest.mock('../../ReactNative/getNativeComponentAttributes', () => () => ({ +const TestComponentNativeViewConfig = { + uiViewClassName: 'TestComponent', NativeProps: { value: 'BOOL', }, @@ -40,62 +41,63 @@ jest.mock('../../ReactNative/getNativeComponentAttributes', () => () => ({ }, transform: 'CATransform3D', }, -})); - -beforeEach(() => { - global.__DEV__ = true; - console.error = jest.fn(); - jest.resetModules(); -}); +}; describe('verifyComponentAttributeEquivalence', () => { - test('should not verify in prod', () => { - global.__DEV__ = false; - verifyComponentAttributeEquivalence('TestComponent', {}); + beforeEach(() => { + global.__DEV__ = true; + console.error = jest.fn(); + jest.resetModules(); }); - test('should not error with native config that is a subset of the given config', () => { - const configWithAdditionalProperties = getNativeComponentAttributes( - 'TestComponent', - ); + it('should not verify in prod', () => { + global.__DEV__ = false; + verifyComponentAttributeEquivalence(TestComponentNativeViewConfig, {}); + }); - configWithAdditionalProperties.bubblingEventTypes.topFocus = { - phasedRegistrationNames: { - bubbled: 'onFocus', - captured: 'onFocusCapture', + it('should not error with native config that is a subset of the given config', () => { + const configWithAdditionalProperties = { + ...TestComponentNativeViewConfig, + bubblingEventTypes: { + ...TestComponentNativeViewConfig.bubblingEventTypes, + topFocus: { + phasedRegistrationNames: { + bubbled: 'onFocus', + captured: 'onFocusCapture', + }, + }, + }, + directEventTypes: { + ...TestComponentNativeViewConfig.directEventTypes, + topSlidingComplete: { + registrationName: 'onSlidingComplete', + }, + }, + validAttributes: { + ...TestComponentNativeViewConfig.validAttributes, + active: true, }, }; - - configWithAdditionalProperties.directEventTypes.topSlidingComplete = { - registrationName: 'onSlidingComplete', - }; - - configWithAdditionalProperties.validAttributes.active = true; - - verifyComponentAttributeEquivalence( - 'TestComponent', - configWithAdditionalProperties, - ); verifyComponentAttributeEquivalence( - 'TestComponent', + TestComponentNativeViewConfig, configWithAdditionalProperties, ); expect(console.error).not.toBeCalled(); }); - test('should error if given config is missing native config properties', () => { - verifyComponentAttributeEquivalence('TestComponent', {}); + it('should error if given config is missing native config properties', () => { + verifyComponentAttributeEquivalence(TestComponentNativeViewConfig, {}); expect(console.error).toBeCalledTimes(3); expect(console.error).toBeCalledWith( - 'TestComponent generated view config for directEventTypes does not match native, missing: topAccessibilityAction', + "'TestComponent' has a view config that does not match native. 'validAttributes' is missing: borderColor, style", ); expect(console.error).toBeCalledWith( - 'TestComponent generated view config for bubblingEventTypes does not match native, missing: topChange', + "'TestComponent' has a view config that does not match native. 'bubblingEventTypes' is missing: topChange", ); expect(console.error).toBeCalledWith( - 'TestComponent generated view config for validAttributes does not match native, missing: borderColor style', + "'TestComponent' has a view config that does not match native. 'directEventTypes' is missing: topAccessibilityAction", ); }); }); diff --git a/Libraries/Utilities/createPerformanceLogger.js b/Libraries/Utilities/createPerformanceLogger.js index c44d649651df85..66c2183186cf60 100644 --- a/Libraries/Utilities/createPerformanceLogger.js +++ b/Libraries/Utilities/createPerformanceLogger.js @@ -13,253 +13,319 @@ const Systrace = require('../Performance/Systrace'); const infoLog = require('./infoLog'); -const performanceNow = - global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance); -type Timespan = { - description?: string, - totalTime?: number, - startTime?: number, +export type Timespan = { + startTime: number, endTime?: number, - ... + totalTime?: number, + startExtras?: Extras, + endExtras?: Extras, }; +// Extra values should be serializable primitives +export type ExtraValue = number | string | boolean; + +export type Extras = {[key: string]: ExtraValue}; + export interface IPerformanceLogger { - addTimeAnnotation( - key: string, - durationInMs: number, - description?: string, - ): void; addTimespan( key: string, startTime: number, endTime: number, - description?: string, + startExtras?: Extras, + endExtras?: Extras, ): void; - startTimespan(key: string, description?: string): void; - stopTimespan(key: string, options?: {update?: boolean}): void; + append(logger: IPerformanceLogger): void; clear(): void; clearCompleted(): void; + close(): void; currentTimestamp(): number; - getTimespans(): {[key: string]: Timespan, ...}; + getExtras(): $ReadOnly<{[key: string]: ?ExtraValue, ...}>; + getPoints(): $ReadOnly<{[key: string]: ?number, ...}>; + getPointExtras(): $ReadOnly<{[key: string]: ?Extras, ...}>; + getTimespans(): $ReadOnly<{[key: string]: ?Timespan, ...}>; hasTimespan(key: string): boolean; - setExtra(key: string, value: mixed): void; - getExtras(): {[key: string]: mixed, ...}; - removeExtra(key: string): ?mixed; - markPoint(key: string, timestamp?: number): void; - getPoints(): {[key: string]: number, ...}; + isClosed(): boolean; logEverything(): void; + markPoint(key: string, timestamp?: number, extras?: Extras): void; + removeExtra(key: string): ?ExtraValue; + setExtra(key: string, value: ExtraValue): void; + startTimespan(key: string, timestamp?: number, extras?: Extras): void; + stopTimespan(key: string, timestamp?: number, extras?: Extras): void; } const _cookies: {[key: string]: number, ...} = {}; const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally committing `true`; -/** - * This function creates performance loggers that can be used to collect and log - * various performance data such as timespans, points and extras. - * The loggers need to have minimal overhead since they're used in production. - */ -function createPerformanceLogger(): IPerformanceLogger { - const result: IPerformanceLogger & { - _timespans: {[key: string]: Timespan, ...}, - _extras: {[key: string]: mixed, ...}, - _points: {[key: string]: number, ...}, - ... - } = { - _timespans: {}, - _extras: {}, - _points: {}, - - addTimeAnnotation(key: string, durationInMs: number, description?: string) { - if (this._timespans[key]) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to add a timespan that already exists ', - key, - ); - } - return; +export const getCurrentTimestamp: () => number = + global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance); + +class PerformanceLogger implements IPerformanceLogger { + _timespans: {[key: string]: ?Timespan} = {}; + _extras: {[key: string]: ?ExtraValue} = {}; + _points: {[key: string]: ?number} = {}; + _pointExtras: {[key: string]: ?Extras, ...} = {}; + _closed: boolean = false; + + addTimespan( + key: string, + startTime: number, + endTime: number, + startExtras?: Extras, + endExtras?: Extras, + ) { + if (this._closed) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog('PerformanceLogger: addTimespan - has closed ignoring: ', key); } + return; + } + if (this._timespans[key]) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to add a timespan that already exists ', + key, + ); + } + return; + } - this._timespans[key] = { - description: description, - totalTime: durationInMs, - }; - }, - - addTimespan( - key: string, - startTime: number, - endTime: number, - description?: string, - ) { - if (this._timespans[key]) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to add a timespan that already exists ', - key, - ); - } - return; + this._timespans[key] = { + startTime, + endTime, + totalTime: endTime - (startTime || 0), + startExtras, + endExtras, + }; + } + + append(performanceLogger: IPerformanceLogger) { + this._timespans = { + ...performanceLogger.getTimespans(), + ...this._timespans, + }; + this._extras = {...performanceLogger.getExtras(), ...this._extras}; + this._points = {...performanceLogger.getPoints(), ...this._points}; + this._pointExtras = { + ...performanceLogger.getPointExtras(), + ...this._pointExtras, + }; + } + + clear() { + this._timespans = {}; + this._extras = {}; + this._points = {}; + if (PRINT_TO_CONSOLE) { + infoLog('PerformanceLogger.js', 'clear'); + } + } + + clearCompleted() { + for (const key in this._timespans) { + if (this._timespans[key]?.totalTime != null) { + delete this._timespans[key]; } + } + this._extras = {}; + this._points = {}; + if (PRINT_TO_CONSOLE) { + infoLog('PerformanceLogger.js', 'clearCompleted'); + } + } + + close() { + this._closed = true; + } + + currentTimestamp() { + return getCurrentTimestamp(); + } + + getExtras() { + return this._extras; + } + + getPoints() { + return this._points; + } + + getPointExtras() { + return this._pointExtras; + } + + getTimespans() { + return this._timespans; + } - this._timespans[key] = { - description, - startTime, - endTime, - totalTime: endTime - (startTime || 0), - }; - }, - - startTimespan(key: string, description?: string) { - if (this._timespans[key]) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to start a timespan that already exists ', - key, - ); + hasTimespan(key: string) { + return !!this._timespans[key]; + } + + isClosed() { + return this._closed; + } + + logEverything() { + if (PRINT_TO_CONSOLE) { + // log timespans + for (const key in this._timespans) { + if (this._timespans[key]?.totalTime != null) { + infoLog(key + ': ' + this._timespans[key].totalTime + 'ms'); } - return; } - this._timespans[key] = { - description: description, - startTime: performanceNow(), - }; - _cookies[key] = Systrace.beginAsyncEvent(key); - if (PRINT_TO_CONSOLE) { - infoLog('PerformanceLogger.js', 'start: ' + key); - } - }, - - stopTimespan(key: string, options?: {update?: boolean}) { - const timespan = this._timespans[key]; - if (!timespan || !timespan.startTime) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to end a timespan that has not started ', - key, - ); + // log extras + infoLog(this._extras); + + // log points + for (const key in this._points) { + if (this._points[key] != null) { + infoLog(key + ': ' + this._points[key] + 'ms'); } - return; } - if (timespan.endTime && !options?.update) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to end a timespan that has already ended ', - key, - ); - } - return; + } + } + + markPoint( + key: string, + timestamp?: number = getCurrentTimestamp(), + extras?: Extras, + ) { + if (this._closed) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog('PerformanceLogger: markPoint - has closed ignoring: ', key); + } + return; + } + if (this._points[key] != null) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to mark a point that has been already logged ', + key, + ); } + return; + } + this._points[key] = timestamp; + if (extras) { + this._pointExtras[key] = extras; + } + } - timespan.endTime = performanceNow(); - timespan.totalTime = timespan.endTime - (timespan.startTime || 0); - if (PRINT_TO_CONSOLE) { - infoLog('PerformanceLogger.js', 'end: ' + key); + removeExtra(key: string): ?ExtraValue { + const value = this._extras[key]; + delete this._extras[key]; + return value; + } + + setExtra(key: string, value: ExtraValue) { + if (this._closed) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog('PerformanceLogger: setExtra - has closed ignoring: ', key); } + return; + } - if (_cookies[key] != null) { - Systrace.endAsyncEvent(key, _cookies[key]); - delete _cookies[key]; + if (this._extras.hasOwnProperty(key)) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to set an extra that already exists ', + {key, currentValue: this._extras[key], attemptedValue: value}, + ); } - }, - - clear() { - this._timespans = {}; - this._extras = {}; - this._points = {}; - if (PRINT_TO_CONSOLE) { - infoLog('PerformanceLogger.js', 'clear'); + return; + } + this._extras[key] = value; + } + + startTimespan( + key: string, + timestamp?: number = getCurrentTimestamp(), + extras?: Extras, + ) { + if (this._closed) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: startTimespan - has closed ignoring: ', + key, + ); } - }, + return; + } - clearCompleted() { - for (const key in this._timespans) { - if (this._timespans[key].totalTime) { - delete this._timespans[key]; - } + if (this._timespans[key]) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to start a timespan that already exists ', + key, + ); } - this._extras = {}; - this._points = {}; - if (PRINT_TO_CONSOLE) { - infoLog('PerformanceLogger.js', 'clearCompleted'); + return; + } + + this._timespans[key] = { + startTime: timestamp, + startExtras: extras, + }; + _cookies[key] = Systrace.beginAsyncEvent(key); + if (PRINT_TO_CONSOLE) { + infoLog('PerformanceLogger.js', 'start: ' + key); + } + } + + stopTimespan( + key: string, + timestamp?: number = getCurrentTimestamp(), + extras?: Extras, + ) { + if (this._closed) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog('PerformanceLogger: stopTimespan - has closed ignoring: ', key); } - }, - - currentTimestamp() { - return performanceNow(); - }, - - getTimespans() { - return this._timespans; - }, - - hasTimespan(key: string) { - return !!this._timespans[key]; - }, - - setExtra(key: string, value: mixed) { - if (this._extras[key]) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to set an extra that already exists ', - {key, currentValue: this._extras[key], attemptedValue: value}, - ); - } - return; + return; + } + + const timespan = this._timespans[key]; + if (!timespan || timespan.startTime == null) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to end a timespan that has not started ', + key, + ); } - this._extras[key] = value; - }, - - getExtras() { - return this._extras; - }, - - removeExtra(key: string): ?mixed { - const value = this._extras[key]; - delete this._extras[key]; - return value; - }, - - markPoint(key: string, timestamp?: number) { - if (this._points[key]) { - if (PRINT_TO_CONSOLE && __DEV__) { - infoLog( - 'PerformanceLogger: Attempting to mark a point that has been already logged ', - key, - ); - } - return; + return; + } + if (timespan.endTime != null) { + if (PRINT_TO_CONSOLE && __DEV__) { + infoLog( + 'PerformanceLogger: Attempting to end a timespan that has already ended ', + key, + ); } - this._points[key] = timestamp ?? performanceNow(); - }, - - getPoints() { - return this._points; - }, - - logEverything() { - if (PRINT_TO_CONSOLE) { - // log timespans - for (const key in this._timespans) { - if (this._timespans[key].totalTime) { - infoLog(key + ': ' + this._timespans[key].totalTime + 'ms'); - } - } + return; + } - // log extras - infoLog(this._extras); + timespan.endExtras = extras; + timespan.endTime = timestamp; + timespan.totalTime = timespan.endTime - (timespan.startTime || 0); + if (PRINT_TO_CONSOLE) { + infoLog('PerformanceLogger.js', 'end: ' + key); + } - // log points - for (const key in this._points) { - infoLog(key + ': ' + this._points[key] + 'ms'); - } - } - }, - }; - return result; + if (_cookies[key] != null) { + Systrace.endAsyncEvent(key, _cookies[key]); + delete _cookies[key]; + } + } } -module.exports = createPerformanceLogger; +/** + * This function creates performance loggers that can be used to collect and log + * various performance data such as timespans, points and extras. + * The loggers need to have minimal overhead since they're used in production. + */ +export default function createPerformanceLogger(): IPerformanceLogger { + return new PerformanceLogger(); +} diff --git a/Libraries/Utilities/deprecatedPropType.js b/Libraries/Utilities/deprecatedPropType.js index 480cf4cbeda6f6..4fc73c836fe832 100644 --- a/Libraries/Utilities/deprecatedPropType.js +++ b/Libraries/Utilities/deprecatedPropType.js @@ -10,7 +10,7 @@ 'use strict'; -const UIManager = require('../ReactNative/UIManager'); +import UIManager from '../ReactNative/UIManager'; /** * Adds a deprecation warning when the prop is used. @@ -23,7 +23,7 @@ function deprecatedPropType( // Don't warn for native components. if ( !global.RN$Bridgeless && - !UIManager.getViewManagerConfig(componentName) && + UIManager.hasViewManagerConfig(componentName) && props[propName] !== undefined ) { console.warn( diff --git a/Libraries/Utilities/registerGeneratedViewConfig.js b/Libraries/Utilities/registerGeneratedViewConfig.js index 947b3b06642b72..cb8449590a46d8 100644 --- a/Libraries/Utilities/registerGeneratedViewConfig.js +++ b/Libraries/Utilities/registerGeneratedViewConfig.js @@ -10,73 +10,26 @@ 'use strict'; -const ReactNativeViewConfigRegistry = require('../Renderer/shims/ReactNativeViewConfigRegistry'); -const ReactNativeViewViewConfig = require('../Components/View/ReactNativeViewViewConfig'); +import {createViewConfig} from '../NativeComponent/ViewConfig'; +import {type PartialViewConfig} from '../Renderer/shims/ReactNativeTypes'; +import ReactNativeViewConfigRegistry from '../Renderer/shims/ReactNativeViewConfigRegistry'; +import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; import verifyComponentAttributeEquivalence from './verifyComponentAttributeEquivalence'; -export type GeneratedViewConfig = { - uiViewClassName: string, - bubblingEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| - phasedRegistrationNames: $ReadOnly<{| - captured: string, - bubbled: string, - |}>, - |}>, - ..., - }>, - directEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| - registrationName: string, - |}>, - ..., - }>, - validAttributes?: { - [propName: string]: - | true - | $ReadOnly<{| - diff?: (arg1: any, arg2: any) => boolean, - process?: (arg1: any) => any, - |}>, - ..., - }, - ... -}; - function registerGeneratedViewConfig( componentName: string, - viewConfig: GeneratedViewConfig, + partialViewConfig: PartialViewConfig, ) { - const mergedViewConfig = { - uiViewClassName: componentName, - Commands: {}, - /* $FlowFixMe(>=0.122.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.122.0 was deployed. To see the error, delete - * this comment and run Flow. */ - bubblingEventTypes: { - ...ReactNativeViewViewConfig.bubblingEventTypes, - ...(viewConfig.bubblingEventTypes || {}), - }, - /* $FlowFixMe(>=0.122.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.122.0 was deployed. To see the error, delete - * this comment and run Flow. */ - directEventTypes: { - ...ReactNativeViewViewConfig.directEventTypes, - ...(viewConfig.directEventTypes || {}), - }, - /* $FlowFixMe(>=0.122.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.122.0 was deployed. To see the error, delete - * this comment and run Flow. */ - validAttributes: { - ...ReactNativeViewViewConfig.validAttributes, - ...(viewConfig.validAttributes || {}), - }, - }; + const staticViewConfig = createViewConfig(partialViewConfig); ReactNativeViewConfigRegistry.register(componentName, () => { - verifyComponentAttributeEquivalence(componentName, mergedViewConfig); + if (!global.RN$Bridgeless) { + const nativeViewConfig = getNativeComponentAttributes(componentName); + + verifyComponentAttributeEquivalence(nativeViewConfig, staticViewConfig); + } - return mergedViewConfig; + return staticViewConfig; }); } diff --git a/Libraries/Utilities/verifyComponentAttributeEquivalence.js b/Libraries/Utilities/verifyComponentAttributeEquivalence.js index 10dbe98dd0b4a1..acd459c1e12650 100644 --- a/Libraries/Utilities/verifyComponentAttributeEquivalence.js +++ b/Libraries/Utilities/verifyComponentAttributeEquivalence.js @@ -10,12 +10,11 @@ 'use strict'; -const getNativeComponentAttributes = require('../ReactNative/getNativeComponentAttributes'); - import ReactNativeViewViewConfig from '../Components/View/ReactNativeViewViewConfig'; -import type {ReactNativeBaseComponentViewConfig} from '../Renderer/shims/ReactNativeTypes'; +import {type ViewConfig} from '../Renderer/shims/ReactNativeTypes'; const IGNORED_KEYS = ['transform', 'hitSlop']; + /** * The purpose of this function is to validate that the view config that * native exposes for a given view manager is the same as the view config @@ -39,28 +38,27 @@ const IGNORED_KEYS = ['transform', 'hitSlop']; * single source of truth. I wonder if this message will still be here two * years from now... */ -function verifyComponentAttributeEquivalence( - componentName: string, - config: ReactNativeBaseComponentViewConfig<>, +export default function verifyComponentAttributeEquivalence( + nativeViewConfig: ViewConfig, + staticViewConfig: ViewConfig, ) { - if (!global.RN$Bridgeless) { - const nativeAttributes = getNativeComponentAttributes(componentName); - - ['validAttributes', 'bubblingEventTypes', 'directEventTypes'].forEach( - prop => { - const diffKeys = Object.keys( - lefthandObjectDiff(nativeAttributes[prop], config[prop]), - ); - - if (diffKeys.length) { - console.error( - `${componentName} generated view config for ${prop} does not match native, missing: ${diffKeys.join( - ' ', - )}`, - ); - } - }, + for (const prop of [ + 'validAttributes', + 'bubblingEventTypes', + 'directEventTypes', + ]) { + const diff = Object.keys( + lefthandObjectDiff(nativeViewConfig[prop], staticViewConfig[prop]), ); + + if (diff.length > 0) { + const name = + staticViewConfig.uiViewClassName ?? nativeViewConfig.uiViewClassName; + console.error( + `'${name}' has a view config that does not match native. ` + + `'${prop}' is missing: ${diff.join(', ')}`, + ); + } } } @@ -103,7 +101,7 @@ export function lefthandObjectDiff(leftObj: Object, rightObj: Object): Object { } export function getConfigWithoutViewProps( - viewConfig: ReactNativeBaseComponentViewConfig<>, + viewConfig: ViewConfig, propName: string, ): {...} { if (!viewConfig[propName]) { @@ -130,5 +128,3 @@ export function stringifyViewConfig(viewConfig: any): string { 2, ); } - -export default verifyComponentAttributeEquivalence; diff --git a/Libraries/Vibration/React-RCTVibration.podspec b/Libraries/Vibration/React-RCTVibration.podspec index c08abe6407cc3a..8e5b16875bde6a 100644 --- a/Libraries/Vibration/React-RCTVibration.podspec +++ b/Libraries/Vibration/React-RCTVibration.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/vibration" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{m,mm}" diff --git a/Libraries/WebSocket/WebSocket.js b/Libraries/WebSocket/WebSocket.js index 65cfd09c52c335..fa2b8260eb7bc0 100644 --- a/Libraries/WebSocket/WebSocket.js +++ b/Libraries/WebSocket/WebSocket.js @@ -11,10 +11,11 @@ 'use strict'; import Blob from '../Blob/Blob'; +import type {BlobData} from '../Blob/BlobTypes'; import BlobManager from '../Blob/BlobManager'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import binaryToBase64 from '../Utilities/binaryToBase64'; -import {type EventSubscription} from '../vendor/emitter/EventEmitter'; +import type {EventSubscription} from '../vendor/emitter/EventEmitter'; import NativeWebSocketModule from './NativeWebSocketModule'; import WebSocketEvent from './WebSocketEvent'; import base64 from 'base64-js'; @@ -46,6 +47,17 @@ const WEBSOCKET_EVENTS = ['close', 'error', 'message', 'open']; let nextWebSocketId = 0; +type WebSocketEventDefinitions = { + websocketOpen: [{id: number, protocol: string}], + websocketClosed: [{id: number, code: number, reason: string}], + websocketMessage: [ + | {type: 'binary', id: number, data: string} + | {type: 'text', id: number, data: string} + | {type: 'blob', id: number, data: BlobData}, + ], + websocketFailed: [{id: number, message: string}], +}; + /** * Browser-compatible WebSockets implementation. * @@ -64,7 +76,7 @@ class WebSocket extends (EventTarget(...WEBSOCKET_EVENTS): any) { CLOSED: number = CLOSED; _socketId: number; - _eventEmitter: NativeEventEmitter; + _eventEmitter: NativeEventEmitter; _subscriptions: Array; _binaryType: ?BinaryType; @@ -85,6 +97,7 @@ class WebSocket extends (EventTarget(...WEBSOCKET_EVENTS): any) { options: ?{headers?: {origin?: string, ...}, ...}, ) { super(); + this.url = url; if (typeof protocols === 'string') { protocols = [protocols]; } diff --git a/Libraries/promiseRejectionTrackingOptions.js b/Libraries/promiseRejectionTrackingOptions.js new file mode 100644 index 00000000000000..7b30a9c66bb4bd --- /dev/null +++ b/Libraries/promiseRejectionTrackingOptions.js @@ -0,0 +1,54 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict + */ + +'use strict'; + +import typeof {enable} from 'promise/setimmediate/rejection-tracking'; + +type ExtractOptionsType =

((options?: ?P) => void) => P; + +let rejectionTrackingOptions: $Call = { + allRejections: true, + onUnhandled: (id, rejection = {}) => { + let message: string; + let stack: ?string; + + const stringValue = Object.prototype.toString.call(rejection); + if (stringValue === '[object Error]') { + message = Error.prototype.toString.call(rejection); + const error: Error = (rejection: $FlowFixMe); + stack = error.stack; + } else { + try { + message = require('pretty-format')(rejection); + } catch { + message = + typeof rejection === 'string' + ? rejection + : JSON.stringify((rejection: $FlowFixMe)); + } + } + + const warning = + `Possible Unhandled Promise Rejection (id: ${id}):\n` + + `${message ?? ''}\n` + + (stack == null ? '' : stack); + console.warn(warning); + }, + onHandled: id => { + const warning = + `Promise Rejection Handled (id: ${id})\n` + + 'This means you can ignore any previous messages of the form ' + + `"Possible Unhandled Promise Rejection (id: ${id}):"`; + console.warn(warning); + }, +}; + +export default rejectionTrackingOptions; diff --git a/Libraries/vendor/emitter/EventEmitter.js b/Libraries/vendor/emitter/EventEmitter.js index 3057ea4cb5642e..380aedabb35db1 100644 --- a/Libraries/vendor/emitter/EventEmitter.js +++ b/Libraries/vendor/emitter/EventEmitter.js @@ -4,13 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict-local + * @flow strict * @format */ 'use strict'; -// $FlowFixMe - EventEmitter Type Safety const EventEmitter = require('./_EventEmitter'); export default EventEmitter; diff --git a/Libraries/vendor/emitter/_EmitterSubscription.js b/Libraries/vendor/emitter/_EmitterSubscription.js index dc2c72efb85c15..e78af30b2e8cb7 100644 --- a/Libraries/vendor/emitter/_EmitterSubscription.js +++ b/Libraries/vendor/emitter/_EmitterSubscription.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict */ 'use strict'; @@ -17,11 +17,13 @@ import type EventSubscriptionVendor from './_EventSubscriptionVendor'; /** * EmitterSubscription represents a subscription with listener and context data. */ -class EmitterSubscription extends EventSubscription { - // $FlowFixMe[value-as-type] - emitter: EventEmitter; - listener: Function; - context: ?Object; +class EmitterSubscription< + EventDefinitions: {...}, + K: $Keys, +> extends EventSubscription { + emitter: EventEmitter; + listener: ?(...$ElementType) => mixed; + context: ?$FlowFixMe; /** * @param {EventEmitter} emitter - The event emitter that registered this @@ -34,11 +36,10 @@ class EmitterSubscription extends EventSubscription { * listener */ constructor( - // $FlowFixMe[value-as-type] - emitter: EventEmitter, - subscriber: EventSubscriptionVendor, - listener: Function, - context: ?Object, + emitter: EventEmitter, + subscriber: EventSubscriptionVendor, + listener: (...$ElementType) => mixed, + context: ?$FlowFixMe, ) { super(subscriber); this.emitter = emitter; @@ -52,7 +53,7 @@ class EmitterSubscription extends EventSubscription { * but deliberately not calling `super.remove()` as the responsibility * for removing the subscription lies with the EventEmitter. */ - remove() { + remove(): void { this.emitter.removeSubscription(this); } } diff --git a/Libraries/vendor/emitter/_EventEmitter.js b/Libraries/vendor/emitter/_EventEmitter.js index 150c2538916698..4786dacd283812 100644 --- a/Libraries/vendor/emitter/_EventEmitter.js +++ b/Libraries/vendor/emitter/_EventEmitter.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @noflow + * @flow strict * @typecheck */ @@ -18,6 +18,21 @@ import EventSubscriptionVendor from './_EventSubscriptionVendor'; const sparseFilterPredicate = () => true; +export interface IEventEmitter { + addListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription; + + removeAllListeners>(eventType: ?K): void; + + emit>( + eventType: K, + ...args: $ElementType + ): void; +} + /** * @class EventEmitter * @description @@ -31,8 +46,9 @@ const sparseFilterPredicate = () => true; * mechanism on top of which extra functionality can be composed. For example, a * more advanced emitter may use an EventHolder and EventFactory. */ -class EventEmitter { - _subscriber: EventSubscriptionVendor; +class EventEmitter + implements IEventEmitter { + _subscriber: EventSubscriptionVendor; /** * @constructor @@ -40,8 +56,9 @@ class EventEmitter { * @param {EventSubscriptionVendor} subscriber - Optional subscriber instance * to use. If omitted, a new subscriber will be created for the emitter. */ - constructor(subscriber: ?EventSubscriptionVendor) { - this._subscriber = subscriber || new EventSubscriptionVendor(); + constructor(subscriber: ?EventSubscriptionVendor) { + this._subscriber = + subscriber || new EventSubscriptionVendor(); } /** @@ -58,15 +75,16 @@ class EventEmitter { * @param {*} context - Optional context object to use when invoking the * listener */ - addListener( - eventType: string, - listener: Function, - context: ?Object, - ): EmitterSubscription { + addListener>( + eventType: K, + // FIXME: listeners should return void instead of mixed to prevent issues + listener: (...$ElementType) => mixed, + context: $FlowFixMe, + ): EmitterSubscription { return (this._subscriber.addSubscription( eventType, new EmitterSubscription(this, this._subscriber, listener, context), - ): any); + ): $FlowFixMe); } /** @@ -76,7 +94,7 @@ class EventEmitter { * @param {?string} eventType - Optional name of the event whose registered * listeners to remove */ - removeAllListeners(eventType: ?string) { + removeAllListeners>(eventType: ?K): void { this._subscriber.removeAllSubscriptions(eventType); } @@ -84,7 +102,9 @@ class EventEmitter { * Removes a specific subscription. Called by the `remove()` method of the * subscription itself to ensure any necessary cleanup is performed. */ - removeSubscription(subscription: EmitterSubscription) { + removeSubscription>( + subscription: EmitterSubscription, + ): void { invariant( subscription.emitter === this, 'Subscription does not belong to this emitter.', @@ -99,7 +119,7 @@ class EventEmitter { * @param {string} eventType - Name of the event to query * @returns {number} */ - listenerCount(eventType: string): number { + listenerCount>(eventType: K): number { const subscriptions = this._subscriber.getSubscriptionsForType(eventType); return subscriptions ? // We filter out missing entries because the array is sparse. @@ -124,7 +144,10 @@ class EventEmitter { * * emitter.emit('someEvent', 'abc'); // logs 'abc' */ - emit(eventType: string) { + emit>( + eventType: K, + ...args: $ElementType + ): void { const subscriptions = this._subscriber.getSubscriptionsForType(eventType); if (subscriptions) { for (let i = 0, l = subscriptions.length; i < l; i++) { @@ -132,10 +155,7 @@ class EventEmitter { // The subscription may have been removed during this event loop. if (subscription && subscription.listener) { - subscription.listener.apply( - subscription.context, - Array.prototype.slice.call(arguments, 1), - ); + subscription.listener.apply(subscription.context, args); } } } @@ -154,7 +174,11 @@ class EventEmitter { * }); // removes the listener if already registered * */ - removeListener(eventType: String, listener) { + removeListener>( + eventType: K, + // FIXME: listeners should return void instead of mixed to prevent issues + listener: (...$ElementType) => mixed, + ): void { const subscriptions = this._subscriber.getSubscriptionsForType(eventType); if (subscriptions) { for (let i = 0, l = subscriptions.length; i < l; i++) { diff --git a/Libraries/vendor/emitter/_EventSubscription.js b/Libraries/vendor/emitter/_EventSubscription.js index 54ec8f2f2ddc41..7a4243811e3e9e 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 strict-local + * @flow strict */ 'use strict'; @@ -16,23 +16,25 @@ import type EventSubscriptionVendor from './_EventSubscriptionVendor'; * EventSubscription represents a subscription to a particular event. It can * remove its own subscription. */ -class EventSubscription { - eventType: string; +class EventSubscription> { + eventType: K; key: number; - subscriber: EventSubscriptionVendor; + subscriber: EventSubscriptionVendor; + listener: ?(...$ElementType) => mixed; + context: ?$FlowFixMe; /** * @param {EventSubscriptionVendor} subscriber the subscriber that controls * this subscription. */ - constructor(subscriber: EventSubscriptionVendor) { + constructor(subscriber: EventSubscriptionVendor) { this.subscriber = subscriber; } /** * Removes this subscription from the subscriber that controls it. */ - remove() { + remove(): void { this.subscriber.removeSubscription(this); } } diff --git a/Libraries/vendor/emitter/_EventSubscriptionVendor.js b/Libraries/vendor/emitter/_EventSubscriptionVendor.js index 5ea0aa821e0360..ace97393e42537 100644 --- a/Libraries/vendor/emitter/_EventSubscriptionVendor.js +++ b/Libraries/vendor/emitter/_EventSubscriptionVendor.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict */ 'use strict'; @@ -18,13 +18,16 @@ import type EventSubscription from './_EventSubscription'; * EventSubscriptionVendor stores a set of EventSubscriptions that are * subscribed to a particular event type. */ -class EventSubscriptionVendor { - _subscriptionsForType: Object; - _currentSubscription: ?EventSubscription; +class EventSubscriptionVendor { + _subscriptionsForType: { + [type: $Keys]: Array< + EventSubscription, + >, + ..., + }; constructor() { this._subscriptionsForType = {}; - this._currentSubscription = null; } /** @@ -33,10 +36,10 @@ class EventSubscriptionVendor { * @param {string} eventType * @param {EventSubscription} subscription */ - addSubscription( - eventType: string, - subscription: EventSubscription, - ): EventSubscription { + addSubscription>( + eventType: K, + subscription: EventSubscription, + ): EventSubscription { invariant( subscription.subscriber === this, 'The subscriber of the subscription is incorrectly set.', @@ -57,8 +60,8 @@ class EventSubscriptionVendor { * @param {?string} eventType - Optional name of the event type whose * registered supscriptions to remove, if null remove all subscriptions. */ - removeAllSubscriptions(eventType: ?string) { - if (eventType === undefined) { + removeAllSubscriptions>(eventType: ?K): void { + if (eventType == null) { this._subscriptionsForType = {}; } else { delete this._subscriptionsForType[eventType]; @@ -71,7 +74,9 @@ class EventSubscriptionVendor { * * @param {object} subscription */ - removeSubscription(subscription: Object) { + removeSubscription>( + subscription: EventSubscription, + ): void { const eventType = subscription.eventType; const key = subscription.key; @@ -93,7 +98,9 @@ class EventSubscriptionVendor { * @param {string} eventType * @returns {?array} */ - getSubscriptionsForType(eventType: string): ?[EventSubscription] { + getSubscriptionsForType>( + eventType: K, + ): ?Array> { return this._subscriptionsForType[eventType]; } } diff --git a/Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js b/Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js new file mode 100644 index 00000000000000..3047f21ff10ea7 --- /dev/null +++ b/Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js @@ -0,0 +1,127 @@ +/** + * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + * + * @flow strict + * @format + */ + +'use strict'; + +import EventEmitter from '../EventEmitter'; + +type MyEvents = { + noArgsEvent: [], + stringEvent: [string], + numberEvent: [number], + anotherNumberEvent: [number], + objectAndBooleanEvent: [{prop: string}, boolean], +}; + +export function testBaseEventEmitterInstance() { + const emitter = new EventEmitter(); + + emitter.addListener('noArgsEvent', expectedUndefined => { + (expectedUndefined: void); + }); + + emitter.addListener('stringEvent', expectedString => { + (expectedString: string); + }); + + emitter.addListener('numberEvent', expectedNumber => { + (expectedNumber: number); + }); + + emitter.addListener('anotherNumberEvent', expectedNumber => { + (expectedNumber: number); + }); + + emitter.addListener( + 'objectAndBooleanEvent', + (expectedObject, expectedBoolean, unexpectedArg) => { + (expectedObject: {prop: string}); + (expectedBoolean: boolean); + (unexpectedArg: void); + }, + ); + + // $FlowExpectedError[prop-missing] + emitter.addListener('unexpectedEvent', () => {}); + + // $FlowExpectedError[incompatible-call] + emitter.addListener('noArgsEvent', (value: number) => {}); + + // $FlowExpectedError[incompatible-call] + emitter.addListener('numberEvent', (value: string) => {}); + + emitter.emit('noArgsEvent'); + emitter.emit('stringEvent', 'value'); + emitter.emit('numberEvent', 4); + emitter.emit('anotherNumberEvent', 4); + emitter.emit('objectAndBooleanEvent', {prop: 'value'}, true); +} + +export function testSubclass() { + // $FlowExpectedError[incompatible-type-arg] + class EmitterWithUndefinedDefinition extends EventEmitter {} + + // $FlowExpectedError[incompatible-type-arg] + class EmitterWithNumberDefinition extends EventEmitter {} + + class EmitterWithInvalidDefinitions extends EventEmitter<{ + foo: number, + }> {} + + const emitter = new EmitterWithInvalidDefinitions(); + // $FlowExpectedError[not-an-array] + // $FlowExpectedError[incompatible-call] + emitter.emit('foo'); + + class EmitterWithValidDefinitions extends EventEmitter {} +} + +export function testSubclassInstance() { + class MyEmitter extends EventEmitter {} + + const emitter = new MyEmitter(); + + emitter.addListener('noArgsEvent', expectedUndefined => { + (expectedUndefined: void); + }); + + emitter.addListener('stringEvent', expectedString => { + (expectedString: string); + }); + + emitter.addListener('numberEvent', expectedNumber => { + (expectedNumber: number); + }); + + emitter.addListener('anotherNumberEvent', expectedNumber => { + (expectedNumber: number); + }); + + emitter.addListener( + 'objectAndBooleanEvent', + (expectedObject, expectedBoolean, unexpectedArg) => { + (expectedObject: {prop: string}); + (expectedBoolean: boolean); + (unexpectedArg: void); + }, + ); + + // $FlowExpectedError[prop-missing] + emitter.addListener('unexpectedEvent', () => {}); + + // $FlowExpectedError[incompatible-call] + emitter.addListener('noArgsEvent', (value: number) => {}); + + // $FlowExpectedError[incompatible-call] + emitter.addListener('numberEvent', (value: string) => {}); + + emitter.emit('noArgsEvent'); + emitter.emit('stringEvent', 'value'); + emitter.emit('numberEvent', 4); + emitter.emit('anotherNumberEvent', 4); + emitter.emit('objectAndBooleanEvent', {prop: 'value'}, true); +} diff --git a/README.md b/README.md index 8a9d89887480a1..13b6140cceff90 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Current CircleCI build status. - Current npm package version. + Current npm package version. PRs welcome! @@ -36,7 +36,7 @@ · Contribute · - Community + Community · Support @@ -67,19 +67,19 @@ React Native is developed and supported by many companies and individual core co ## 📋 Requirements -React Native apps may target iOS 10.0 and Android 4.1 (API 16) or newer. You may use Windows, macOS, or Linux as your development operating system, though building and running iOS apps is limited to macOS. Tools like [Expo](https://expo.io) can be used to work around this. +React Native apps may target iOS 11.0 and Android 5.0 (API 21) or newer. You may use Windows, macOS, or Linux as your development operating system, though building and running iOS apps is limited to macOS. Tools like [Expo](https://expo.io) can be used to work around this. ## 🎉 Building your first React Native app -Follow the [Getting Started guide](https://reactnative.dev/docs/getting-started.html). The recommended way to install React Native depends on your project. Here you can find short guides for the most common scenarios: +Follow the [Getting Started guide](https://reactnative.dev/docs/getting-started). The recommended way to install React Native depends on your project. Here you can find short guides for the most common scenarios: - [Trying out React Native][hello-world] - [Creating a New Application][new-app] - [Adding React Native to an Existing Application][existing] [hello-world]: https://snack.expo.io/@hramos/hello,-world! -[new-app]: https://reactnative.dev/docs/getting-started.html -[existing]: https://reactnative.dev/docs/integration-with-existing-apps.html +[new-app]: https://reactnative.dev/docs/getting-started +[existing]: https://reactnative.dev/docs/integration-with-existing-apps ## 📖 Documentation @@ -89,7 +89,7 @@ The React Native documentation discusses components, APIs, and topics that are s The source for the React Native documentation and website is hosted on a separate repo, [**@facebook/react-native-website**][repo-website]. -[docs]: https://reactnative.dev/docs/getting-started.html +[docs]: https://reactnative.dev/docs/getting-started [r-docs]: https://reactjs.org/docs/getting-started.html [repo-website]: https://github.com/facebook/react-native-website diff --git a/React-Core.podspec b/React-Core.podspec index 7a004607739d7f..07f0ec398b3536 100644 --- a/React-Core.podspec +++ b/React-Core.podspec @@ -41,14 +41,14 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.source = source s.resource_bundle = { "AccessibilityResources" => ["React/AccessibilityResources/*.lproj"]} s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.header_dir = "React" s.framework = "JavaScriptCore" s.library = "stdc++" - s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/RCT-Folly\"" } + s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/RCT-Folly\"", "DEFINES_MODULE" => "YES" } s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\""} s.default_subspec = "Default" @@ -59,27 +59,9 @@ Pod::Spec.new do |s| "React/Fabric/**/*", "React/Tests/**/*", "React/Inspector/**/*" - ss.ios.exclude_files = "React/**/RCTTV*.*" - ss.tvos.exclude_files = "React/Modules/RCTClipboard*", - "React/Views/RCTDatePicker*", - "React/Views/RCTPicker*", - "React/Views/RCTRefreshControl*", - "React/Views/RCTSlider*", - "React/Views/RCTSwitch*", ss.private_header_files = "React/Cxx*/*.h" end - s.subspec "Hermes" do |ss| - ss.platforms = { :osx => "10.14" } - ss.source_files = "ReactCommon/hermes/executor/*.{cpp,h}", - "ReactCommon/hermes/inspector/*.{cpp,h}", - "ReactCommon/hermes/inspector/chrome/*.{cpp,h}", - "ReactCommon/hermes/inspector/detail/*.{cpp,h}" - ss.pod_target_xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } - ss.dependency "RCT-Folly/Futures" - ss.dependency "hermes", "~> 0.6.0" - end - s.subspec "DevSupport" do |ss| ss.source_files = "React/DevSupport/*.{h,mm,m}", "React/Inspector/*.{h,mm,m}" diff --git a/React.podspec b/React.podspec index da482ff0154c7e..3fbfdae511f85b 100644 --- a/React.podspec +++ b/React.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" s.cocoapods_version = ">= 1.2.0" diff --git a/React/AccessibilityResources/en.lproj/Localizable.strings b/React/AccessibilityResources/en.lproj/Localizable.strings index 866bd0d883862d..ee35fc3e5fe25d 100644 --- a/React/AccessibilityResources/en.lproj/Localizable.strings +++ b/React/AccessibilityResources/en.lproj/Localizable.strings @@ -14,7 +14,7 @@ "scrollbar"="scroll bar"; "spinbutton"="spin button"; "switch"="switch"; -"tab"="tab description"; +"tab"="tab"; "tablist"="tab list"; "timer"="timer"; "toolbar"="tool bar"; diff --git a/React/Base/RCTAssert.h b/React/Base/RCTAssert.h index 9f0e9af2dec37c..95b37cc785dbe0 100644 --- a/React/Base/RCTAssert.h +++ b/React/Base/RCTAssert.h @@ -154,13 +154,12 @@ RCT_EXTERN NSString *RCTFormatStackTrace(NSArray *> */ #if DEBUG -#define RCTAssertThread(thread, format...) \ - _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") RCTAssert( \ - [(id)thread isKindOfClass:[NSString class]] \ - ? [RCTCurrentThreadName() isEqualToString:(NSString *)thread] \ - : [(id)thread isKindOfClass:[NSThread class]] ? [NSThread currentThread] == (NSThread *)thread \ - : dispatch_get_current_queue() == (dispatch_queue_t)thread, \ - format); \ +#define RCTAssertThread(thread, format...) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") RCTAssert( \ + [(id)thread isKindOfClass:[NSString class]] ? [RCTCurrentThreadName() isEqualToString:(NSString *)thread] \ + : [(id)thread isKindOfClass:[NSThread class]] ? [NSThread currentThread] == (NSThread *)thread \ + : dispatch_get_current_queue() == (dispatch_queue_t)thread, \ + format); \ _Pragma("clang diagnostic pop") #else diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 5981e1faa0ae0a..36678d39629e4e 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -15,7 +15,6 @@ @class JSValue; @class RCTBridge; -@class RCTEventDispatcher; @class RCTPerformanceLogger; /** diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 8cca1a00b9d749..cee883f875d980 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -11,7 +11,6 @@ #import #import "RCTConvert.h" -#import "RCTEventDispatcher.h" #if RCT_ENABLE_INSPECTOR #import "RCTInspectorDevServerHelper.h" #endif diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 102f98194bd5f2..b8d3ea6ee71fc0 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -6,11 +6,14 @@ */ #import +#import #import @class RCTBridge; @protocol RCTBridgeMethod; +@class RCTModuleRegistry; +@class RCTViewRegistry; /** * The type of a block that is capable of sending a response to a bridged @@ -113,6 +116,25 @@ RCT_EXTERN_C_END @optional +/** + * A reference to the RCTModuleRegistry. Useful for modules that require access + * to other NativeModules. To implement this in your module, just add `@synthesize + * moduleRegistry = _moduleRegistry;`. If using Swift, add + * `@objc var moduleRegistry: RCTModuleRegistry!` to your module. + */ +@property (nonatomic, weak, readonly) RCTModuleRegistry *moduleRegistry; + +/** + * A reference to the RCTViewRegistry. Useful for modules that query UIViews, + * given a react tag. This API is deprecated, and only exists to help migrate + * NativeModules to Venice. + * + * To implement this in your module, just add `@synthesize + * viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;`. If using Swift, add + * `@objc var viewRegistry_DEPRECATED: RCTViewRegistry!` to your module. + */ +@property (nonatomic, weak, readonly) RCTViewRegistry *viewRegistry_DEPRECATED; + /** * A reference to the RCTBridge. Useful for modules that require access * to bridge features, such as sending events or making JS calls. This @@ -372,3 +394,26 @@ RCT_EXTERN_C_END * See RCTTurboModule.h for actual signature. */ @protocol RCTTurboModule; + +/** + * A class that allows NativeModules and TurboModules to look up one another. + */ +@interface RCTModuleRegistry : NSObject +- (void)setBridge:(RCTBridge *)bridge; +- (void)setTurboModuleRegistry:(id)turboModuleRegistry; + +- (id)moduleForName:(const char *)moduleName; +- (id)moduleForName:(const char *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; +@end + +typedef UIView * (^RCTBridgelessComponentViewProvider)(NSNumber *); + +/** + * A class that allows NativeModules to query for views, given React Tags. + */ +@interface RCTViewRegistry : NSObject +- (void)setBridge:(RCTBridge *)bridge; +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)bridgelessComponentViewProvider; + +- (UIView *)viewForReactTag:(NSNumber *)reactTag; +@end diff --git a/React/Base/RCTBundleURLProvider.mm b/React/Base/RCTBundleURLProvider.mm index d43e2a0e96954c..751afb8a7d8ca6 100644 --- a/React/Base/RCTBundleURLProvider.mm +++ b/React/Base/RCTBundleURLProvider.mm @@ -10,11 +10,6 @@ #import "RCTConvert.h" #import "RCTDefines.h" -#if __has_include("hermes.h") || __has_include() -#import -#define HAS_BYTECODE_VERSION -#endif - NSString *const RCTBundleURLProviderUpdatedNotification = @"RCTBundleURLProviderUpdatedNotification"; const NSUInteger kRCTBundleURLProviderDefaultPort = RCT_METRO_PORT; @@ -236,9 +231,8 @@ + (NSURL *)jsBundleURLForBundleRoot:(NSString *)bundleRoot runModule:(BOOL)runModule { NSString *path = [NSString stringWithFormat:@"/%@.bundle", bundleRoot]; -#ifdef HAS_BYTECODE_VERSION - NSString *runtimeBytecodeVersion = - [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", facebook::hermes::HermesRuntime::getBytecodeVersion()]; +#ifdef HERMES_BYTECODE_VERSION + NSString *runtimeBytecodeVersion = [NSString stringWithFormat:@"&runtimeBytecodeVersion=%u", HERMES_BYTECODE_VERSION]; #else NSString *runtimeBytecodeVersion = @""; #endif diff --git a/React/Base/RCTComponentEvent.h b/React/Base/RCTComponentEvent.h index cad756234b21e4..0467f8c50f3787 100644 --- a/React/Base/RCTComponentEvent.h +++ b/React/Base/RCTComponentEvent.h @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/React/Base/RCTConstants.h b/React/Base/RCTConstants.h index 64b3117e18adcc..9f2297a1ad440e 100644 --- a/React/Base/RCTConstants.h +++ b/React/Base/RCTConstants.h @@ -18,7 +18,19 @@ RCT_EXTERN BOOL RCTExperimentGetOnDemandViewMounting(void); RCT_EXTERN void RCTExperimentSetOnDemandViewMounting(BOOL value); /* - * Allows to some performance flags to report data synchronously right after the mounting transaction finishes. + * It's an experimental feature that improves performance of hit-testing. */ -RCT_EXTERN BOOL RCTExperimentGetSyncPerformanceFlag(void); -RCT_EXTERN void RCTExperimentSetSyncPerformanceFlag(BOOL value); +RCT_EXTERN BOOL RCTExperimentGetOptimizedHitTesting(void); +RCT_EXTERN void RCTExperimentSetOptimizedHitTesting(BOOL value); + +/* + * Preemptive View Allocation + */ +RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void); +RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value); + +/* + * Release resources when app enters background + */ +RCT_EXTERN BOOL RCTExperimentGetReleaseResourcesWhenBackgrounded(void); +RCT_EXTERN void RCTExperimentSetReleaseResourcesWhenBackgrounded(BOOL value); diff --git a/React/Base/RCTConstants.m b/React/Base/RCTConstants.m index cbc0c75e90f473..13128f54940188 100644 --- a/React/Base/RCTConstants.m +++ b/React/Base/RCTConstants.m @@ -10,6 +10,9 @@ NSString *const RCTUserInterfaceStyleDidChangeNotification = @"RCTUserInterfaceStyleDidChangeNotification"; NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey = @"traitCollection"; +/* + * On-demand view mounting + */ static BOOL RCTExperimentOnDemandViewMounting = NO; BOOL RCTExperimentGetOnDemandViewMounting() @@ -22,14 +25,47 @@ void RCTExperimentSetOnDemandViewMounting(BOOL value) RCTExperimentOnDemandViewMounting = value; } -static BOOL RCTExperimentSyncPerformanceFlag = NO; +/* + * Optimized hit-testing + */ +static BOOL RCTExperimentOptimizedHitTesting = NO; + +BOOL RCTExperimentGetOptimizedHitTesting() +{ + return RCTExperimentOptimizedHitTesting; +} + +void RCTExperimentSetOptimizedHitTesting(BOOL value) +{ + RCTExperimentOptimizedHitTesting = value; +} + +/* + * Preemptive View Allocation + */ +static BOOL RCTExperimentPreemptiveViewAllocationDisabled = NO; + +BOOL RCTExperimentGetPreemptiveViewAllocationDisabled() +{ + return RCTExperimentPreemptiveViewAllocationDisabled; +} + +void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value) +{ + RCTExperimentPreemptiveViewAllocationDisabled = value; +} + +/* + * Release resources when app enters background + */ +static BOOL RCTExperimentReleaseResourcesWhenBackgrounded = NO; -BOOL RCTExperimentGetSyncPerformanceFlag() +BOOL RCTExperimentGetReleaseResourcesWhenBackgrounded() { - return RCTExperimentSyncPerformanceFlag; + return RCTExperimentReleaseResourcesWhenBackgrounded; } -void RCTExperimentSetSyncPerformanceFlag(BOOL value) +void RCTExperimentSetReleaseResourcesWhenBackgrounded(BOOL value) { - RCTExperimentSyncPerformanceFlag = value; + RCTExperimentReleaseResourcesWhenBackgrounded = value; } diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index f3588b38ecb503..af47b0d353ed1a 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -416,7 +416,6 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC return type; } -#if !TARGET_OS_TV RCT_MULTI_ENUM_CONVERTER( UIDataDetectorTypes, (@{ @@ -446,8 +445,6 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC WKDataDetectorTypePhoneNumber, unsignedLongLongValue) -#endif // !TARGET_OS_TV - RCT_ENUM_CONVERTER( UIKeyboardAppearance, (@{ @@ -500,7 +497,6 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC UIViewContentModeScaleAspectFill, integerValue) -#if !TARGET_OS_TV RCT_ENUM_CONVERTER( UIBarStyle, (@{ @@ -511,7 +507,6 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC }), UIBarStyleDefault, integerValue) -#endif static void convertCGStruct(const char *type, NSArray *fields, CGFloat *result, id json) { @@ -727,6 +722,11 @@ +(type)type : (id)json \ // iOS 13.0 RCTFallbackARGB : @(0xFFf2f2f7) }, + // Transparent Color + @"clearColor" : @{ + // iOS 13.0 + RCTFallbackARGB : @(0x00000000) + }, } mutableCopy]; // The color names are the Objective-C UIColor selector names, // but Swift selector names are valid as well, so make aliases. diff --git a/React/Base/RCTEventDispatcher.m b/React/Base/RCTEventDispatcher.m index dfb613657600e8..9da63c3af1190c 100644 --- a/React/Base/RCTEventDispatcher.m +++ b/React/Base/RCTEventDispatcher.m @@ -5,14 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTEventDispatcher.h" - -#import "RCTAssert.h" -#import "RCTBridge+Private.h" -#import "RCTBridge.h" -#import "RCTComponentEvent.h" -#import "RCTProfile.h" -#import "RCTUtils.h" +#import "RCTEventDispatcherProtocol.h" const NSInteger RCTTextUpdateLagWarningThreshold = 3; @@ -27,217 +20,11 @@ return eventName; } -static NSNumber *RCTGetEventID(NSNumber *viewTag, NSString *eventName, uint16_t coalescingKey) -{ - return @(viewTag.intValue | (((uint64_t)eventName.hash & 0xFFFF) << 32) | (((uint64_t)coalescingKey) << 48)); -} - -static uint16_t RCTUniqueCoalescingKeyGenerator = 0; - -@implementation RCTEventDispatcher { - // We need this lock to protect access to _events, _eventQueue and _eventsDispatchScheduled. It's filled in on main - // thread and consumed on js thread. - NSLock *_eventQueueLock; - // We have this id -> event mapping so we coalesce effectively. - NSMutableDictionary> *_events; - // This array contains ids of events in order they come in, so we can emit them to JS in the exact same order. - NSMutableArray *_eventQueue; - BOOL _eventsDispatchScheduled; - NSHashTable> *_observers; - NSLock *_observersLock; -} - -@synthesize bridge = _bridge; -@synthesize dispatchToJSThread = _dispatchToJSThread; -@synthesize invokeJS = _invokeJS; -@synthesize invokeJSWithModuleDotMethod = _invokeJSWithModuleDotMethod; - -RCT_EXPORT_MODULE() - -- (void)setBridge:(RCTBridge *)bridge -{ - _bridge = bridge; - _events = [NSMutableDictionary new]; - _eventQueue = [NSMutableArray new]; - _eventQueueLock = [NSLock new]; - _eventsDispatchScheduled = NO; - _observers = [NSHashTable weakObjectsHashTable]; - _observersLock = [NSLock new]; -} - -- (void)sendAppEventWithName:(NSString *)name body:(id)body -{ - if (_bridge) { - [_bridge enqueueJSCall:@"RCTNativeAppEventEmitter" - method:@"emit" - args:body ? @[ name, body ] : @[ name ] - completion:NULL]; - } else { - _invokeJS(@"RCTNativeAppEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]); - } -} - -- (void)sendDeviceEventWithName:(NSString *)name body:(id)body -{ - if (_bridge) { - [_bridge enqueueJSCall:@"RCTDeviceEventEmitter" - method:@"emit" - args:body ? @[ name, body ] : @[ name ] - completion:NULL]; - } else { - _invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]); - } -} - -- (void)sendTextEventWithType:(RCTTextEventType)type - reactTag:(NSNumber *)reactTag - text:(NSString *)text - key:(NSString *)key - eventCount:(NSInteger)eventCount -{ - static NSString *events[] = {@"focus", @"blur", @"change", @"submitEditing", @"endEditing", @"keyPress"}; - - NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithDictionary:@{ - @"eventCount" : @(eventCount), - }]; - - if (text) { - body[@"text"] = text; - } - - if (key) { - if (key.length == 0) { - key = @"Backspace"; // backspace - } else { - switch ([key characterAtIndex:0]) { - case '\t': - key = @"Tab"; - break; - case '\n': - key = @"Enter"; - default: - break; - } - } - body[@"key"] = key; - } - - RCTComponentEvent *event = [[RCTComponentEvent alloc] initWithName:events[type] viewTag:reactTag body:body]; - [self sendEvent:event]; -} - -- (void)sendEvent:(id)event -{ - [_observersLock lock]; - - for (id observer in _observers) { - [observer eventDispatcherWillDispatchEvent:event]; - } - - [_observersLock unlock]; - - [_eventQueueLock lock]; - - NSNumber *eventID; - if (event.canCoalesce) { - eventID = RCTGetEventID(event.viewTag, event.eventName, event.coalescingKey); - id previousEvent = _events[eventID]; - if (previousEvent) { - event = [previousEvent coalesceWithEvent:event]; - } else { - [_eventQueue addObject:eventID]; - } - } else { - id previousEvent = _events[eventID]; - eventID = RCTGetEventID(event.viewTag, event.eventName, RCTUniqueCoalescingKeyGenerator++); - RCTAssert( - previousEvent == nil, - @"Got event %@ which cannot be coalesced, but has the same eventID %@ as the previous event %@", - event, - eventID, - previousEvent); - [_eventQueue addObject:eventID]; - } - - _events[eventID] = event; - - BOOL scheduleEventsDispatch = NO; - if (!_eventsDispatchScheduled) { - _eventsDispatchScheduled = YES; - scheduleEventsDispatch = YES; - } - - // We have to release the lock before dispatching block with events, - // since dispatchBlock: can be executed synchronously on the same queue. - // (This is happening when chrome debugging is turned on.) - [_eventQueueLock unlock]; - - if (scheduleEventsDispatch) { - if (_bridge) { - [_bridge - dispatchBlock:^{ - [self flushEventsQueue]; - } - queue:RCTJSThread]; - } else if (_dispatchToJSThread) { - _dispatchToJSThread(^{ - [self flushEventsQueue]; - }); - } - } -} - -- (void)addDispatchObserver:(id)observer -{ - [_observersLock lock]; - [_observers addObject:observer]; - [_observersLock unlock]; -} - -- (void)removeDispatchObserver:(id)observer -{ - [_observersLock lock]; - [_observers removeObject:observer]; - [_observersLock unlock]; -} - -- (void)dispatchEvent:(id)event -{ - if (_bridge) { - [_bridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]]; - } else { - _invokeJSWithModuleDotMethod([[event class] moduleDotMethod], [event arguments]); - } -} - -- (dispatch_queue_t)methodQueue -{ - return RCTJSThread; -} - -// js thread only (which surprisingly can be the main thread, depends on used JS executor) -- (void)flushEventsQueue -{ - [_eventQueueLock lock]; - NSDictionary *events = _events; - _events = [NSMutableDictionary new]; - NSMutableArray *eventQueue = _eventQueue; - _eventQueue = [NSMutableArray new]; - _eventsDispatchScheduled = NO; - [_eventQueueLock unlock]; - - for (NSNumber *eventId in eventQueue) { - [self dispatchEvent:events[eventId]]; - } -} - -@end - @implementation RCTBridge (RCTEventDispatcher) -- (RCTEventDispatcher *)eventDispatcher +- (id)eventDispatcher { - return [self moduleForClass:[RCTEventDispatcher class]]; + return [self moduleForName:@"EventDispatcher" lazilyLoadIfNecessary:YES]; } @end diff --git a/React/Base/RCTEventDispatcher.h b/React/Base/RCTEventDispatcherProtocol.h similarity index 95% rename from React/Base/RCTEventDispatcher.h rename to React/Base/RCTEventDispatcherProtocol.h index dfaba98c2cf443..0c7039277264eb 100644 --- a/React/Base/RCTEventDispatcher.h +++ b/React/Base/RCTEventDispatcherProtocol.h @@ -10,15 +10,6 @@ #import #import -typedef NS_ENUM(NSInteger, RCTTextEventType) { - RCTTextEventTypeFocus, - RCTTextEventTypeBlur, - RCTTextEventTypeChange, - RCTTextEventTypeSubmit, - RCTTextEventTypeEnd, - RCTTextEventTypeKeyPress -}; - /** * The threshold at which text inputs will start warning that the JS thread * has fallen behind (resulting in poor input performance, missed keys, etc.) @@ -32,6 +23,15 @@ RCT_EXTERN const NSInteger RCTTextUpdateLagWarningThreshold; */ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName); +typedef NS_ENUM(NSInteger, RCTTextEventType) { + RCTTextEventTypeFocus, + RCTTextEventTypeBlur, + RCTTextEventTypeChange, + RCTTextEventTypeSubmit, + RCTTextEventTypeEnd, + RCTTextEventTypeKeyPress +}; + @protocol RCTEvent @required @@ -80,7 +80,7 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName); * This class wraps the -[RCTBridge enqueueJSCall:args:] method, and * provides some convenience methods for generating event calls. */ -@interface RCTEventDispatcher : NSObject +@protocol RCTEventDispatcherProtocol /** * Deprecated, do not use. @@ -123,6 +123,6 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName); @interface RCTBridge (RCTEventDispatcher) -- (RCTEventDispatcher *)eventDispatcher; +- (id)eventDispatcher; @end diff --git a/React/Base/RCTJavaScriptLoader.mm b/React/Base/RCTJavaScriptLoader.mm index d902f0c92d0002..dfce0d5e93a253 100755 --- a/React/Base/RCTJavaScriptLoader.mm +++ b/React/Base/RCTJavaScriptLoader.mm @@ -177,6 +177,7 @@ + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL facebook::react::ScriptTag tag = facebook::react::parseTypeFromHeader(header); switch (tag) { + case facebook::react::ScriptTag::HBCBundle: case facebook::react::ScriptTag::RAMBundle: break; diff --git a/React/Base/RCTModuleData.h b/React/Base/RCTModuleData.h index 5ff81532eb34b6..cefd6209313f09 100644 --- a/React/Base/RCTModuleData.h +++ b/React/Base/RCTModuleData.h @@ -13,19 +13,28 @@ @protocol RCTBridgeMethod; @protocol RCTBridgeModule; @class RCTBridge; +@class RCTModuleRegistry; +@class RCTViewRegistry; typedef id (^RCTBridgeModuleProvider)(void); @interface RCTModuleData : NSObject -- (instancetype)initWithModuleClass:(Class)moduleClass bridge:(RCTBridge *)bridge; +- (instancetype)initWithModuleClass:(Class)moduleClass + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED; - (instancetype)initWithModuleClass:(Class)moduleClass moduleProvider:(RCTBridgeModuleProvider)moduleProvider - bridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED NS_DESIGNATED_INITIALIZER; - (instancetype)initWithModuleInstance:(id)instance - bridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED NS_DESIGNATED_INITIALIZER; /** * Calls `constantsToExport` on the module and stores the result. Note that diff --git a/React/Base/RCTModuleData.mm b/React/Base/RCTModuleData.mm index c81b8a41fafb29..f8a5459e66bf00 100644 --- a/React/Base/RCTModuleData.mm +++ b/React/Base/RCTModuleData.mm @@ -48,6 +48,8 @@ @implementation RCTModuleData { RCTBridgeModuleProvider _moduleProvider; std::mutex _instanceLock; BOOL _setupComplete; + RCTModuleRegistry *_moduleRegistry; + RCTViewRegistry *_viewRegistry_DEPRECATED; } @synthesize methods = _methods; @@ -97,34 +99,48 @@ - (void)setUp } } -- (instancetype)initWithModuleClass:(Class)moduleClass bridge:(RCTBridge *)bridge +- (instancetype)initWithModuleClass:(Class)moduleClass + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED { return [self initWithModuleClass:moduleClass moduleProvider:^id { return [moduleClass new]; } - bridge:bridge]; + bridge:bridge + moduleRegistry:moduleRegistry + viewRegistry_DEPRECATED:viewRegistry_DEPRECATED]; } - (instancetype)initWithModuleClass:(Class)moduleClass moduleProvider:(RCTBridgeModuleProvider)moduleProvider bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED { if (self = [super init]) { _bridge = bridge; _moduleClass = moduleClass; _moduleProvider = [moduleProvider copy]; + _moduleRegistry = moduleRegistry; + _viewRegistry_DEPRECATED = viewRegistry_DEPRECATED; [self setUp]; } return self; } -- (instancetype)initWithModuleInstance:(id)instance bridge:(RCTBridge *)bridge +- (instancetype)initWithModuleInstance:(id)instance + bridge:(RCTBridge *)bridge + moduleRegistry:(RCTModuleRegistry *)moduleRegistry + viewRegistry_DEPRECATED:(RCTViewRegistry *)viewRegistry_DEPRECATED { if (self = [super init]) { _bridge = bridge; _instance = instance; _moduleClass = [instance class]; + _moduleRegistry = moduleRegistry; + _viewRegistry_DEPRECATED = viewRegistry_DEPRECATED; [self setUp]; } return self; @@ -185,6 +201,8 @@ - (void)setUpInstanceAndBridge:(int32_t)requestId // initialization requires it (View Managers get their queue by calling // self.bridge.uiManager.methodQueue) [self setBridgeForInstance]; + [self setModuleRegistryForInstance]; + [self setViewRegistryForInstance]; } [self setUpMethodQueue]; @@ -231,6 +249,41 @@ - (void)setBridgeForInstance } } +- (void)setModuleRegistryForInstance +{ + if ([_instance respondsToSelector:@selector(moduleRegistry)] && _instance.moduleRegistry != _moduleRegistry) { + RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setModuleRegistryForInstance]", nil); + @try { + [(id)_instance setValue:_moduleRegistry forKey:@"moduleRegistry"]; + } @catch (NSException *exception) { + RCTLogError( + @"%@ has no setter or ivar for its module registry, which is not " + "permitted. You must either @synthesize the moduleRegistry property, " + "or provide your own setter method.", + self.name); + } + RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); + } +} + +- (void)setViewRegistryForInstance +{ + if ([_instance respondsToSelector:@selector(viewRegistry_DEPRECATED)] && + _instance.viewRegistry_DEPRECATED != _viewRegistry_DEPRECATED) { + RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTModuleData setViewRegistryForInstance]", nil); + @try { + [(id)_instance setValue:_viewRegistry_DEPRECATED forKey:@"viewRegistry_DEPRECATED"]; + } @catch (NSException *exception) { + RCTLogError( + @"%@ has no setter or ivar for its module registry, which is not " + "permitted. You must either @synthesize the viewRegistry_DEPRECATED property, " + "or provide your own setter method.", + self.name); + } + RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); + } +} + - (void)finishSetupForInstance { if (!_setupComplete && _instance) { diff --git a/React/Base/RCTModuleRegistry.m b/React/Base/RCTModuleRegistry.m new file mode 100644 index 00000000000000..c5a5d10ab48eb3 --- /dev/null +++ b/React/Base/RCTModuleRegistry.m @@ -0,0 +1,48 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTBridge.h" +#import "RCTBridgeModule.h" + +@implementation RCTModuleRegistry { + __weak id _turboModuleRegistry; + __weak RCTBridge *_bridge; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; +} + +- (void)setTurboModuleRegistry:(id)turboModuleRegistry +{ + _turboModuleRegistry = turboModuleRegistry; +} + +- (id)moduleForName:(const char *)moduleName +{ + return [self moduleForName:moduleName lazilyLoadIfNecessary:YES]; +} + +- (id)moduleForName:(const char *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad +{ + id module = nil; + + RCTBridge *bridge = _bridge; + if (bridge) { + module = [bridge moduleForName:[NSString stringWithUTF8String:moduleName] lazilyLoadIfNecessary:lazilyLoad]; + } + + id turboModuleRegistry = _turboModuleRegistry; + if (module == nil && turboModuleRegistry && (lazilyLoad || [turboModuleRegistry moduleIsInitialized:moduleName])) { + module = [turboModuleRegistry moduleForName:moduleName]; + } + + return module; +} + +@end diff --git a/React/Base/RCTPerformanceLogger.h b/React/Base/RCTPerformanceLogger.h index 1c440582b7b482..b0e4a4e2a57873 100644 --- a/React/Base/RCTPerformanceLogger.h +++ b/React/Base/RCTPerformanceLogger.h @@ -27,6 +27,7 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) { RCTPLBridgeStartup, RCTPLTTI, RCTPLBundleSize, + RCTPLReactInstanceInit, RCTPLSize // This is used to count the size }; diff --git a/React/Base/RCTPerformanceLogger.m b/React/Base/RCTPerformanceLogger.m index ea4c5d407aa0eb..ee71be042a9503 100644 --- a/React/Base/RCTPerformanceLogger.m +++ b/React/Base/RCTPerformanceLogger.m @@ -46,6 +46,7 @@ - (instancetype)init @"BridgeStartup", @"RootViewTTI", @"BundleSize", + @"ReactInstanceInit", ]; } return self; diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 013c7506850fd2..62bdd7585779f8 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -15,7 +15,6 @@ #import "RCTBridge+Private.h" #import "RCTBridge.h" #import "RCTConstants.h" -#import "RCTEventDispatcher.h" #import "RCTKeyCommands.h" #import "RCTLog.h" #import "RCTPerformanceLogger.h" @@ -29,11 +28,6 @@ #import "RCTView.h" #import "UIView+React.h" -#if TARGET_OS_TV -#import "RCTTVNavigationEventEmitter.h" -#import "RCTTVRemoteHandler.h" -#endif - NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification"; @interface RCTUIManager (RCTRootView) @@ -89,13 +83,6 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge name:RCTContentDidAppearNotification object:self]; -#if TARGET_OS_TV - self.tvRemoteHandler = [RCTTVRemoteHandler new]; - for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { - [self addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; - } -#endif - [self showLoadingView]; // Immediately schedule the application to be started. @@ -121,16 +108,6 @@ - (instancetype)initWithBundleURL:(NSURL *)bundleURL RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder) -#if TARGET_OS_TV -- (UIView *)preferredFocusedView -{ - if (self.reactPreferredFocusedView) { - return self.reactPreferredFocusedView; - } - return [super preferredFocusedView]; -} -#endif - #pragma mark - passThroughTouches - (BOOL)passThroughTouches diff --git a/React/Base/RCTRootViewInternal.h b/React/Base/RCTRootViewInternal.h index c6a21c9ab1cb2f..8e28dd453570c1 100644 --- a/React/Base/RCTRootViewInternal.h +++ b/React/Base/RCTRootViewInternal.h @@ -7,8 +7,6 @@ #import -@class RCTTVRemoteHandler; - /** * The interface provides a set of functions that allow other internal framework * classes to change the RCTRootViews's internal state. @@ -21,14 +19,6 @@ */ @property (readwrite, nonatomic, assign) CGSize intrinsicContentSize; -/** - * TV remote gesture recognizers - */ -#if TARGET_OS_TV -@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler; -@property (nonatomic, strong) UIView *reactPreferredFocusedView; -#endif - - (void)contentViewInvalidated; @end diff --git a/React/Base/RCTTVRemoteHandler.h b/React/Base/RCTTVRemoteHandler.h deleted file mode 100644 index 10d56906901677..00000000000000 --- a/React/Base/RCTTVRemoteHandler.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -extern NSString *const RCTTVRemoteEventMenu; -extern NSString *const RCTTVRemoteEventPlayPause; -extern NSString *const RCTTVRemoteEventSelect; - -extern NSString *const RCTTVRemoteEventLongPlayPause; -extern NSString *const RCTTVRemoteEventLongSelect; - -extern NSString *const RCTTVRemoteEventLeft; -extern NSString *const RCTTVRemoteEventRight; -extern NSString *const RCTTVRemoteEventUp; -extern NSString *const RCTTVRemoteEventDown; - -extern NSString *const RCTTVRemoteEventSwipeLeft; -extern NSString *const RCTTVRemoteEventSwipeRight; -extern NSString *const RCTTVRemoteEventSwipeUp; -extern NSString *const RCTTVRemoteEventSwipeDown; - -@interface RCTTVRemoteHandler : NSObject - -@property (nonatomic, copy, readonly) NSDictionary *tvRemoteGestureRecognizers; - -@end diff --git a/React/Base/RCTTVRemoteHandler.m b/React/Base/RCTTVRemoteHandler.m deleted file mode 100644 index aadbacec4b7eb5..00000000000000 --- a/React/Base/RCTTVRemoteHandler.m +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTTVRemoteHandler.h" - -#import - -#import "RCTAssert.h" -#import "RCTBridge.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTRootView.h" -#import "RCTTVNavigationEventEmitter.h" -#import "RCTUIManager.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "UIView+React.h" - -#if __has_include("RCTDevMenu.h") -#import "RCTDevMenu.h" -#endif - -NSString *const RCTTVRemoteEventMenu = @"menu"; -NSString *const RCTTVRemoteEventPlayPause = @"playPause"; -NSString *const RCTTVRemoteEventSelect = @"select"; - -NSString *const RCTTVRemoteEventLongPlayPause = @"longPlayPause"; -NSString *const RCTTVRemoteEventLongSelect = @"longSelect"; - -NSString *const RCTTVRemoteEventLeft = @"left"; -NSString *const RCTTVRemoteEventRight = @"right"; -NSString *const RCTTVRemoteEventUp = @"up"; -NSString *const RCTTVRemoteEventDown = @"down"; - -NSString *const RCTTVRemoteEventSwipeLeft = @"swipeLeft"; -NSString *const RCTTVRemoteEventSwipeRight = @"swipeRight"; -NSString *const RCTTVRemoteEventSwipeUp = @"swipeUp"; -NSString *const RCTTVRemoteEventSwipeDown = @"swipeDown"; - -@implementation RCTTVRemoteHandler { - NSMutableDictionary *_tvRemoteGestureRecognizers; -} - -- (instancetype)init -{ - if ((self = [super init])) { - _tvRemoteGestureRecognizers = [NSMutableDictionary dictionary]; - - // Recognizers for Apple TV remote buttons - - // Play/Pause - [self addTapGestureRecognizerWithSelector:@selector(playPausePressed:) - pressType:UIPressTypePlayPause - name:RCTTVRemoteEventPlayPause]; - - // Menu - [self addTapGestureRecognizerWithSelector:@selector(menuPressed:) - pressType:UIPressTypeMenu - name:RCTTVRemoteEventMenu]; - - // Select - [self addTapGestureRecognizerWithSelector:@selector(selectPressed:) - pressType:UIPressTypeSelect - name:RCTTVRemoteEventSelect]; - - // Up - [self addTapGestureRecognizerWithSelector:@selector(tappedUp:) - pressType:UIPressTypeUpArrow - name:RCTTVRemoteEventUp]; - - // Down - [self addTapGestureRecognizerWithSelector:@selector(tappedDown:) - pressType:UIPressTypeDownArrow - name:RCTTVRemoteEventDown]; - - // Left - [self addTapGestureRecognizerWithSelector:@selector(tappedLeft:) - pressType:UIPressTypeLeftArrow - name:RCTTVRemoteEventLeft]; - - // Right - [self addTapGestureRecognizerWithSelector:@selector(tappedRight:) - pressType:UIPressTypeRightArrow - name:RCTTVRemoteEventRight]; - - // Recognizers for long button presses - // We don't intercept long menu press -- that's used by the system to go to the home screen - - [self addLongPressGestureRecognizerWithSelector:@selector(longPlayPausePressed:) - pressType:UIPressTypePlayPause - name:RCTTVRemoteEventLongPlayPause]; - - [self addLongPressGestureRecognizerWithSelector:@selector(longSelectPressed:) - pressType:UIPressTypeSelect - name:RCTTVRemoteEventLongSelect]; - - // Recognizers for Apple TV remote trackpad swipes - - // Up - [self addSwipeGestureRecognizerWithSelector:@selector(swipedUp:) - direction:UISwipeGestureRecognizerDirectionUp - name:RCTTVRemoteEventSwipeUp]; - - // Down - [self addSwipeGestureRecognizerWithSelector:@selector(swipedDown:) - direction:UISwipeGestureRecognizerDirectionDown - name:RCTTVRemoteEventSwipeDown]; - - // Left - [self addSwipeGestureRecognizerWithSelector:@selector(swipedLeft:) - direction:UISwipeGestureRecognizerDirectionLeft - name:RCTTVRemoteEventSwipeLeft]; - - // Right - [self addSwipeGestureRecognizerWithSelector:@selector(swipedRight:) - direction:UISwipeGestureRecognizerDirectionRight - name:RCTTVRemoteEventSwipeRight]; - } - - return self; -} - -- (void)playPausePressed:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventPlayPause toView:r.view]; -} - -- (void)menuPressed:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventMenu toView:r.view]; -} - -- (void)selectPressed:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventSelect toView:r.view]; -} - -- (void)longPlayPausePressed:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventLongPlayPause toView:r.view]; - -#if __has_include("RCTDevMenu.h") && RCT_DEV - // If shake to show is enabled on device, use long play/pause event to show dev menu - [[NSNotificationCenter defaultCenter] postNotificationName:RCTShowDevMenuNotification object:nil]; -#endif -} - -- (void)longSelectPressed:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventLongSelect toView:r.view]; -} - -- (void)swipedUp:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventSwipeUp toView:r.view]; -} - -- (void)swipedDown:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventSwipeDown toView:r.view]; -} - -- (void)swipedLeft:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventSwipeLeft toView:r.view]; -} - -- (void)swipedRight:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventSwipeRight toView:r.view]; -} - -- (void)tappedUp:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventUp toView:r.view]; -} - -- (void)tappedDown:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventDown toView:r.view]; -} - -- (void)tappedLeft:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventLeft toView:r.view]; -} - -- (void)tappedRight:(UIGestureRecognizer *)r -{ - [self sendAppleTVEvent:RCTTVRemoteEventRight toView:r.view]; -} - -#pragma mark - - -- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector - pressType:(UIPressType)pressType - name:(NSString *)name -{ - UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector]; - recognizer.allowedPressTypes = @[ @(pressType) ]; - - _tvRemoteGestureRecognizers[name] = recognizer; -} - -- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType name:(NSString *)name -{ - UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:selector]; - recognizer.allowedPressTypes = @[ @(pressType) ]; - - _tvRemoteGestureRecognizers[name] = recognizer; -} - -- (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector - direction:(UISwipeGestureRecognizerDirection)direction - name:(NSString *)name -{ - UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:selector]; - recognizer.direction = direction; - - _tvRemoteGestureRecognizers[name] = recognizer; -} - -- (void)sendAppleTVEvent:(NSString *)eventType toView:(__unused UIView *)v -{ - [[NSNotificationCenter defaultCenter] postNotificationName:RCTTVNavigationEventNotification - object:@{@"eventType" : eventType}]; -} - -@end diff --git a/React/Base/RCTTouchEvent.h b/React/Base/RCTTouchEvent.h index 99cc6d435a1573..9f3cc4f9ff388a 100644 --- a/React/Base/RCTTouchEvent.h +++ b/React/Base/RCTTouchEvent.h @@ -7,7 +7,7 @@ #import -#import +#import /** * Represents a touch event, which may be composed of several touches (one for every finger). diff --git a/React/Base/RCTTouchHandler.m b/React/Base/RCTTouchHandler.m index 8361fdf55c7e95..fc32afb0a79cfc 100644 --- a/React/Base/RCTTouchHandler.m +++ b/React/Base/RCTTouchHandler.m @@ -11,7 +11,7 @@ #import "RCTAssert.h" #import "RCTBridge.h" -#import "RCTEventDispatcher.h" +#import "RCTEventDispatcherProtocol.h" #import "RCTLog.h" #import "RCTSurfaceView.h" #import "RCTTouchEvent.h" @@ -25,7 +25,7 @@ @interface RCTTouchHandler () // TODO: this class behaves a lot like a module, and could be implemented as a // module if we were to assume that modules and RootViews had a 1:1 relationship @implementation RCTTouchHandler { - __weak RCTEventDispatcher *_eventDispatcher; + __weak id _eventDispatcher; /** * Arrays managed in parallel tracking native touch object along with the @@ -47,7 +47,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge RCTAssertParam(bridge); if ((self = [super initWithTarget:nil action:NULL])) { - _eventDispatcher = [bridge moduleForClass:[RCTEventDispatcher class]]; + _eventDispatcher = bridge.eventDispatcher; _nativeTouches = [NSMutableOrderedSet new]; _reactTouches = [NSMutableArray new]; diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index 1d26c256557a28..a65a36926176e0 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -167,8 +167,12 @@ id RCTJSONClean(id object) static dispatch_once_t onceToken; static NSSet *validLeafTypes; dispatch_once(&onceToken, ^{ - validLeafTypes = - [[NSSet alloc] initWithArray:@ [[NSString class], [NSMutableString class], [NSNumber class], [NSNull class], ]]; + validLeafTypes = [[NSSet alloc] initWithArray:@[ + [NSString class], + [NSMutableString class], + [NSNumber class], + [NSNull class], + ]]; }); if ([validLeafTypes containsObject:[object classForCoder]]) { diff --git a/React/Base/RCTViewRegistry.m b/React/Base/RCTViewRegistry.m new file mode 100644 index 00000000000000..d66caa17bb6197 --- /dev/null +++ b/React/Base/RCTViewRegistry.m @@ -0,0 +1,45 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +#import "RCTBridge.h" +#import "RCTBridgeModule.h" + +@implementation RCTViewRegistry { + RCTBridgelessComponentViewProvider _bridgelessComponentViewProvider; + __weak RCTBridge *_bridge; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; +} + +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)bridgelessComponentViewProvider +{ + _bridgelessComponentViewProvider = bridgelessComponentViewProvider; +} + +- (UIView *)viewForReactTag:(NSNumber *)reactTag +{ + UIView *view = nil; + + RCTBridge *bridge = _bridge; + if (bridge) { + view = [bridge.uiManager viewForReactTag:reactTag]; + } + + if (view == nil && _bridgelessComponentViewProvider) { + view = _bridgelessComponentViewProvider(reactTag); + } + + return view; +} + +@end diff --git a/React/CoreModules/BUCK b/React/CoreModules/BUCK index 2f9902478139d5..d9475c86bb52c3 100644 --- a/React/CoreModules/BUCK +++ b/React/CoreModules/BUCK @@ -1,4 +1,4 @@ -load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode") +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode") load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "rn_apple_library", "rn_extra_build_flags") load( "@fbsource//xplat/configurations/buck/apple/plugins/sad_xplat_hosted_configurations:react_module_registration.bzl", @@ -36,6 +36,7 @@ rn_apple_library( header_path_prefix = "React", labels = [ "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", "supermodule:xplat/default/public.react_native.infra", ], link_whole = True, @@ -104,9 +105,6 @@ rn_apple_library( ) + react_module_plugin_providers( name = "LogBox", native_class_func = "RCTLogBoxCls", - ) + react_module_plugin_providers( - name = "TVNavigationEventEmitter", - native_class_func = "RCTTVNavigationEventEmitterCls", ) + react_module_plugin_providers( name = "WebSocketExecutor", native_class_func = "RCTWebSocketExecutorCls", @@ -119,9 +117,12 @@ rn_apple_library( ) + react_module_plugin_providers( name = "DevSplitBundleLoader", native_class_func = "RCTDevSplitBundleLoaderCls", + ) + react_module_plugin_providers( + name = "EventDispatcher", + native_class_func = "RCTEventDispatcherCls", ), plugins_header = "FBCoreModulesPlugins.h", - preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ "-DRN_DISABLE_OSS_PLUGIN_HEADER", ], reexport_all_header_dependencies = True, @@ -130,6 +131,6 @@ rn_apple_library( "//xplat/js:RCTLinkingApple", "//xplat/js:RCTPushNotificationApple", "//xplat/js/react-native-github:ReactInternalApple", - "//xplat/js/react-native-github/Libraries/FBReactNativeSpec:FBReactNativeSpecApple", + "//xplat/js/react-native-github/Libraries:FBReactNativeSpecApple", ], ) diff --git a/React/CoreModules/CoreModulesPlugins.h b/React/CoreModules/CoreModulesPlugins.h index 509eb5af2f8dbc..0dd21309bceedd 100644 --- a/React/CoreModules/CoreModulesPlugins.h +++ b/React/CoreModules/CoreModulesPlugins.h @@ -49,11 +49,11 @@ Class RCTDevMenuCls(void) __attribute__((used)); Class RCTDevSettingsCls(void) __attribute__((used)); Class RCTRedBoxCls(void) __attribute__((used)); Class RCTLogBoxCls(void) __attribute__((used)); -Class RCTTVNavigationEventEmitterCls(void) __attribute__((used)); Class RCTWebSocketExecutorCls(void) __attribute__((used)); Class RCTWebSocketModuleCls(void) __attribute__((used)); Class RCTDevLoadingViewCls(void) __attribute__((used)); Class RCTDevSplitBundleLoaderCls(void) __attribute__((used)); +Class RCTEventDispatcherCls(void) __attribute__((used)); #ifdef __cplusplus } diff --git a/React/CoreModules/CoreModulesPlugins.mm b/React/CoreModules/CoreModulesPlugins.mm index ced0cbd0797bbe..c2d1b268b4fa6a 100644 --- a/React/CoreModules/CoreModulesPlugins.mm +++ b/React/CoreModules/CoreModulesPlugins.mm @@ -38,11 +38,11 @@ Class RCTCoreModulesClassProvider(const char *name) { {"DevSettings", RCTDevSettingsCls}, {"RedBox", RCTRedBoxCls}, {"LogBox", RCTLogBoxCls}, - {"TVNavigationEventEmitter", RCTTVNavigationEventEmitterCls}, {"WebSocketExecutor", RCTWebSocketExecutorCls}, {"WebSocketModule", RCTWebSocketModuleCls}, {"DevLoadingView", RCTDevLoadingViewCls}, {"DevSplitBundleLoader", RCTDevSplitBundleLoaderCls}, + {"EventDispatcher", RCTEventDispatcherCls}, }; auto p = sCoreModuleClassMap.find(name); diff --git a/React/CoreModules/RCTAccessibilityManager.mm b/React/CoreModules/RCTAccessibilityManager.mm index 3f6098e66aba7e..3b15ec0e89a3c8 100644 --- a/React/CoreModules/RCTAccessibilityManager.mm +++ b/React/CoreModules/RCTAccessibilityManager.mm @@ -10,7 +10,7 @@ #import #import #import -#import +#import #import #import @@ -28,7 +28,8 @@ @interface RCTAccessibilityManager () @implementation RCTAccessibilityManager -@synthesize bridge = _bridge; +@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED; +@synthesize moduleRegistry = _moduleRegistry; @synthesize multipliers = _multipliers; RCT_EXPORT_MODULE() @@ -111,7 +112,7 @@ - (void)accessibilityAnnouncementDidFinish:(__unused NSNotification *)notificati #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"announcementFinished" body:response]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"announcementFinished" body:response]; #pragma clang diagnostic pop } @@ -122,7 +123,8 @@ - (void)boldTextStatusDidChange:(__unused NSNotification *)notification _isBoldTextEnabled = newBoldTextEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"boldTextChanged" body:@(_isBoldTextEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"boldTextChanged" + body:@(_isBoldTextEnabled)]; #pragma clang diagnostic pop } } @@ -134,7 +136,8 @@ - (void)grayscaleStatusDidChange:(__unused NSNotification *)notification _isGrayscaleEnabled = newGrayscaleEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"grayscaleChanged" body:@(_isGrayscaleEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"grayscaleChanged" + body:@(_isGrayscaleEnabled)]; #pragma clang diagnostic pop } } @@ -146,7 +149,8 @@ - (void)invertColorsStatusDidChange:(__unused NSNotification *)notification _isInvertColorsEnabled = newInvertColorsEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"invertColorsChanged" body:@(_isInvertColorsEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"invertColorsChanged" + body:@(_isInvertColorsEnabled)]; #pragma clang diagnostic pop } } @@ -158,7 +162,8 @@ - (void)reduceMotionStatusDidChange:(__unused NSNotification *)notification _isReduceMotionEnabled = newReduceMotionEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"reduceMotionChanged" body:@(_isReduceMotionEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"reduceMotionChanged" + body:@(_isReduceMotionEnabled)]; #pragma clang diagnostic pop } } @@ -170,7 +175,8 @@ - (void)reduceTransparencyStatusDidChange:(__unused NSNotification *)notificatio _isReduceTransparencyEnabled = newReduceTransparencyEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"reduceTransparencyChanged" body:@(_isReduceTransparencyEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"reduceTransparencyChanged" + body:@(_isReduceTransparencyEnabled)]; #pragma clang diagnostic pop } } @@ -182,7 +188,8 @@ - (void)voiceVoiceOverStatusDidChange:(__unused NSNotification *)notification _isVoiceOverEnabled = newIsVoiceOverEnabled; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"screenReaderChanged" body:@(_isVoiceOverEnabled)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"screenReaderChanged" + body:@(_isVoiceOverEnabled)]; #pragma clang diagnostic pop } } @@ -278,7 +285,7 @@ static void setMultipliers( RCT_EXPORT_METHOD(setAccessibilityFocus : (double)reactTag) { dispatch_async(dispatch_get_main_queue(), ^{ - UIView *view = [self.bridge.uiManager viewForReactTag:@(reactTag)]; + UIView *view = [self.viewRegistry_DEPRECATED viewForReactTag:@(reactTag)]; UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, view); }); } diff --git a/React/CoreModules/RCTActionSheetManager.mm b/React/CoreModules/RCTActionSheetManager.mm index 754e461157349d..76918d9ab79655 100644 --- a/React/CoreModules/RCTActionSheetManager.mm +++ b/React/CoreModules/RCTActionSheetManager.mm @@ -31,7 +31,7 @@ @implementation RCTActionSheetManager { RCT_EXPORT_MODULE() -@synthesize bridge = _bridge; +@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED; - (dispatch_queue_t)methodQueue { @@ -46,7 +46,7 @@ - (void)presentViewController:(UIViewController *)alertController UIView *sourceView = parentViewController.view; if (anchorViewTag) { - sourceView = [self.bridge.uiManager viewForReactTag:anchorViewTag]; + sourceView = [self.viewRegistry_DEPRECATED viewForReactTag:anchorViewTag]; } else { alertController.popoverPresentationController.permittedArrowDirections = 0; } @@ -73,9 +73,15 @@ - (void)presentViewController:(UIViewController *)alertController NSArray *buttons = RCTConvertOptionalVecToArray(options.options(), ^id(NSString *element) { return element; }); + NSArray *disabledButtonIndices; NSInteger cancelButtonIndex = options.cancelButtonIndex() ? [RCTConvert NSInteger:@(*options.cancelButtonIndex())] : -1; NSArray *destructiveButtonIndices; + if (options.disabledButtonIndices()) { + disabledButtonIndices = RCTConvertVecToArray(*options.disabledButtonIndices(), ^id(double element) { + return @(element); + }); + } if (options.destructiveButtonIndices()) { destructiveButtonIndices = RCTConvertVecToArray(*options.destructiveButtonIndices(), ^id(double element) { return @(element); @@ -90,15 +96,17 @@ - (void)presentViewController:(UIViewController *)alertController UIColor *tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil]; if (controller == nil) { - RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", @{ - @"title" : title, - @"message" : message, - @"options" : buttons, - @"cancelButtonIndex" : @(cancelButtonIndex), - @"destructiveButtonIndices" : destructiveButtonIndices, - @"anchor" : anchor, - @"tintColor" : tintColor, - }); + RCTLogError( + @"Tried to display action sheet but there is no application window. options: %@", @{ + @"title" : title, + @"message" : message, + @"options" : buttons, + @"cancelButtonIndex" : @(cancelButtonIndex), + @"destructiveButtonIndices" : destructiveButtonIndices, + @"anchor" : anchor, + @"tintColor" : tintColor, + @"disabledButtonIndices" : disabledButtonIndices, + }); return; } @@ -132,6 +140,20 @@ - (void)presentViewController:(UIViewController *)alertController index++; } + if (disabledButtonIndices) { + for (NSNumber *disabledButtonIndex in disabledButtonIndices) { + if ([disabledButtonIndex integerValue] < buttons.count) { + [alertController.actions[[disabledButtonIndex integerValue]] setEnabled:false]; + } else { + RCTLogError( + @"Index %@ from `disabledButtonIndices` is out of bounds. Maximum index value is %@.", + @([disabledButtonIndex integerValue]), + @(buttons.count - 1)); + return; + } + } + } + alertController.view.tintColor = tintColor; #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 diff --git a/React/CoreModules/RCTAlertController.h b/React/CoreModules/RCTAlertController.h index ada35e81fd846e..f5c206cb1226b4 100644 --- a/React/CoreModules/RCTAlertController.h +++ b/React/CoreModules/RCTAlertController.h @@ -10,5 +10,6 @@ @interface RCTAlertController : UIAlertController - (void)show:(BOOL)animated completion:(void (^)(void))completion; +- (void)hide; -@end \ No newline at end of file +@end diff --git a/React/CoreModules/RCTAlertController.m b/React/CoreModules/RCTAlertController.m index e38c5005a8ff62..8cd0babb5595c0 100644 --- a/React/CoreModules/RCTAlertController.m +++ b/React/CoreModules/RCTAlertController.m @@ -33,4 +33,9 @@ - (void)show:(BOOL)animated completion:(void (^)(void))completion [self.alertWindow.rootViewController presentViewController:self animated:animated completion:completion]; } +- (void)hide +{ + _alertWindow = nil; +} + @end diff --git a/React/CoreModules/RCTAlertManager.mm b/React/CoreModules/RCTAlertManager.mm index 425951e60f8c3e..e0f450e480e703 100644 --- a/React/CoreModules/RCTAlertManager.mm +++ b/React/CoreModules/RCTAlertManager.mm @@ -161,6 +161,7 @@ - (void)invalidate case RCTAlertViewStylePlainTextInput: case RCTAlertViewStyleSecureTextInput: callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]); + [weakAlertController hide]; break; case RCTAlertViewStyleLoginAndPasswordInput: { NSDictionary *loginCredentials = @{ @@ -168,10 +169,12 @@ - (void)invalidate @"password" : [weakAlertController.textFields.lastObject text] }; callback(@[ buttonKey, loginCredentials ]); + [weakAlertController hide]; break; } case RCTAlertViewStyleDefault: callback(@[ buttonKey ]); + [weakAlertController hide]; break; } }]]; diff --git a/React/CoreModules/RCTAppState.h b/React/CoreModules/RCTAppState.h index 6e0f19c3356f65..0921f70e44723b 100644 --- a/React/CoreModules/RCTAppState.h +++ b/React/CoreModules/RCTAppState.h @@ -7,6 +7,6 @@ #import -@interface RCTAppState : RCTEventEmitter +@interface RCTAppState : RCTEventEmitter @end diff --git a/React/CoreModules/RCTAppState.mm b/React/CoreModules/RCTAppState.mm index 66a1e72693f2f6..5fc28ef71c875f 100644 --- a/React/CoreModules/RCTAppState.mm +++ b/React/CoreModules/RCTAppState.mm @@ -10,7 +10,7 @@ #import #import #import -#import +#import #import #import "CoreModulesPlugins.h" @@ -99,11 +99,6 @@ - (void)stopObserving [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)invalidate -{ - [self stopObserving]; -} - #pragma mark - App Notification Methods - (void)handleMemoryWarning diff --git a/React/CoreModules/RCTAsyncLocalStorage.mm b/React/CoreModules/RCTAsyncLocalStorage.mm index 00b66634f03edd..3276d152013888 100644 --- a/React/CoreModules/RCTAsyncLocalStorage.mm +++ b/React/CoreModules/RCTAsyncLocalStorage.mm @@ -76,11 +76,7 @@ static void RCTAppendError(NSDictionary *error, NSMutableArray * static NSString *storageDirectory = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ -#if TARGET_OS_TV - storageDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; -#else storageDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; -#endif storageDirectory = [storageDirectory stringByAppendingPathComponent:RCTStorageDirectory]; }); return storageDirectory; @@ -166,7 +162,7 @@ static dispatch_queue_t RCTGetMethodQueue() #pragma mark - RCTAsyncLocalStorage -@interface RCTAsyncLocalStorage () +@interface RCTAsyncLocalStorage () @end @implementation RCTAsyncLocalStorage { @@ -232,10 +228,6 @@ - (NSDictionary *)_ensureSetup { RCTAssertThread(RCTGetMethodQueue(), @"Must be executed on storage thread"); -#if TARGET_OS_TV - RCTLogWarn(@"Persistent storage is not supported on tvOS, your data may be removed at any point."); -#endif - NSError *error = nil; if (!RCTHasCreatedStorageDirectory) { [[NSFileManager defaultManager] createDirectoryAtPath:RCTGetStorageDirectory() @@ -463,7 +455,7 @@ - (NSDictionary *)_writeEntry:(NSArray *)entry changedManifest:(BOOL - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } @end diff --git a/React/CoreModules/RCTDevMenu.mm b/React/CoreModules/RCTDevMenu.mm index 3e9e78e85a5897..6ffd2ca9fc0dad 100644 --- a/React/CoreModules/RCTDevMenu.mm +++ b/React/CoreModules/RCTDevMenu.mm @@ -95,6 +95,7 @@ @implementation RCTDevMenu { } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -135,14 +136,16 @@ - (instancetype)init [commands registerKeyCommandWithInput:@"i" modifierFlags:UIKeyModifierCommand action:^(__unused UIKeyCommand *command) { - [weakSelf.bridge.devSettings toggleElementInspector]; + [(RCTDevSettings *)[weakSelf.moduleRegistry moduleForName:"DevSettings"] + toggleElementInspector]; }]; // Reload in normal mode [commands registerKeyCommandWithInput:@"n" modifierFlags:UIKeyModifierCommand action:^(__unused UIKeyCommand *command) { - [weakSelf.bridge.devSettings setIsDebuggingRemotely:NO]; + [(RCTDevSettings *)[weakSelf.moduleRegistry moduleForName:"DevSettings"] + setIsDebuggingRemotely:NO]; }]; #endif } @@ -164,8 +167,14 @@ - (void)invalidate - (void)showOnShake { - if ([_bridge.devSettings isShakeToShowDevMenuEnabled]) { - [self show]; + if ([((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]) isShakeToShowDevMenuEnabled]) { + for (UIWindow *window in [RCTSharedApplication() windows]) { + NSString *recursiveDescription = [window valueForKey:@"recursiveDescription"]; + if ([recursiveDescription containsString:@"RCTView"]) { + [self show]; + return; + } + } } } @@ -210,7 +219,7 @@ - (void)setDefaultJSBundle // Add built-in items __weak RCTBridge *bridge = _bridge; - __weak RCTDevSettings *devSettings = _bridge.devSettings; + __weak RCTDevSettings *devSettings = [_moduleRegistry moduleForName:"DevSettings"]; __weak RCTDevMenu *weakSelf = self; [items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Reload" @@ -315,9 +324,9 @@ - (void)setDefaultJSBundle if (devSettings.isLiveReloadAvailable) { [items addObject:[RCTDevMenuItem buttonItemWithTitleBlock:^NSString * { - return devSettings.isDebuggingRemotely - ? @"Systrace Unavailable" - : devSettings.isProfilingEnabled ? @"Stop Systrace" : @"Start Systrace"; + return devSettings.isDebuggingRemotely ? @"Systrace Unavailable" + : devSettings.isProfilingEnabled ? @"Stop Systrace" + : @"Start Systrace"; } handler:^{ if (devSettings.isDebuggingRemotely) { @@ -469,12 +478,12 @@ - (RCTDevMenuAlertActionHandler)alertActionHandlerForDevItem:(RCTDevMenuItem *__ - (void)setShakeToShow:(BOOL)shakeToShow { - _bridge.devSettings.isShakeToShowDevMenuEnabled = shakeToShow; + ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isShakeToShowDevMenuEnabled = shakeToShow; } - (BOOL)shakeToShow { - return _bridge.devSettings.isShakeToShowDevMenuEnabled; + return ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isShakeToShowDevMenuEnabled; } RCT_EXPORT_METHOD(reload) @@ -486,29 +495,29 @@ - (BOOL)shakeToShow RCT_EXPORT_METHOD(debugRemotely : (BOOL)enableDebug) { WARN_DEPRECATED_DEV_MENU_EXPORT(); - _bridge.devSettings.isDebuggingRemotely = enableDebug; + ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isDebuggingRemotely = enableDebug; } RCT_EXPORT_METHOD(setProfilingEnabled : (BOOL)enabled) { WARN_DEPRECATED_DEV_MENU_EXPORT(); - _bridge.devSettings.isProfilingEnabled = enabled; + ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isProfilingEnabled = enabled; } - (BOOL)profilingEnabled { - return _bridge.devSettings.isProfilingEnabled; + return ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isProfilingEnabled; } RCT_EXPORT_METHOD(setHotLoadingEnabled : (BOOL)enabled) { WARN_DEPRECATED_DEV_MENU_EXPORT(); - _bridge.devSettings.isHotLoadingEnabled = enabled; + ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isHotLoadingEnabled = enabled; } - (BOOL)hotLoadingEnabled { - return _bridge.devSettings.isHotLoadingEnabled; + return ((RCTDevSettings *)[_moduleRegistry moduleForName:"DevSettings"]).isHotLoadingEnabled; } - (std::shared_ptr)getTurboModule: diff --git a/React/CoreModules/RCTDevSettings.mm b/React/CoreModules/RCTDevSettings.mm index b84d4e3114233e..ccce3b2931f5a1 100644 --- a/React/CoreModules/RCTDevSettings.mm +++ b/React/CoreModules/RCTDevSettings.mm @@ -12,7 +12,7 @@ #import #import #import -#import +#import #import #import #import @@ -202,6 +202,7 @@ - (dispatch_queue_t)methodQueue - (void)invalidate { + [super invalidate]; #if ENABLE_PACKAGER_CONNECTION [[RCTPackagerConnection sharedPackagerConnection] removeHandler:_reloadToken]; #endif @@ -349,7 +350,7 @@ - (BOOL)isHotLoadingEnabled if (_isJSLoaded) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil]; + [[self.moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"toggleElementInspector" body:nil]; #pragma clang diagnostic pop } } @@ -357,11 +358,11 @@ - (BOOL)isHotLoadingEnabled RCT_EXPORT_METHOD(addMenuItem : (NSString *)title) { __weak __typeof(self) weakSelf = self; - [self.bridge.devMenu addItem:[RCTDevMenuItem buttonItemWithTitle:title - handler:^{ - [weakSelf sendEventWithName:@"didPressMenuItem" - body:@{@"title" : title}]; - }]]; + [(RCTDevMenu *)[self.moduleRegistry moduleForName:"DevMenu"] + addItem:[RCTDevMenuItem buttonItemWithTitle:title + handler:^{ + [weakSelf sendEventWithName:@"didPressMenuItem" body:@{@"title" : title}]; + }]]; } - (BOOL)isElementInspectorShown @@ -405,17 +406,18 @@ - (void)addHandler:(id)handler forPackagerMethod:(NSStr - (void)setupHMRClientWithBundleURL:(NSURL *)bundleURL { - if (bundleURL && !bundleURL.fileURL) { // isHotLoadingAvailable check + if (bundleURL && !bundleURL.fileURL) { NSString *const path = [bundleURL.path substringFromIndex:1]; // Strip initial slash. NSString *const host = bundleURL.host; NSNumber *const port = bundleURL.port; + BOOL isHotLoadingEnabled = self.isHotLoadingEnabled; if (self.bridge) { [self.bridge enqueueJSCall:@"HMRClient" method:@"setup" - args:@[ @"ios", path, host, RCTNullIfNil(port), @(YES) ] + args:@[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled) ] completion:NULL]; } else { - self.invokeJS(@"HMRClient", @"setup", @[ @"ios", path, host, RCTNullIfNil(port), @(YES) ]); + self.invokeJS(@"HMRClient", @"setup", @[ @"ios", path, host, RCTNullIfNil(port), @(isHotLoadingEnabled) ]); } } } @@ -461,7 +463,8 @@ - (void)jsLoaded:(NSNotification *)notification if ([self isElementInspectorShown]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil]; + [[self.moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"toggleElementInspector" + body:nil]; #pragma clang diagnostic pop } }); diff --git a/React/CoreModules/RCTDeviceInfo.mm b/React/CoreModules/RCTDeviceInfo.mm index eb5f8217946238..f470f99572e8cf 100644 --- a/React/CoreModules/RCTDeviceInfo.mm +++ b/React/CoreModules/RCTDeviceInfo.mm @@ -11,7 +11,7 @@ #import #import #import -#import +#import #import #import @@ -23,13 +23,12 @@ @interface RCTDeviceInfo () @end @implementation RCTDeviceInfo { -#if !TARGET_OS_TV UIInterfaceOrientation _currentInterfaceOrientation; NSDictionary *_currentInterfaceDimensions; -#endif } -@synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; +@synthesize turboModuleRegistry = _turboModuleRegistry; RCT_EXPORT_MODULE() @@ -43,15 +42,14 @@ - (dispatch_queue_t)methodQueue return dispatch_get_main_queue(); } -- (void)setBridge:(RCTBridge *)bridge +- (void)setModuleRegistry:(RCTModuleRegistry *)moduleRegistry { - _bridge = bridge; - + _moduleRegistry = moduleRegistry; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveNewContentSizeMultiplier) name:RCTAccessibilityManagerDidUpdateMultiplierNotification - object:_bridge.accessibilityManager]; -#if !TARGET_OS_TV + object:[moduleRegistry moduleForName:"AccessibilityManager"]]; + _currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -59,7 +57,7 @@ - (void)setBridge:(RCTBridge *)bridge name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; - _currentInterfaceDimensions = RCTExportedDimensions(_bridge); + _currentInterfaceDimensions = RCTExportedDimensions(_moduleRegistry); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) @@ -70,8 +68,6 @@ - (void)setBridge:(RCTBridge *)bridge selector:@selector(interfaceFrameDidChange) name:RCTUserInterfaceStyleDidChangeNotification object:nil]; - -#endif } static BOOL RCTIsIPhoneX() @@ -86,18 +82,30 @@ static BOOL RCTIsIPhoneX() CGSize iPhoneXScreenSize = CGSizeMake(1125, 2436); CGSize iPhoneXMaxScreenSize = CGSizeMake(1242, 2688); CGSize iPhoneXRScreenSize = CGSizeMake(828, 1792); + CGSize iPhone12ScreenSize = CGSizeMake(1170, 2532); + CGSize iPhone12MiniScreenSize = CGSizeMake(1080, 2340); + CGSize iPhone12ProMaxScreenSize = CGSizeMake(1284, 2778); isIPhoneX = CGSizeEqualToSize(screenSize, iPhoneXScreenSize) || - CGSizeEqualToSize(screenSize, iPhoneXMaxScreenSize) || CGSizeEqualToSize(screenSize, iPhoneXRScreenSize); + CGSizeEqualToSize(screenSize, iPhoneXMaxScreenSize) || CGSizeEqualToSize(screenSize, iPhoneXRScreenSize) || + CGSizeEqualToSize(screenSize, iPhone12ScreenSize) || CGSizeEqualToSize(screenSize, iPhone12MiniScreenSize) || + CGSizeEqualToSize(screenSize, iPhone12ProMaxScreenSize); + ; }); return isIPhoneX; } -static NSDictionary *RCTExportedDimensions(RCTBridge *bridge) +static NSDictionary *RCTExportedDimensions(RCTModuleRegistry *moduleRegistry) { RCTAssertMainQueue(); - RCTDimensions dimensions = RCTGetDimensions(bridge.accessibilityManager.multiplier); + RCTDimensions dimensions; + if (moduleRegistry) { + dimensions = RCTGetDimensions( + ((RCTAccessibilityManager *)[moduleRegistry moduleForName:"AccessibilityManager"]).multiplier ?: 1.0); + } else { + RCTAssert(false, @"ModuleRegistry must be set to properly init dimensions."); + } __typeof(dimensions.window) window = dimensions.window; NSDictionary *dimsWindow = @{ @"width" : @(window.width), @@ -123,9 +131,10 @@ static BOOL RCTIsIPhoneX() - (NSDictionary *)getConstants { __block NSDictionary *constants; + RCTModuleRegistry *moduleRegistry = _moduleRegistry; RCTUnsafeExecuteOnMainQueueSync(^{ constants = @{ - @"Dimensions" : RCTExportedDimensions(self->_bridge), + @"Dimensions" : RCTExportedDimensions(moduleRegistry), // Note: // This prop is deprecated and will be removed in a future release. // Please use this only for a quick and temporary solution. @@ -139,18 +148,17 @@ static BOOL RCTIsIPhoneX() - (void)didReceiveNewContentSizeMultiplier { - RCTBridge *bridge = _bridge; + RCTModuleRegistry *moduleRegistry = _moduleRegistry; RCTExecuteOnMainQueue(^{ // Report the event across the bridge. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(bridge)]; + [[moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"didUpdateDimensions" + body:RCTExportedDimensions(moduleRegistry)]; #pragma clang diagnostic pop }); } -#if !TARGET_OS_TV - - (void)interfaceOrientationDidChange { __weak __typeof(self) weakSelf = self; @@ -170,7 +178,8 @@ - (void)_interfaceOrientationDidChange !UIInterfaceOrientationIsLandscape(nextOrientation))) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(_bridge)]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"didUpdateDimensions" + body:RCTExportedDimensions(_moduleRegistry)]; #pragma clang diagnostic pop } @@ -187,20 +196,19 @@ - (void)interfaceFrameDidChange - (void)_interfaceFrameDidChange { - NSDictionary *nextInterfaceDimensions = RCTExportedDimensions(_bridge); + NSDictionary *nextInterfaceDimensions = RCTExportedDimensions(_moduleRegistry); if (!([nextInterfaceDimensions isEqual:_currentInterfaceDimensions])) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:nextInterfaceDimensions]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"didUpdateDimensions" + body:nextInterfaceDimensions]; #pragma clang diagnostic pop } _currentInterfaceDimensions = nextInterfaceDimensions; } -#endif // TARGET_OS_TV - - (std::shared_ptr)getTurboModule:(const ObjCTurboModule::InitParams &)params { return std::make_shared(params); diff --git a/React/CoreModules/RCTEventDispatcher.h b/React/CoreModules/RCTEventDispatcher.h new file mode 100644 index 00000000000000..e15c20723252dd --- /dev/null +++ b/React/CoreModules/RCTEventDispatcher.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import +/** + * This class wraps the -[RCTBridge enqueueJSCall:args:] method, and + * provides some convenience methods for generating event calls. + */ +@interface RCTEventDispatcher : NSObject +@end diff --git a/React/CoreModules/RCTEventDispatcher.mm b/React/CoreModules/RCTEventDispatcher.mm new file mode 100644 index 00000000000000..1dd07d936caaac --- /dev/null +++ b/React/CoreModules/RCTEventDispatcher.mm @@ -0,0 +1,232 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTEventDispatcher.h" + +#import +#import +#import +#import +#import +#import +#import + +#import "CoreModulesPlugins.h" + +static NSNumber *RCTGetEventID(NSNumber *viewTag, NSString *eventName, uint16_t coalescingKey) +{ + return @(viewTag.intValue | (((uint64_t)eventName.hash & 0xFFFF) << 32) | (((uint64_t)coalescingKey) << 48)); +} + +static uint16_t RCTUniqueCoalescingKeyGenerator = 0; + +@interface RCTEventDispatcher () +@end + +@implementation RCTEventDispatcher { + // We need this lock to protect access to _events, _eventQueue and _eventsDispatchScheduled. It's filled in on main + // thread and consumed on js thread. + NSLock *_eventQueueLock; + // We have this id -> event mapping so we coalesce effectively. + NSMutableDictionary> *_events; + // This array contains ids of events in order they come in, so we can emit them to JS in the exact same order. + NSMutableArray *_eventQueue; + BOOL _eventsDispatchScheduled; + NSHashTable> *_observers; + NSLock *_observersLock; +} + +@synthesize bridge = _bridge; +@synthesize dispatchToJSThread = _dispatchToJSThread; +@synthesize invokeJS = _invokeJS; +@synthesize invokeJSWithModuleDotMethod = _invokeJSWithModuleDotMethod; + +RCT_EXPORT_MODULE() + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; + _events = [NSMutableDictionary new]; + _eventQueue = [NSMutableArray new]; + _eventQueueLock = [NSLock new]; + _eventsDispatchScheduled = NO; + _observers = [NSHashTable weakObjectsHashTable]; + _observersLock = [NSLock new]; +} + +- (void)sendAppEventWithName:(NSString *)name body:(id)body +{ + if (_bridge) { + [_bridge enqueueJSCall:@"RCTNativeAppEventEmitter" + method:@"emit" + args:body ? @[ name, body ] : @[ name ] + completion:NULL]; + } else if (_invokeJS) { + _invokeJS(@"RCTNativeAppEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]); + } +} + +- (void)sendDeviceEventWithName:(NSString *)name body:(id)body +{ + if (_bridge) { + [_bridge enqueueJSCall:@"RCTDeviceEventEmitter" + method:@"emit" + args:body ? @[ name, body ] : @[ name ] + completion:NULL]; + } else if (_invokeJS) { + _invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]); + } +} + +- (void)sendTextEventWithType:(RCTTextEventType)type + reactTag:(NSNumber *)reactTag + text:(NSString *)text + key:(NSString *)key + eventCount:(NSInteger)eventCount +{ + static NSString *events[] = {@"focus", @"blur", @"change", @"submitEditing", @"endEditing", @"keyPress"}; + + NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithDictionary:@{ + @"eventCount" : @(eventCount), + }]; + + if (text) { + body[@"text"] = text; + } + + if (key) { + if (key.length == 0) { + key = @"Backspace"; // backspace + } else { + switch ([key characterAtIndex:0]) { + case '\t': + key = @"Tab"; + break; + case '\n': + key = @"Enter"; + default: + break; + } + } + body[@"key"] = key; + } + + RCTComponentEvent *event = [[RCTComponentEvent alloc] initWithName:events[type] viewTag:reactTag body:body]; + [self sendEvent:event]; +} + +- (void)sendEvent:(id)event +{ + [_observersLock lock]; + + for (id observer in _observers) { + [observer eventDispatcherWillDispatchEvent:event]; + } + + [_observersLock unlock]; + + [_eventQueueLock lock]; + + NSNumber *eventID; + if (event.canCoalesce) { + eventID = RCTGetEventID(event.viewTag, event.eventName, event.coalescingKey); + id previousEvent = _events[eventID]; + if (previousEvent) { + event = [previousEvent coalesceWithEvent:event]; + } else { + [_eventQueue addObject:eventID]; + } + } else { + id previousEvent = _events[eventID]; + eventID = RCTGetEventID(event.viewTag, event.eventName, RCTUniqueCoalescingKeyGenerator++); + RCTAssert( + previousEvent == nil, + @"Got event %@ which cannot be coalesced, but has the same eventID %@ as the previous event %@", + event, + eventID, + previousEvent); + [_eventQueue addObject:eventID]; + } + + _events[eventID] = event; + + BOOL scheduleEventsDispatch = NO; + if (!_eventsDispatchScheduled) { + _eventsDispatchScheduled = YES; + scheduleEventsDispatch = YES; + } + + // We have to release the lock before dispatching block with events, + // since dispatchBlock: can be executed synchronously on the same queue. + // (This is happening when chrome debugging is turned on.) + [_eventQueueLock unlock]; + + if (scheduleEventsDispatch) { + if (_bridge) { + [_bridge + dispatchBlock:^{ + [self flushEventsQueue]; + } + queue:RCTJSThread]; + } else if (_dispatchToJSThread) { + _dispatchToJSThread(^{ + [self flushEventsQueue]; + }); + } + } +} + +- (void)addDispatchObserver:(id)observer +{ + [_observersLock lock]; + [_observers addObject:observer]; + [_observersLock unlock]; +} + +- (void)removeDispatchObserver:(id)observer +{ + [_observersLock lock]; + [_observers removeObject:observer]; + [_observersLock unlock]; +} + +- (void)dispatchEvent:(id)event +{ + if (_bridge) { + [_bridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]]; + } else if (_invokeJSWithModuleDotMethod) { + _invokeJSWithModuleDotMethod([[event class] moduleDotMethod], [event arguments]); + } +} + +- (dispatch_queue_t)methodQueue +{ + return RCTJSThread; +} + +// js thread only (which surprisingly can be the main thread, depends on used JS executor) +- (void)flushEventsQueue +{ + [_eventQueueLock lock]; + NSDictionary *events = _events; + _events = [NSMutableDictionary new]; + NSMutableArray *eventQueue = _eventQueue; + _eventQueue = [NSMutableArray new]; + _eventsDispatchScheduled = NO; + [_eventQueueLock unlock]; + + for (NSNumber *eventId in eventQueue) { + [self dispatchEvent:events[eventId]]; + } +} + +@end + +Class RCTEventDispatcherCls(void) +{ + return RCTEventDispatcher.class; +} diff --git a/React/CoreModules/RCTExceptionsManager.mm b/React/CoreModules/RCTExceptionsManager.mm index cd2c2f34013156..175c5612cff592 100644 --- a/React/CoreModules/RCTExceptionsManager.mm +++ b/React/CoreModules/RCTExceptionsManager.mm @@ -23,8 +23,7 @@ @interface RCTExceptionsManager () @implementation RCTExceptionsManager -@synthesize bridge = _bridge; -@synthesize turboModuleRegistry = _turboModuleRegistry; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -42,13 +41,8 @@ - (void)reportSoft:(NSString *)message suppressRedBox:(BOOL)suppressRedBox { if (!suppressRedBox) { - // TODO T5287269 - Delete _bridge case when TM ships. - if (_bridge) { - [_bridge.redBox showErrorMessage:message withStack:stack errorCookie:((int)exceptionId)]; - } else { - RCTRedBox *redbox = [_turboModuleRegistry moduleForName:"RCTRedBox"]; - [redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; - } + RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"]; + [redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; } if (_delegate) { @@ -64,13 +58,8 @@ - (void)reportFatal:(NSString *)message suppressRedBox:(BOOL)suppressRedBox { if (!suppressRedBox) { - // TODO T5287269 - Delete _bridge case when TM ships. - if (_bridge) { - [_bridge.redBox showErrorMessage:message withStack:stack errorCookie:((int)exceptionId)]; - } else { - RCTRedBox *redbox = [_turboModuleRegistry moduleForName:"RCTRedBox"]; - [redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; - } + RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"]; + [redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; } if (_delegate) { @@ -111,13 +100,8 @@ - (void)reportFatal:(NSString *)message : (NSArray *)stack exceptionId : (double)exceptionId) { - // TODO T5287269 - Delete _bridge case when TM ships. - if (_bridge) { - [_bridge.redBox updateErrorMessage:message withStack:stack errorCookie:((int)exceptionId)]; - } else { - RCTRedBox *redbox = [_turboModuleRegistry moduleForName:"RCTRedBox"]; - [redbox updateErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; - } + RCTRedBox *redbox = [_moduleRegistry moduleForName:"RedBox"]; + [redbox showErrorMessage:message withStack:stack errorCookie:(int)exceptionId]; if (_delegate && [_delegate respondsToSelector:@selector(updateJSExceptionWithMessage:stack:exceptionId:)]) { [_delegate updateJSExceptionWithMessage:message stack:stack exceptionId:[NSNumber numberWithDouble:exceptionId]]; diff --git a/React/CoreModules/RCTKeyboardObserver.mm b/React/CoreModules/RCTKeyboardObserver.mm index b00f08c21cabb6..072df8ce3d7efe 100644 --- a/React/CoreModules/RCTKeyboardObserver.mm +++ b/React/CoreModules/RCTKeyboardObserver.mm @@ -8,7 +8,7 @@ #import "RCTKeyboardObserver.h" #import -#import +#import #import "CoreModulesPlugins.h" @@ -23,8 +23,6 @@ @implementation RCTKeyboardObserver - (void)startObserving { -#if !TARGET_OS_TV - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; #define ADD_KEYBOARD_HANDLER(NAME, SELECTOR) [nc addObserver:self selector:@selector(SELECTOR:) name:NAME object:nil] @@ -37,8 +35,6 @@ - (void)startObserving ADD_KEYBOARD_HANDLER(UIKeyboardDidChangeFrameNotification, keyboardDidChangeFrame); #undef ADD_KEYBOARD_HANDLER - -#endif } - (NSArray *)supportedEvents @@ -113,9 +109,6 @@ -(void)EVENT : (NSNotification *)notification static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification) { -#if TARGET_OS_TV - return @{}; -#else NSDictionary *userInfo = notification.userInfo; CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; @@ -131,7 +124,6 @@ -(void)EVENT : (NSNotification *)notification @"easing" : RCTAnimationNameForCurve(curve), @"isEventFromThisApp" : isLocalUserInfoKey == 1 ? @YES : @NO, }; -#endif } Class RCTKeyboardObserverCls(void) diff --git a/React/CoreModules/RCTPerfMonitor.mm b/React/CoreModules/RCTPerfMonitor.mm index 790591d3afcacd..7ad8770dffc676 100644 --- a/React/CoreModules/RCTPerfMonitor.mm +++ b/React/CoreModules/RCTPerfMonitor.mm @@ -136,6 +136,7 @@ @implementation RCTPerfMonitor { } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -149,12 +150,11 @@ - (dispatch_queue_t)methodQueue return dispatch_get_main_queue(); } -- (void)setBridge:(RCTBridge *)bridge +- (void)setModuleRegistry:(RCTModuleRegistry *)moduleRegistry { - _bridge = bridge; - + _moduleRegistry = moduleRegistry; #if __has_include() - [_bridge.devMenu addItem:self.devMenuItem]; + [(RCTDevMenu *)[_moduleRegistry moduleForName:"DevMenu"] addItem:self.devMenuItem]; #endif } @@ -168,7 +168,7 @@ - (RCTDevMenuItem *)devMenuItem { if (!_devMenuItem) { __weak __typeof__(self) weakSelf = self; - __weak RCTDevSettings *devSettings = self.bridge.devSettings; + __weak RCTDevSettings *devSettings = [self->_moduleRegistry moduleForName:"DevSettings"]; if (devSettings.isPerfMonitorShown) { [weakSelf show]; } diff --git a/React/CoreModules/RCTRedBox.mm b/React/CoreModules/RCTRedBox.mm index 4325dc139eca47..ce47519514d862 100644 --- a/React/CoreModules/RCTRedBox.mm +++ b/React/CoreModules/RCTRedBox.mm @@ -12,7 +12,7 @@ #import #import #import -#import +#import #import #import #import @@ -104,10 +104,8 @@ - (instancetype)initWithFrame:(CGRect)frame _stackTraceTableView.delegate = self; _stackTraceTableView.dataSource = self; _stackTraceTableView.backgroundColor = [UIColor clearColor]; -#if !TARGET_OS_TV _stackTraceTableView.separatorColor = [UIColor colorWithWhite:1 alpha:0.3]; _stackTraceTableView.separatorStyle = UITableViewCellSeparatorStyleNone; -#endif _stackTraceTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite; [rootView addSubview:_stackTraceTableView]; @@ -292,10 +290,8 @@ - (void)copyStack [fullStackTrace appendFormat:@" %@\n", [self formatFrameSource:stackFrame]]; } } -#if !TARGET_OS_TV UIPasteboard *pb = [UIPasteboard generalPasteboard]; [pb setString:fullStackTrace]; -#endif } - (NSString *)formatFrameSource:(RCTJSStackFrame *)stackFrame @@ -459,6 +455,7 @@ @implementation RCTRedBox { } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -594,7 +591,8 @@ - (void)showErrorMessage:(NSString *)message #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self->_bridge.eventDispatcher sendDeviceEventWithName:@"collectRedBoxExtraData" body:nil]; + [[self->_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"collectRedBoxExtraData" + body:nil]; #pragma clang diagnostic pop if (!self->_window) { diff --git a/React/CoreModules/RCTStatusBarManager.h b/React/CoreModules/RCTStatusBarManager.h index dead2d86a85803..db02b9176a694b 100644 --- a/React/CoreModules/RCTStatusBarManager.h +++ b/React/CoreModules/RCTStatusBarManager.h @@ -12,10 +12,8 @@ @interface RCTConvert (UIStatusBar) -#if !TARGET_OS_TV + (UIStatusBarStyle)UIStatusBarStyle:(id)json; + (UIStatusBarAnimation)UIStatusBarAnimation:(id)json; -#endif @end diff --git a/React/CoreModules/RCTStatusBarManager.mm b/React/CoreModules/RCTStatusBarManager.mm index 3e62b9df5052c7..c40fdd4379e03e 100644 --- a/React/CoreModules/RCTStatusBarManager.mm +++ b/React/CoreModules/RCTStatusBarManager.mm @@ -8,11 +8,10 @@ #import "RCTStatusBarManager.h" #import "CoreModulesPlugins.h" -#import +#import #import #import -#if !TARGET_OS_TV #import @implementation RCTConvert (UIStatusBar) @@ -58,15 +57,10 @@ + (UIStatusBarStyle)UIStatusBarStyle:(id)json RCT_DYNAMIC integerValue); @end -#endif - -#if !TARGET_OS_TV @interface RCTStatusBarManager () @end -#endif - @implementation RCTStatusBarManager static BOOL RCTViewControllerBasedStatusBarAppearance() @@ -94,8 +88,6 @@ + (BOOL)requiresMainQueueSetup return @[ @"statusBarFrameDidChange", @"statusBarFrameWillChange" ]; } -#if !TARGET_OS_TV - - (void)startObserving { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; @@ -207,8 +199,6 @@ - (void)applicationWillChangeStatusBarFrame:(NSNotification *)notification return std::make_shared(params); } -#endif // TARGET_OS_TV - @end Class RCTStatusBarManagerCls(void) diff --git a/React/CoreModules/RCTTVNavigationEventEmitter.mm b/React/CoreModules/RCTTVNavigationEventEmitter.mm deleted file mode 100644 index 58fc1ead297cfb..00000000000000 --- a/React/CoreModules/RCTTVNavigationEventEmitter.mm +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTTVNavigationEventEmitter.h" - -#import -#import "CoreModulesPlugins.h" - -NSString *const RCTTVNavigationEventNotification = @"RCTTVNavigationEventNotification"; - -static NSString *const TVNavigationEventName = @"onHWKeyEvent"; - -@interface RCTTVNavigationEventEmitter () -@end - -@implementation RCTTVNavigationEventEmitter - -RCT_EXPORT_MODULE() - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - -- (instancetype)init -{ - if (self = [super init]) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleTVNavigationEventNotification:) - name:RCTTVNavigationEventNotification - object:nil]; - } - return self; -} - -- (NSArray *)supportedEvents -{ - return @[ TVNavigationEventName ]; -} - -- (void)handleTVNavigationEventNotification:(NSNotification *)notif -{ - if (self.bridge) { - [self sendEventWithName:TVNavigationEventName body:notif.object]; - } -} - -- (std::shared_ptr)getTurboModule: - (const facebook::react::ObjCTurboModule::InitParams &)params -{ - return std::make_shared(params); -} - -@end - -Class RCTTVNavigationEventEmitterCls(void) -{ - return RCTTVNavigationEventEmitter.class; -} diff --git a/React/CoreModules/RCTWebSocketModule.mm b/React/CoreModules/RCTWebSocketModule.mm index e26423d245438b..32889ea7d4bddb 100644 --- a/React/CoreModules/RCTWebSocketModule.mm +++ b/React/CoreModules/RCTWebSocketModule.mm @@ -53,6 +53,8 @@ - (NSArray *)supportedEvents - (void)invalidate { + [super invalidate]; + _contentHandlers = nil; for (RCTSRWebSocket *socket in _sockets.allValues) { socket.delegate = nil; @@ -166,7 +168,9 @@ - (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error NSNumber *socketID = [webSocket reactTag]; _contentHandlers[socketID] = nil; _sockets[socketID] = nil; - [self sendEventWithName:@"websocketFailed" body:@{@"message" : error.localizedDescription, @"id" : socketID}]; + NSDictionary *body = + @{@"message" : error.localizedDescription ?: @"Undefined, error is nil", @"id" : socketID ?: @(-1)}; + [self sendEventWithName:@"websocketFailed" body:body]; } - (void)webSocket:(RCTSRWebSocket *)webSocket diff --git a/React/CoreModules/React-CoreModules.podspec b/React/CoreModules/React-CoreModules.podspec index 7d5a617b28a7ee..dee7239471187d 100644 --- a/React/CoreModules/React-CoreModules.podspec +++ b/React/CoreModules/React-CoreModules.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "**/*.{c,m,mm,cpp}" diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 594b1cbeec6536..05cd58cff701fe 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -12,6 +12,8 @@ #import #import #import +#import +#import #import #import #import @@ -37,11 +39,16 @@ #import #import -#if TARGET_OS_OSX && __has_include() +#ifndef RCT_USE_HERMES +#if __has_include() #define RCT_USE_HERMES 1 +#else +#define RCT_USE_HERMES 0 +#endif #endif + #if RCT_USE_HERMES -#import "HermesExecutorFactory.h" +#import #else #import "JSCExecutorFactory.h" #endif @@ -126,41 +133,57 @@ static void notifyAboutModuleSetup(RCTPerformanceLogger *performanceLogger, cons } } +static void mapReactMarkerToPerformanceLogger( + const ReactMarker::ReactMarkerId markerId, + RCTPerformanceLogger *performanceLogger, + const char *tag, + int instanceKey) +{ + switch (markerId) { + case ReactMarker::RUN_JS_BUNDLE_START: + [performanceLogger markStartForTag:RCTPLScriptExecution]; + break; + case ReactMarker::RUN_JS_BUNDLE_STOP: + [performanceLogger markStopForTag:RCTPLScriptExecution]; + break; + case ReactMarker::NATIVE_REQUIRE_START: + [performanceLogger appendStartForTag:RCTPLRAMNativeRequires]; + break; + case ReactMarker::NATIVE_REQUIRE_STOP: + [performanceLogger appendStopForTag:RCTPLRAMNativeRequires]; + [performanceLogger addValue:1 forTag:RCTPLRAMNativeRequiresCount]; + break; + case ReactMarker::NATIVE_MODULE_SETUP_START: + [performanceLogger markStartForTag:RCTPLNativeModuleSetup]; + break; + case ReactMarker::NATIVE_MODULE_SETUP_STOP: + [performanceLogger markStopForTag:RCTPLNativeModuleSetup]; + notifyAboutModuleSetup(performanceLogger, tag); + break; + // Not needed in bridge mode. + case ReactMarker::REACT_INSTANCE_INIT_START: + case ReactMarker::REACT_INSTANCE_INIT_STOP: + // Not used on iOS. + case ReactMarker::CREATE_REACT_CONTEXT_STOP: + case ReactMarker::JS_BUNDLE_STRING_CONVERT_START: + case ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP: + case ReactMarker::REGISTER_JS_SEGMENT_START: + case ReactMarker::REGISTER_JS_SEGMENT_STOP: + break; + } +} + static void registerPerformanceLoggerHooks(RCTPerformanceLogger *performanceLogger) { __weak RCTPerformanceLogger *weakPerformanceLogger = performanceLogger; - ReactMarker::logTaggedMarker = [weakPerformanceLogger]( - const ReactMarker::ReactMarkerId markerId, const char *__unused tag) { - switch (markerId) { - case ReactMarker::RUN_JS_BUNDLE_START: - [weakPerformanceLogger markStartForTag:RCTPLScriptExecution]; - break; - case ReactMarker::RUN_JS_BUNDLE_STOP: - [weakPerformanceLogger markStopForTag:RCTPLScriptExecution]; - break; - case ReactMarker::NATIVE_REQUIRE_START: - [weakPerformanceLogger appendStartForTag:RCTPLRAMNativeRequires]; - break; - case ReactMarker::NATIVE_REQUIRE_STOP: - [weakPerformanceLogger appendStopForTag:RCTPLRAMNativeRequires]; - [weakPerformanceLogger addValue:1 forTag:RCTPLRAMNativeRequiresCount]; - break; - case ReactMarker::NATIVE_MODULE_SETUP_START: - [weakPerformanceLogger markStartForTag:RCTPLNativeModuleSetup]; - break; - case ReactMarker::NATIVE_MODULE_SETUP_STOP: - [weakPerformanceLogger markStopForTag:RCTPLNativeModuleSetup]; - notifyAboutModuleSetup(weakPerformanceLogger, tag); - break; - case ReactMarker::CREATE_REACT_CONTEXT_STOP: - case ReactMarker::JS_BUNDLE_STRING_CONVERT_START: - case ReactMarker::JS_BUNDLE_STRING_CONVERT_STOP: - case ReactMarker::REGISTER_JS_SEGMENT_START: - case ReactMarker::REGISTER_JS_SEGMENT_STOP: - // These are not used on iOS. - break; - } + ReactMarker::logTaggedMarker = [weakPerformanceLogger](const ReactMarker::ReactMarkerId markerId, const char *tag) { + mapReactMarkerToPerformanceLogger(markerId, weakPerformanceLogger, tag, 0); }; + + ReactMarker::logTaggedMarkerWithInstanceKey = + [weakPerformanceLogger](const ReactMarker::ReactMarkerId markerId, const char *tag, const int instanceKey) { + mapReactMarkerToPerformanceLogger(markerId, weakPerformanceLogger, tag, instanceKey); + }; } @interface RCTCxxBridge () @@ -209,6 +232,9 @@ @implementation RCTCxxBridge { // Necessary for searching in TurboModules in TurboModuleManager id _turboModuleRegistry; + + RCTModuleRegistry *_objCModuleRegistry; + RCTViewRegistry *_viewRegistry_DEPRECATED; } @synthesize bridgeDescription = _bridgeDescription; @@ -219,6 +245,7 @@ @implementation RCTCxxBridge { - (void)setRCTTurboModuleRegistry:(id)turboModuleRegistry { _turboModuleRegistry = turboModuleRegistry; + [_objCModuleRegistry setTurboModuleRegistry:_turboModuleRegistry]; } - (std::shared_ptr)jsMessageThread @@ -255,6 +282,10 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge _moduleDataByName = [NSMutableDictionary new]; _moduleClassesByID = [NSMutableArray new]; _moduleDataByID = [NSMutableArray new]; + _objCModuleRegistry = [RCTModuleRegistry new]; + [_objCModuleRegistry setBridge:self]; + _viewRegistry_DEPRECATED = [RCTViewRegistry new]; + [_viewRegistry_DEPRECATED setBridge:self]; [RCTBridge setCurrentBridge:self]; @@ -262,6 +293,10 @@ - (instancetype)initWithParentBridge:(RCTBridge *)bridge selector:@selector(handleMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleApplicationDidEnterBackgroundNotification) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; } return self; } @@ -306,7 +341,9 @@ - (void)_tryAndHandleError:(dispatch_block_t)block - (void)handleMemoryWarning { - if (!_valid || !_loading) { + // We only want to run garbage collector when the loading is finished + // and the instance is valid. + if (!_valid || _loading) { return; } @@ -318,6 +355,26 @@ - (void)handleMemoryWarning } } +- (void)handleApplicationDidEnterBackgroundNotification +{ + if (!RCTExperimentGetReleaseResourcesWhenBackgrounded()) { + return; + } + + // We only want to run garbage collector when the loading is finished + // and the instance is valid. + if (!_valid || _loading) { + return; + } + + // We need to hold a local retaining pointer to react instance + // in case if some other tread resets it. + auto reactInstance = _reactInstance; + if (reactInstance) { + reactInstance->handleMemoryPressure(40 /* TRIM_MEMORY_BACKGROUND */); + } +} + /** * Ensure block is run on the JS thread. If we're already on the JS thread, the block will execute synchronously. * If we're not on the JS thread, the block is dispatched to that thread. Any errors encountered while executing @@ -721,7 +778,10 @@ - (void)updateModuleWithInstance:(id)instance // TODO #13258411: can we defer this until config generation? int32_t moduleDataId = getUniqueId(); BridgeNativeModulePerfLogger::moduleDataCreateStart([moduleName UTF8String], moduleDataId); - moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass bridge:self]; + moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass + bridge:self + moduleRegistry:_objCModuleRegistry + viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED]; BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId); _moduleDataByName[moduleName] = moduleData; @@ -784,7 +844,10 @@ - (void)registerExtraModules // Instantiate moduleData container int32_t moduleDataId = getUniqueId(); BridgeNativeModulePerfLogger::moduleDataCreateStart([moduleName UTF8String], moduleDataId); - RCTModuleData *moduleData = [[RCTModuleData alloc] initWithModuleInstance:module bridge:self]; + RCTModuleData *moduleData = [[RCTModuleData alloc] initWithModuleInstance:module + bridge:self + moduleRegistry:_objCModuleRegistry + viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED]; BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId); _moduleDataByName[moduleName] = moduleData; @@ -835,7 +898,10 @@ - (void)registerExtraLazyModules int32_t moduleDataId = getUniqueId(); BridgeNativeModulePerfLogger::moduleDataCreateStart([moduleName UTF8String], moduleDataId); - moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass bridge:self]; + moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass + bridge:self + moduleRegistry:_objCModuleRegistry + viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED]; BridgeNativeModulePerfLogger::moduleDataCreateEnd([moduleName UTF8String], moduleDataId); _moduleDataByName[moduleName] = moduleData; diff --git a/React/CxxBridge/RCTMessageThread.h b/React/CxxBridge/RCTMessageThread.h index ecdee6d6cc7bd0..b15c536d0a14e0 100644 --- a/React/CxxBridge/RCTMessageThread.h +++ b/React/CxxBridge/RCTMessageThread.h @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#import #import #import @@ -15,7 +16,8 @@ namespace facebook { namespace react { -class RCTMessageThread : public MessageQueueThread { +class RCTMessageThread : public MessageQueueThread, + public std::enable_shared_from_this { public: RCTMessageThread(NSRunLoop *runLoop, RCTJavaScriptCompleteBlock errorBlock); ~RCTMessageThread() override; diff --git a/React/CxxBridge/RCTMessageThread.mm b/React/CxxBridge/RCTMessageThread.mm index f29e47dd032350..c340fa7b737a2b 100644 --- a/React/CxxBridge/RCTMessageThread.mm +++ b/React/CxxBridge/RCTMessageThread.mm @@ -31,6 +31,7 @@ RCTMessageThread::~RCTMessageThread() { + RCTAssert(m_shutdown, @"RCTMessageThread: quitSynchronous() not called before destructor"); CFRelease(m_cfRunLoop); } @@ -76,10 +77,9 @@ if (m_shutdown) { return; } - - runAsync([this, func = std::make_shared>(std::move(func))] { - if (!m_shutdown) { - tryFunc(*func); + runAsync([sharedThis = shared_from_this(), func = std::make_shared>(std::move(func))] { + if (!sharedThis->m_shutdown) { + sharedThis->tryFunc(*func); } }); } @@ -89,9 +89,9 @@ if (m_shutdown) { return; } - runSync([this, func = std::move(func)] { - if (!m_shutdown) { - tryFunc(func); + runSync([sharedThis = shared_from_this(), func = std::move(func)] { + if (!sharedThis->m_shutdown) { + sharedThis->tryFunc(func); } }); } diff --git a/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm index dd79102526d9e5..f5c0a1e421deb8 100644 --- a/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm @@ -7,11 +7,13 @@ #import "RCTActivityIndicatorViewComponentView.h" +#import + #import #import #import -#import "FBRCTFabricComponentsPlugins.h" +#import "RCTFabricComponentsPlugins.h" using namespace facebook::react; @@ -50,7 +52,7 @@ - (instancetype)initWithFrame:(CGRect)frame } else { [_activityIndicatorView stopAnimating]; } - _activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps->color.get()]; + _activityIndicatorView.color = RCTUIColorFromSharedColor(defaultProps->color); _activityIndicatorView.hidesWhenStopped = defaultProps->hidesWhenStopped; _activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps->size); @@ -73,8 +75,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & } } - if (oldViewProps.color.get() != newViewProps.color.get()) { - _activityIndicatorView.color = [UIColor colorWithCGColor:newViewProps.color.get()]; + if (oldViewProps.color != newViewProps.color) { + _activityIndicatorView.color = RCTUIColorFromSharedColor(newViewProps.color); } // TODO: This prop should be deprecated. diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h index c8db70c6b80002..8f40efe885c947 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#import #import NS_ASSUME_NONNULL_BEGIN @@ -12,7 +13,10 @@ NS_ASSUME_NONNULL_BEGIN /** * UIView class for root component. */ -@interface RCTImageComponentView : RCTViewComponentView +@interface RCTImageComponentView : RCTViewComponentView { + @protected + UIImageView *_imageView; +} @end diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index 0de4b95a59235a..114a85b9c0c782 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -7,27 +7,20 @@ #import "RCTImageComponentView.h" +#import #import #import -#import #import #import #import #import -#import #import -#import #import using namespace facebook::react; -@interface RCTImageComponentView () -@end - @implementation RCTImageComponentView { - UIImageView *_imageView; - ImageShadowNode::ConcreteStateTeller _stateTeller; - ImageResponseObserverCoordinator const *_coordinator; + ImageShadowNode::ConcreteState::Shared _state; RCTImageResponseObserverProxy _imageResponseObserverProxy; } @@ -76,7 +69,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // `tintColor` if (oldImageProps.tintColor != newImageProps.tintColor) { - _imageView.tintColor = [UIColor colorWithCGColor:newImageProps.tintColor.get()]; + _imageView.tintColor = RCTUIColorFromSharedColor(newImageProps.tintColor); } [super updateProps:props oldProps:oldProps]; @@ -84,17 +77,19 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState { - _stateTeller.setConcreteState(state); - auto _oldState = std::static_pointer_cast(oldState); - auto data = _stateTeller.getData().value(); + RCTAssert(state, @"`state` must not be null."); + RCTAssert( + std::dynamic_pointer_cast(state), + @"`state` must be a pointer to `ImageShadowNode::ConcreteState`."); + + auto oldImageState = std::static_pointer_cast(_state); + auto newImageState = std::static_pointer_cast(state); - // This call (setting `coordinator`) must be unconditional (at the same block as setting `State`) - // because the setter stores a raw pointer to object that `State` owns. - self.coordinator = &data.getImageRequest().getObserverCoordinator(); + [self _setStateAndResubscribeImageResponseObserver:newImageState]; - bool havePreviousData = _oldState && _oldState->getData().getImageSource() != ImageSource{}; + bool havePreviousData = oldImageState && oldImageState->getData().getImageSource() != ImageSource{}; - if (!havePreviousData || data.getImageSource() != _oldState->getData().getImageSource()) { + if (!havePreviousData || newImageState->getData().getImageSource() != oldImageState->getData().getImageSource()) { // Loading actually starts a little before this, but this is the first time we know // the image is loading and can fire an event from this component std::static_pointer_cast(_eventEmitter)->onLoadStart(); @@ -104,35 +99,33 @@ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const & } } -- (void)setCoordinator:(ImageResponseObserverCoordinator const *)coordinator +- (void)_setStateAndResubscribeImageResponseObserver:(ImageShadowNode::ConcreteState::Shared const &)state { - if (_coordinator) { - _coordinator->removeObserver(_imageResponseObserverProxy); + if (_state) { + auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator(); + observerCoordinator.removeObserver(_imageResponseObserverProxy); } - _coordinator = coordinator; - if (_coordinator != nullptr) { - _coordinator->addObserver(_imageResponseObserverProxy); + + _state = state; + + if (_state) { + auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator(); + observerCoordinator.addObserver(_imageResponseObserverProxy); } } - (void)prepareForRecycle { [super prepareForRecycle]; - self.coordinator = nullptr; + [self _setStateAndResubscribeImageResponseObserver:nullptr]; _imageView.image = nil; - _stateTeller.invalidate(); -} - -- (void)dealloc -{ - self.coordinator = nullptr; } #pragma mark - RCTImageResponseDelegate -- (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer +- (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(void const *)observer { - if (!_eventEmitter || !_stateTeller.isValid()) { + if (!_eventEmitter || !_state) { // Notifications are delivered asynchronously and might arrive after the view is already recycled. // In the future, we should incorporate an `EventEmitter` into a separate object owned by `ImageRequest` or `State`. // See for more info: T46311063. @@ -157,30 +150,17 @@ - (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer resizingMode:UIImageResizingModeStretch]; } - void (^didSetImage)() = ^() { - auto data = self->_stateTeller.getData(); - if (!data.hasValue()) { - return; - } - auto instrumentation = std::static_pointer_cast( - data.value().getImageRequest().getSharedImageInstrumentation()); - if (instrumentation) { - instrumentation->didSetImage(); - } - }; - if (imageProps.blurRadius > __FLT_EPSILON__) { // Blur on a background thread to avoid blocking interaction. + CGFloat blurRadius = imageProps.blurRadius; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - UIImage *blurredImage = RCTBlurredImageWithRadius(image, imageProps.blurRadius); + UIImage *blurredImage = RCTBlurredImageWithRadius(image, blurRadius); RCTExecuteOnMainQueue(^{ self->_imageView.image = blurredImage; - didSetImage(); }); }); } else { self->_imageView.image = image; - didSetImage(); } } diff --git a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm index d151d1c0c3a421..e53c8570d95cc6 100644 --- a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm @@ -41,7 +41,7 @@ } @implementation RCTInputAccessoryComponentView { - InputAccessoryShadowNode::ConcreteStateTeller _stateTeller; + InputAccessoryShadowNode::ConcreteState::Shared _state; RCTInputAccessoryContentView *_contentView; RCTSurfaceTouchHandler *_touchHandler; UIView __weak *_textInput; @@ -118,15 +118,16 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & self.hidden = true; } -- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState +- (void)updateState:(const facebook::react::State::Shared &)state + oldState:(const facebook::react::State::Shared &)oldState { - _stateTeller.setConcreteState(state); - CGSize oldViewportSize = RCTCGSizeFromSize(_stateTeller.getData().value().viewportSize); + _state = std::static_pointer_cast(state); + CGSize oldScreenSize = RCTCGSizeFromSize(_state->getData().viewportSize); CGSize viewportSize = RCTViewportSize(); viewportSize.height = std::nan(""); - if (oldViewportSize.width != viewportSize.width) { + if (oldScreenSize.width != viewportSize.width) { auto stateData = InputAccessoryState{RCTSizeFromCGSize(viewportSize)}; - _stateTeller.updateState(std::move(stateData)); + _state->updateState(std::move(stateData)); } } @@ -141,7 +142,7 @@ - (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics - (void)prepareForRecycle { [super prepareForRecycle]; - _stateTeller.invalidate(); + _state.reset(); _textInput = nil; } diff --git a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.mm b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.mm index d9c4fb231b2493..1d112b51c1c88f 100644 --- a/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.mm +++ b/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryContentView.mm @@ -24,7 +24,7 @@ - (instancetype)init _heightConstraint = [_safeAreaContainer.heightAnchor constraintEqualToConstant:0]; _heightConstraint.active = YES; - if (@available(iOS 11.0, tvOS 11.0, *)) { + if (@available(iOS 11.0, *)) { [NSLayoutConstraint activateConstraints:@[ [_safeAreaContainer.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor], [_safeAreaContainer.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor], diff --git a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm index 8c9a97ce6aa2ab..661b53ee7b8bf3 100644 --- a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm @@ -22,7 +22,7 @@ @implementation RCTLegacyViewManagerInteropComponentView { NSMutableArray *_viewsToBeMounted; NSMutableArray *_viewsToBeUnmounted; RCTLegacyViewManagerInteropCoordinatorAdapter *_adapter; - LegacyViewManagerInteropShadowNode::ConcreteStateTeller _stateTeller; + LegacyViewManagerInteropShadowNode::ConcreteState::Shared _state; } - (instancetype)initWithFrame:(CGRect)frame @@ -37,6 +37,17 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event +{ + UIView *result = [super hitTest:point withEvent:event]; + + if (result == _adapter.paperView) { + return self; + } + + return result; +} + + (NSMutableSet *)supportedViewManagers { static NSMutableSet *supported = [NSMutableSet setWithObjects:@"Picker", @@ -64,9 +75,9 @@ + (void)supportLegacyViewManagerWithName:(NSString *)componentName - (RCTLegacyViewManagerInteropCoordinator *)coordinator { - auto data = _stateTeller.getData(); - if (data.hasValue()) { - return unwrapManagedObject(data.value().coordinator); + if (_state != nullptr) { + const auto &state = _state->getData(); + return unwrapManagedObject(state.coordinator); } else { return nil; } @@ -74,7 +85,9 @@ - (RCTLegacyViewManagerInteropCoordinator *)coordinator - (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN { - return self.coordinator.componentViewName; + const auto &state = _state->getData(); + RCTLegacyViewManagerInteropCoordinator *coordinator = unwrapManagedObject(state.coordinator); + return coordinator.componentViewName; } #pragma mark - RCTComponentViewProtocol @@ -84,7 +97,7 @@ - (void)prepareForRecycle _adapter = nil; [_viewsToBeMounted removeAllObjects]; [_viewsToBeUnmounted removeAllObjects]; - _stateTeller.invalidate(); + _state.reset(); self.contentView = nil; [super prepareForRecycle]; } @@ -113,7 +126,7 @@ + (ComponentDescriptorProvider)componentDescriptorProvider - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState { - _stateTeller.setConcreteState(state); + _state = std::static_pointer_cast(state); } - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h index 1cd88f8aa62fff..f794b067c75443 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h @@ -15,8 +15,6 @@ @property (nonatomic, weak) id delegate; -#if !TARGET_OS_TV @property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations; -#endif @end diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm index 95f333c2e3f7fe..dc852ff001da6d 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm @@ -40,7 +40,6 @@ - (void)loadView [_touchHandler attachToView:self.view]; } -#if !TARGET_OS_TV - (UIStatusBarStyle)preferredStatusBarStyle { return [RCTSharedApplication() statusBarStyle]; @@ -57,20 +56,6 @@ - (BOOL)prefersStatusBarHidden return [RCTSharedApplication() isStatusBarHidden]; } -- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)())completion -{ - UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO]; - [self.view addSubview:snapshot]; - - [super dismissViewControllerAnimated:flag - completion:^{ - [snapshot removeFromSuperview]; - if (completion) { - completion(); - } - }]; -} - #if RCT_DEV - (UIInterfaceOrientationMask)supportedInterfaceOrientations { @@ -89,6 +74,5 @@ - (UIInterfaceOrientationMask)supportedInterfaceOrientations return _supportedInterfaceOrientations; } #endif // RCT_DEV -#endif // !TARGET_OS_TV @end diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h index 16fbdfb9624ab7..b61196c4c57b0a 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h @@ -5,12 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +#import #import /** * UIView class for root component. */ -@interface RCTModalHostViewComponentView : RCTViewComponentView +@interface RCTModalHostViewComponentView : RCTViewComponentView /** * Subclasses may override this method and present the modal on different view controller. diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm index b4a8b7b2f5239d..cdbb147bba359e 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm @@ -19,7 +19,6 @@ using namespace facebook::react; -#if !TARGET_OS_TV static UIInterfaceOrientationMask supportedOrientationsMask(ModalHostViewSupportedOrientationsMask mask) { UIInterfaceOrientationMask supportedOrientations = 0; @@ -54,7 +53,6 @@ static UIInterfaceOrientationMask supportedOrientationsMask(ModalHostViewSupport return supportedOrientations; } -#endif static std::tuple animationConfiguration(ModalHostViewAnimationType const animation) { @@ -100,9 +98,10 @@ @interface RCTModalHostViewComponentView () onOrientationChange(onOrientationChangeStruct(newBounds)); } - auto newState = ModalHostViewState{RCTSizeFromCGSize(newBounds.size)}; - _stateTeller.updateState(std::move(newState)); + if (_state != nullptr) { + auto newState = ModalHostViewState{RCTSizeFromCGSize(newBounds.size)}; + _state->updateState(std::move(newState)); + } } #pragma mark - RCTComponentViewProtocol @@ -204,7 +217,7 @@ + (ComponentDescriptorProvider)componentDescriptorProvider - (void)prepareForRecycle { [super prepareForRecycle]; - _stateTeller.invalidate(); + _state.reset(); _viewController = nil; _isPresented = NO; } @@ -226,9 +239,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & [super updateProps:props oldProps:oldProps]; } -- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState +- (void)updateState:(facebook::react::State::Shared const &)state + oldState:(facebook::react::State::Shared const &)oldState { - _stateTeller.setConcreteState(state); + _state = std::static_pointer_cast(state); } - (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index diff --git a/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.h b/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.h new file mode 100644 index 00000000000000..62f6d1e61a68c5 --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * UIView class for root component. + */ +@interface RCTPickerComponentView : RCTViewComponentView + +@end + +NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.mm b/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.mm new file mode 100644 index 00000000000000..c77fdfc21ef014 --- /dev/null +++ b/React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.mm @@ -0,0 +1,206 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTPickerComponentView.h" + +#import +#import +#import +#import +#import +#import +#import + +#import "RCTConversions.h" +#import "RCTFabricComponentsPlugins.h" + +using namespace facebook::react; + +@interface RCTPickerComponentView () + +@end + +@implementation RCTPickerComponentView { + UIPickerView *_pickerView; + std::vector _items; + NSInteger _selectedIndex; + NSString *_accessibilityLabel; + NSDictionary *_textAttributes; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + _pickerView = [[UIPickerView alloc] initWithFrame:self.bounds]; + self.contentView = _pickerView; + [self setPropsToDefault]; + } + + return self; +} + +- (void)setPropsToDefault +{ + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _pickerView.delegate = self; + _pickerView.dataSource = self; + _selectedIndex = NSNotFound; + NSMutableParagraphStyle *const paragraphStyle = [NSMutableParagraphStyle new]; + paragraphStyle.alignment = NSTextAlignmentCenter; + _textAttributes = @{ + NSForegroundColorAttributeName : [UIColor blackColor], + NSFontAttributeName : [UIFont systemFontOfSize:21], + NSParagraphStyleAttributeName : paragraphStyle + }; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + _selectedIndex = NSNotFound; +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps +{ + const auto &oldPickerProps = *std::static_pointer_cast(_props); + const auto &newPickerProps = *std::static_pointer_cast(props); + bool needsToReload = false; + + if (oldPickerProps.items != newPickerProps.items) { + _items = newPickerProps.items; + needsToReload = true; + } + + if (oldPickerProps.selectedIndex != newPickerProps.selectedIndex) { + _selectedIndex = newPickerProps.selectedIndex; + [self setSelectedIndex]; + } + + if (oldPickerProps.textAttributes != newPickerProps.textAttributes) { + _textAttributes = RCTNSTextAttributesFromTextAttributes(newPickerProps.getEffectiveTextAttributes()); + needsToReload = true; + } + + // TODO (T75217510) - Figure out testID. + if (oldPickerProps.testID != newPickerProps.testID) { + } + + if (oldPickerProps.accessibilityLabel != newPickerProps.accessibilityLabel) { + _accessibilityLabel = [NSString stringWithUTF8String:newPickerProps.accessibilityLabel.c_str()]; + } + + if (needsToReload) { + [_pickerView reloadAllComponents]; + } + + [super updateProps:props oldProps:oldProps]; +} + +#pragma mark - Native Commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + if ([commandName isEqualToString:@"setNativeSelectedIndex"] && [args objectAtIndex:0]) { + NSNumber *selectedIndex = [args objectAtIndex:0]; + if (_selectedIndex != selectedIndex.integerValue) { + [self setSelectedIndex]; + } + } else { + RCTLogWarn(@"Attempting to send unknown command to Picker component: %@", commandName); + } +} + +- (void)setSelectedIndex +{ + BOOL animated = _selectedIndex != NSNotFound; // Don't animate the initial value. + [_pickerView selectRow:_selectedIndex inComponent:0 animated:animated]; +} + +#pragma mark - UIPickerViewDataSource protocol + +- (NSInteger)numberOfComponentsInPickerView:(__unused UIPickerView *)pickerView +{ + return 1; +} + +- (NSInteger)pickerView:(__unused UIPickerView *)pickerView numberOfRowsInComponent:(__unused NSInteger)component +{ + return _items.size(); +} + +#pragma mark - UIPickerViewDelegate methods + +- (NSString *)pickerView:(__unused UIPickerView *)pickerView + titleForRow:(NSInteger)row + forComponent:(__unused NSInteger)component +{ + return [NSString stringWithUTF8String:_items[row].label.c_str()]; +} + +- (CGFloat)pickerView:(__unused UIPickerView *)pickerView rowHeightForComponent:(NSInteger)__unused component +{ + return ((UIFont *)_textAttributes[NSFontAttributeName]).pointSize + 19; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView + viewForRow:(NSInteger)row + forComponent:(NSInteger)component + reusingView:(UILabel *)label +{ + if (!label) { + label = [[UILabel alloc] initWithFrame:(CGRect){ + CGPointZero, + { + [pickerView rowSizeForComponent:component].width, + [pickerView rowSizeForComponent:component].height, + }}]; + } + NSMutableDictionary *attributes = [_textAttributes mutableCopy]; + // Color can be passed in from or from + // If Picker.Item color is set, use that. Else fall back to Picker style (with black as default). + if (RCTUIColorFromSharedColor(_items[row].textColor)) { + attributes[NSForegroundColorAttributeName] = RCTUIColorFromSharedColor(_items[row].textColor); + } + label.attributedText = [[NSAttributedString alloc] initWithString:[self pickerView:pickerView + titleForRow:row + forComponent:component] + attributes:attributes]; + return label; +} + +- (void)pickerView:(__unused UIPickerView *)pickerView + didSelectRow:(NSInteger)row + inComponent:(__unused NSInteger)component +{ + _selectedIndex = row; + PickerEventEmitter::PickerIOSChangeEvent event = {.newValue = _items[row].value, .newIndex = (int)row}; + if (_eventEmitter) { + std::static_pointer_cast(_eventEmitter)->onChange(event); + } +} + +#pragma mark - UIPickerViewAccessibilityDelegate protocol + +- (NSString *)pickerView:(UIPickerView *)pickerView accessibilityLabelForComponent:(NSInteger)component +{ + return _accessibilityLabel; +} + +@end + +Class RCTPickerCls(void) +{ + return RCTPickerComponentView.class; +} diff --git a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index 4f6ea0e815679c..b0b82ba221b55a 100644 --- a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -35,11 +35,13 @@ Class RCTPullToRefreshViewCls(void) __attribute__((use Class RCTActivityIndicatorViewCls(void) __attribute__((used)); Class RCTSliderCls(void) __attribute__((used)); Class RCTSwitchCls(void) __attribute__((used)); +Class RCTPickerCls(void) __attribute__((used)); Class RCTUnimplementedNativeViewCls(void) __attribute__((used)); Class RCTParagraphCls(void) __attribute__((used)); Class RCTTextInputCls(void) __attribute__((used)); Class RCTInputAccessoryCls(void) __attribute__((used)); Class RCTViewCls(void) __attribute__((used)); +Class RCTImageCls(void) __attribute__((used)); #ifdef __cplusplus } diff --git a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm index a52c8c06e366da..bad4843193a66c 100644 --- a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +++ b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm @@ -24,11 +24,13 @@ {"ActivityIndicatorView", RCTActivityIndicatorViewCls}, {"Slider", RCTSliderCls}, {"Switch", RCTSwitchCls}, + {"Picker", RCTPickerCls}, {"UnimplementedNativeView", RCTUnimplementedNativeViewCls}, {"Paragraph", RCTParagraphCls}, {"TextInput", RCTTextInputCls}, {"InputAccessoryView", RCTInputAccessoryCls}, {"View", RCTViewCls}, + {"Image", RCTImageCls}, }; auto p = sFabricComponentsClassMap.find(name); diff --git a/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm index c54ea89bcac19f..fa362f134a4b6f 100644 --- a/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/SafeAreaView/RCTSafeAreaViewComponentView.mm @@ -10,15 +10,13 @@ #import #import #import -#import "FBRCTFabricComponentsPlugins.h" #import "RCTConversions.h" #import "RCTFabricComponentsPlugins.h" using namespace facebook::react; @implementation RCTSafeAreaViewComponentView { - SafeAreaViewShadowNode::ConcreteStateTeller _stateTeller; - EdgeInsets _lastPaddingStateWasUpdatedWith; + SafeAreaViewShadowNode::ConcreteState::Shared _state; } - (instancetype)initWithFrame:(CGRect)frame @@ -34,7 +32,7 @@ - (instancetype)initWithFrame:(CGRect)frame - (UIEdgeInsets)_safeAreaInsets { - if (@available(iOS 11.0, tvOS 11.0, *)) { + if (@available(iOS 11.0, *)) { return self.safeAreaInsets; } @@ -50,6 +48,10 @@ - (void)safeAreaInsetsDidChange - (void)_updateStateIfNecessary { + if (!_state) { + return; + } + UIEdgeInsets insets = [self _safeAreaInsets]; insets.left = RCTRoundPixelValue(insets.left); insets.top = RCTRoundPixelValue(insets.top); @@ -58,35 +60,47 @@ - (void)_updateStateIfNecessary auto newPadding = RCTEdgeInsetsFromUIEdgeInsets(insets); auto threshold = 1.0 / RCTScreenScale() + 0.01; // Size of a pixel plus some small threshold. - auto deltaPadding = newPadding - _lastPaddingStateWasUpdatedWith; - - if (std::abs(deltaPadding.left) < threshold && std::abs(deltaPadding.top) < threshold && - std::abs(deltaPadding.right) < threshold && std::abs(deltaPadding.bottom) < threshold) { - return; - } - _lastPaddingStateWasUpdatedWith = newPadding; - _stateTeller.updateState(SafeAreaViewState{newPadding}); + _state->updateState( + [=](SafeAreaViewShadowNode::ConcreteState::Data const &oldData) + -> SafeAreaViewShadowNode::ConcreteState::SharedData { + auto oldPadding = oldData.padding; + auto deltaPadding = newPadding - oldPadding; + + if (std::abs(deltaPadding.left) < threshold && std::abs(deltaPadding.top) < threshold && + std::abs(deltaPadding.right) < threshold && std::abs(deltaPadding.bottom) < threshold) { + return nullptr; + } + + auto newData = oldData; + newData.padding = newPadding; + return std::make_shared(newData); + }); } #pragma mark - RCTComponentViewProtocol -- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState ++ (ComponentDescriptorProvider)componentDescriptorProvider { - _stateTeller.setConcreteState(state); - [self _updateStateIfNecessary]; + return concreteComponentDescriptorProvider(); } -- (void)prepareForRecycle +- (void)updateState:(facebook::react::State::Shared const &)state + oldState:(facebook::react::State::Shared const &)oldState { - [super prepareForRecycle]; - _stateTeller.invalidate(); - _lastPaddingStateWasUpdatedWith = {}; + _state = std::static_pointer_cast(state); } -+ (ComponentDescriptorProvider)componentDescriptorProvider +- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask { - return concreteComponentDescriptorProvider(); + [super finalizeUpdates:updateMask]; + [self _updateStateIfNecessary]; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + _state.reset(); } @end diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h index 3fece84488fa45..fa0c29dd6d97a6 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h @@ -12,6 +12,17 @@ NS_ASSUME_NONNULL_BEGIN +/* + * Many `UIScrollView` customizations normally require creating a subclass which is not always convenient. + * `RCTEnhancedScrollView` has a delegate (conforming to this protocol) that allows customizing such behaviors without + * creating a subclass. + */ +@protocol RCTEnhancedScrollViewOverridingDelegate + +- (BOOL)touchesShouldCancelInContentView:(UIView *)view; + +@end + /* * `UIScrollView` subclass which has some improvements and tweaks * which are not directly related to React Native. @@ -31,6 +42,7 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, strong, readonly) RCTGenericDelegateSplitter> *delegateSplitter; +@property (nonatomic, weak) id overridingDelegate; @property (nonatomic, assign) BOOL pinchGestureEnabled; @property (nonatomic, assign) BOOL centerContent; @property (nonatomic, assign) CGFloat snapToInterval; @@ -40,6 +52,12 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL snapToEnd; @property (nonatomic, copy) NSArray *snapToOffsets; +/* + * Makes `setContentOffset:` method no-op when given `block` is executed. + * The block is being executed synchronously. + */ +- (void)preserveContentOffsetWithBlock:(void (^)())block; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm index 9f6d9b8ac1a101..2e917090b97e1c 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm @@ -13,6 +13,7 @@ @interface RCTEnhancedScrollView () @implementation RCTEnhancedScrollView { __weak id _publicDelegate; + BOOL _isSetContentOffsetDisabled; } + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key @@ -46,6 +47,17 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } +- (void)preserveContentOffsetWithBlock:(void (^)())block +{ + if (!block) { + return; + } + + _isSetContentOffsetDisabled = YES; + block(); + _isSetContentOffsetDisabled = NO; +} + /* * Automatically centers the content such that if the content is smaller than the * ScrollView, we force it to be centered, but when you zoom or the content otherwise @@ -54,6 +66,10 @@ - (instancetype)initWithFrame:(CGRect)frame */ - (void)setContentOffset:(CGPoint)contentOffset { + if (_isSetContentOffsetDisabled) { + return; + } + if (_centerContent && !CGSizeEqualToSize(self.contentSize, CGSizeZero)) { CGSize scrollViewSize = self.bounds.size; if (self.contentSize.width <= scrollViewSize.width) { @@ -69,6 +85,15 @@ - (void)setContentOffset:(CGPoint)contentOffset RCTSanitizeNaNValue(contentOffset.y, @"scrollView.contentOffset.y")); } +- (BOOL)touchesShouldCancelInContentView:(UIView *)view +{ + if ([_overridingDelegate respondsToSelector:@selector(touchesShouldCancelInContentView:)]) { + return [_overridingDelegate touchesShouldCancelInContentView:view]; + } + + return [super touchesShouldCancelInContentView:view]; +} + #pragma mark - RCTGenericDelegateSplitter - (void)setPrivateDelegate:(id)delegate @@ -215,9 +240,9 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView // Pick snap point based on direction and proximity CGFloat fractionalIndex = (targetContentOffsetAlongAxis + alignmentOffset) / snapToIntervalF; - NSInteger snapIndex = velocityAlongAxis > 0.0 - ? ceil(fractionalIndex) - : velocityAlongAxis < 0.0 ? floor(fractionalIndex) : round(fractionalIndex); + NSInteger snapIndex = velocityAlongAxis > 0.0 ? ceil(fractionalIndex) + : velocityAlongAxis < 0.0 ? floor(fractionalIndex) + : round(fractionalIndex); CGFloat newTargetContentOffset = (snapIndex * snapToIntervalF) - alignmentOffset; // Set new targetContentOffset diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm index afcec45afa68cc..6d89e699307df8 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm @@ -16,7 +16,7 @@ #import #import -#import "FBRCTFabricComponentsPlugins.h" +#import "RCTFabricComponentsPlugins.h" using namespace facebook::react; diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 859b4582980e8a..2783342928d685 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -28,6 +28,30 @@ static CGFloat const kClippingLeeway = 44.0; +static UIScrollViewKeyboardDismissMode RCTUIKeyboardDismissModeFromProps(ScrollViewProps const &props) +{ + switch (props.keyboardDismissMode) { + case ScrollViewKeyboardDismissMode::None: + return UIScrollViewKeyboardDismissModeNone; + case ScrollViewKeyboardDismissMode::OnDrag: + return UIScrollViewKeyboardDismissModeOnDrag; + case ScrollViewKeyboardDismissMode::Interactive: + return UIScrollViewKeyboardDismissModeInteractive; + } +} + +static UIScrollViewIndicatorStyle RCTUIScrollViewIndicatorStyleFromProps(ScrollViewProps const &props) +{ + switch (props.indicatorStyle) { + case ScrollViewIndicatorStyle::Default: + return UIScrollViewIndicatorStyleDefault; + case ScrollViewIndicatorStyle::Black: + return UIScrollViewIndicatorStyleBlack; + case ScrollViewIndicatorStyle::White: + return UIScrollViewIndicatorStyleWhite; + } +} + static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteger tag) { static uint16_t coalescingKey = 0; @@ -43,12 +67,16 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg [[RCTBridge currentBridge].eventDispatcher sendEvent:scrollEvent]; } -@interface RCTScrollViewComponentView () +@interface RCTScrollViewComponentView () < + UIScrollViewDelegate, + RCTScrollViewProtocol, + RCTScrollableProtocol, + RCTEnhancedScrollViewOverridingDelegate> @end @implementation RCTScrollViewComponentView { - ScrollViewShadowNode::ConcreteStateTeller _stateTeller; + ScrollViewShadowNode::ConcreteState::Shared _state; CGSize _contentSize; NSTimeInterval _lastScrollEventDispatchTime; NSTimeInterval _scrollEventThrottle; @@ -83,6 +111,7 @@ - (instancetype)initWithFrame:(CGRect)frame _scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _scrollView.delaysContentTouches = NO; + ((RCTEnhancedScrollView *)_scrollView).overridingDelegate = self; _isUserTriggeredScrolling = NO; [self addSubview:_scrollView]; @@ -149,8 +178,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // MAP_SCROLL_VIEW_PROP(automaticallyAdjustContentInsets); MAP_SCROLL_VIEW_PROP(decelerationRate); MAP_SCROLL_VIEW_PROP(directionalLockEnabled); - // MAP_SCROLL_VIEW_PROP(indicatorStyle); - // MAP_SCROLL_VIEW_PROP(keyboardDismissMode); MAP_SCROLL_VIEW_PROP(maximumZoomScale); MAP_SCROLL_VIEW_PROP(minimumZoomScale); MAP_SCROLL_VIEW_PROP(scrollEnabled); @@ -160,6 +187,14 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & MAP_SCROLL_VIEW_PROP(showsHorizontalScrollIndicator); MAP_SCROLL_VIEW_PROP(showsVerticalScrollIndicator); + if (oldScrollViewProps.scrollIndicatorInsets != newScrollViewProps.scrollIndicatorInsets) { + _scrollView.scrollIndicatorInsets = RCTUIEdgeInsetsFromEdgeInsets(newScrollViewProps.scrollIndicatorInsets); + } + + if (oldScrollViewProps.indicatorStyle != newScrollViewProps.indicatorStyle) { + _scrollView.indicatorStyle = RCTUIScrollViewIndicatorStyleFromProps(newScrollViewProps); + } + if (oldScrollViewProps.scrollEventThrottle != newScrollViewProps.scrollEventThrottle) { // Zero means "send value only once per significant logical event". // Prop value is in milliseconds. @@ -219,7 +254,9 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & MAP_SCROLL_VIEW_PROP(disableIntervalMomentum); MAP_SCROLL_VIEW_PROP(snapToInterval); - // MAP_SCROLL_VIEW_PROP(scrollIndicatorInsets); + if (oldScrollViewProps.keyboardDismissMode != newScrollViewProps.keyboardDismissMode) { + scrollView.keyboardDismissMode = RCTUIKeyboardDismissModeFromProps(newScrollViewProps); + } [super updateProps:props oldProps:oldProps]; } @@ -227,8 +264,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState { assert(std::dynamic_pointer_cast(state)); - _stateTeller.setConcreteState(state); - auto data = _stateTeller.getData().value(); + _state = std::static_pointer_cast(state); + auto &data = _state->getData(); auto contentOffset = RCTCGPointFromPoint(data.contentOffset); if (!oldState && !CGPointEqualToPoint(contentOffset, CGPointZero)) { @@ -243,7 +280,26 @@ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const & _contentSize = contentSize; _containerView.frame = CGRect{CGPointZero, contentSize}; - _scrollView.contentSize = contentSize; + + [self _preserveContentOffsetIfNeededWithBlock:^{ + self->_scrollView.contentSize = contentSize; + }]; +} + +/* + * Disables programmatical changing of ScrollView's `contentOffset` if a touch gesture is in progress. + */ +- (void)_preserveContentOffsetIfNeededWithBlock:(void (^)())block +{ + if (!block) { + return; + } + + if (!_isUserTriggeredScrolling) { + return block(); + } + + [((RCTEnhancedScrollView *)_scrollView) preserveContentOffsetWithBlock:block]; } - (void)mountChildComponentView:(UIView *)childComponentView index:(NSInteger)index @@ -284,11 +340,14 @@ - (ScrollViewMetrics)_scrollViewMetrics - (void)_updateStateWithContentOffset { + if (!_state) { + return; + } auto contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset); - _stateTeller.updateState([contentOffset](ScrollViewShadowNode::ConcreteState::Data const &data) { + _state->updateState([contentOffset](ScrollViewShadowNode::ConcreteState::Data const &data) { auto newData = data; newData.contentOffset = contentOffset; - return newData; + return std::make_shared(newData); }); } @@ -296,13 +355,20 @@ - (void)prepareForRecycle { const auto &props = *std::static_pointer_cast(_props); _scrollView.contentOffset = RCTCGPointFromPoint(props.contentOffset); - _stateTeller.invalidate(); + _state.reset(); _isUserTriggeredScrolling = NO; [super prepareForRecycle]; } #pragma mark - UIScrollViewDelegate +- (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view +{ + // Historically, `UIScrollView`s in React Native do not cancel touches + // started on `UIControl`-based views (as normal iOS `UIScrollView`s do). + return YES; +} + - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (!_isUserTriggeredScrolling) { @@ -392,6 +458,7 @@ - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self _forceDispatchNextScrollEvent]; + [self scrollViewDidScroll:scrollView]; if (!_eventEmitter) { return; @@ -424,7 +491,12 @@ - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UI [self _updateStateWithContentOffset]; } -#pragma mark - UIScrollViewDelegate +- (UIView *)viewForZoomingInScrollView:(__unused UIScrollView *)scrollView +{ + return _containerView; +} + +#pragma mark - - (void)_forceDispatchNextScrollEvent { @@ -445,7 +517,32 @@ - (void)flashScrollIndicators - (void)scrollTo:(double)x y:(double)y animated:(BOOL)animated { - [_scrollView setContentOffset:CGPointMake(x, y) animated:animated]; + CGPoint offset = CGPointMake(x, y); + if (!CGPointEqualToPoint(_scrollView.contentOffset, offset)) { + CGRect maxRect = CGRectMake( + fmin(-_scrollView.contentInset.left, 0), + fmin(-_scrollView.contentInset.top, 0), + fmax( + _scrollView.contentSize.width - _scrollView.bounds.size.width + _scrollView.contentInset.right + + fmax(_scrollView.contentInset.left, 0), + 0.01), + fmax( + _scrollView.contentSize.height - _scrollView.bounds.size.height + _scrollView.contentInset.bottom + + fmax(_scrollView.contentInset.top, 0), + 0.01)); // Make width and height greater than 0 + + const auto &props = *std::static_pointer_cast(_props); + if (!CGRectContainsPoint(maxRect, offset) && !props.scrollToOverflowEnabled) { + CGFloat localX = fmax(offset.x, CGRectGetMinX(maxRect)); + localX = fmin(localX, CGRectGetMaxX(maxRect)); + CGFloat localY = fmax(offset.y, CGRectGetMinY(maxRect)); + localY = fmin(localY, CGRectGetMaxY(maxRect)); + offset = CGPointMake(localX, localY); + } + + [self _forceDispatchNextScrollEvent]; + [_scrollView setContentOffset:offset animated:animated]; + } } - (void)scrollToEnd:(BOOL)animated @@ -498,16 +595,15 @@ - (void)_remountChildren visibleFrame.size.width *= scale; visibleFrame.size.height *= scale; +#ifndef NDEBUG + NSMutableArray *> *expectedSubviews = [NSMutableArray new]; +#endif + NSInteger mountedIndex = 0; for (UIView *componentView in _childComponentViews) { BOOL shouldBeMounted = YES; BOOL isMounted = componentView.superview != nil; - // If a view is mounted, it must be mounted exactly at `mountedIndex` position. - RCTAssert( - !isMounted || [_containerView.subviews objectAtIndex:mountedIndex] == componentView, - @"Attempt to unmount improperly mounted component view."); - // It's simpler and faster to not mess with views that are not `RCTViewComponentView` subclasses. if ([componentView isKindOfClass:[RCTViewComponentView class]]) { RCTViewComponentView *viewComponentView = (RCTViewComponentView *)componentView; @@ -529,7 +625,24 @@ - (void)_remountChildren if (shouldBeMounted) { mountedIndex++; } + +#ifndef NDEBUG + if (shouldBeMounted) { + [expectedSubviews addObject:componentView]; + } +#endif + } + +#ifndef NDEBUG + RCTAssert( + _containerView.subviews.count == expectedSubviews.count, + @"-[RCTScrollViewComponentView _remountChildren]: Inconsistency detected."); + for (NSInteger i = 0; i < expectedSubviews.count; i++) { + RCTAssert( + [_containerView.subviews objectAtIndex:i] == [expectedSubviews objectAtIndex:i], + @"-[RCTScrollViewComponentView _remountChildren]: Inconsistency detected."); } +#endif } #pragma mark - RCTScrollableProtocol @@ -553,7 +666,7 @@ - (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated - (void)zoomToRect:(CGRect)rect animated:(BOOL)animated { - // Not implemented. + [_scrollView zoomToRect:rect animated:animated]; } - (void)addScrollListener:(NSObject *)scrollListener diff --git a/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm b/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm index fea74e18c146fc..f9c4d89f9b10d9 100644 --- a/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Slider/RCTSliderComponentView.mm @@ -7,13 +7,15 @@ #import "RCTSliderComponentView.h" +#import #import #import + #import #import #import -#import "FBRCTFabricComponentsPlugins.h" +#import "RCTFabricComponentsPlugins.h" using namespace facebook::react; @@ -108,12 +110,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & const auto &oldSliderProps = *std::static_pointer_cast(_props); const auto &newSliderProps = *std::static_pointer_cast(props); - // `value` - if (oldSliderProps.value != newSliderProps.value) { - _sliderView.value = newSliderProps.value; - _previousValue = newSliderProps.value; - } - // `minimumValue` if (oldSliderProps.minimumValue != newSliderProps.minimumValue) { _sliderView.minimumValue = newSliderProps.minimumValue; @@ -124,6 +120,12 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & _sliderView.maximumValue = newSliderProps.maximumValue; } + // `value` + if (oldSliderProps.value != newSliderProps.value) { + _sliderView.value = newSliderProps.value; + _previousValue = newSliderProps.value; + } + // `disabled` if (oldSliderProps.disabled != newSliderProps.disabled) { _sliderView.enabled = !newSliderProps.disabled; @@ -131,17 +133,17 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // `thumbTintColor` if (oldSliderProps.thumbTintColor != newSliderProps.thumbTintColor) { - _sliderView.thumbTintColor = [UIColor colorWithCGColor:newSliderProps.thumbTintColor.get()]; + _sliderView.thumbTintColor = RCTUIColorFromSharedColor(newSliderProps.thumbTintColor); } // `minimumTrackTintColor` if (oldSliderProps.minimumTrackTintColor != newSliderProps.minimumTrackTintColor) { - _sliderView.minimumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.minimumTrackTintColor.get()]; + _sliderView.minimumTrackTintColor = RCTUIColorFromSharedColor(newSliderProps.minimumTrackTintColor); } // `maximumTrackTintColor` if (oldSliderProps.maximumTrackTintColor != newSliderProps.maximumTrackTintColor) { - _sliderView.maximumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.maximumTrackTintColor.get()]; + _sliderView.maximumTrackTintColor = RCTUIColorFromSharedColor(newSliderProps.maximumTrackTintColor); } [super updateProps:props oldProps:oldProps]; @@ -298,7 +300,7 @@ - (void)onChange:(UISlider *)sender withContinuous:(BOOL)continuous const auto &props = *std::static_pointer_cast(_props); - if (props.step > 0 && value <= (props.maximumValue - props.minimumValue)) { + if (props.step > 0 && props.step <= (props.maximumValue - props.minimumValue)) { value = MAX( props.minimumValue, MIN(props.maximumValue, props.minimumValue + round((value - props.minimumValue) / props.step) * props.step)); @@ -320,7 +322,7 @@ - (void)onChange:(UISlider *)sender withContinuous:(BOOL)continuous #pragma mark - RCTImageResponseDelegate -- (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer +- (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(void const *)observer { if (observer == &_trackImageResponseObserverProxy) { self.trackImage = image; diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index 2538f040476c78..970414806e1cd9 100644 --- a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -7,12 +7,14 @@ #import "RCTSwitchComponentView.h" +#import + #import #import #import #import -#import "FBRCTFabricComponentsPlugins.h" +#import "RCTFabricComponentsPlugins.h" using namespace facebook::react; @@ -21,36 +23,31 @@ @interface RCTSwitchComponentView () @implementation RCTSwitchComponentView { UISwitch *_switchView; + BOOL _isInitialValueSet; } - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _switchView = [[UISwitch alloc] initWithFrame:self.bounds]; [_switchView addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged]; self.contentView = _switchView; - - [self setPropsToDefault]; } return self; } -- (void)setPropsToDefault -{ - static const auto defaultProps = std::make_shared(); - _props = defaultProps; - _switchView.on = defaultProps->value; -} - #pragma mark - RCTComponentViewProtocol - (void)prepareForRecycle { [super prepareForRecycle]; - [self setPropsToDefault]; + _isInitialValueSet = NO; } + (ComponentDescriptorProvider)componentDescriptorProvider @@ -65,7 +62,9 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // `value` if (oldSwitchProps.value != newSwitchProps.value) { - _switchView.on = newSwitchProps.value; + BOOL shouldAnimate = _isInitialValueSet == YES; + [_switchView setOn:newSwitchProps.value animated:shouldAnimate]; + _isInitialValueSet = YES; } // `disabled` @@ -75,17 +74,17 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // `tintColor` if (oldSwitchProps.tintColor != newSwitchProps.tintColor) { - _switchView.tintColor = [UIColor colorWithCGColor:newSwitchProps.tintColor.get()]; + _switchView.tintColor = RCTUIColorFromSharedColor(newSwitchProps.tintColor); } // `onTintColor if (oldSwitchProps.onTintColor != newSwitchProps.onTintColor) { - _switchView.onTintColor = [UIColor colorWithCGColor:newSwitchProps.onTintColor.get()]; + _switchView.onTintColor = RCTUIColorFromSharedColor(newSwitchProps.onTintColor); } // `thumbTintColor` if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) { - _switchView.thumbTintColor = [UIColor colorWithCGColor:newSwitchProps.thumbTintColor.get()]; + _switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor); } [super updateProps:props oldProps:oldProps]; diff --git a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index 438e513c7aadbf..48fa05ca37afa9 100644 --- a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -25,7 +25,7 @@ using namespace facebook::react; @implementation RCTParagraphComponentView { - ParagraphShadowNode::ConcreteStateTeller _stateTeller; + ParagraphShadowNode::ConcreteState::Shared _state; ParagraphAttributes _paragraphAttributes; RCTParagraphComponentAccessibilityProvider *_accessibilityProvider; } @@ -36,7 +36,6 @@ - (instancetype)initWithFrame:(CGRect)frame static const auto defaultProps = std::make_shared(); _props = defaultProps; - self.isAccessibilityElement = YES; self.opaque = NO; self.contentMode = UIViewContentModeRedraw; } @@ -58,12 +57,11 @@ - (NSString *)description - (NSAttributedString *_Nullable)attributedText { - auto data = _stateTeller.getData(); - if (!data.hasValue()) { + if (!_state) { return nil; } - return RCTNSAttributedStringFromAttributedString(data.value().attributedString); + return RCTNSAttributedStringFromAttributedString(_state->getData().attributedString); } #pragma mark - RCTComponentViewProtocol @@ -75,8 +73,9 @@ + (ComponentDescriptorProvider)componentDescriptorProvider + (std::vector)supplementalComponentDescriptorProviders { - return {concreteComponentDescriptorProvider(), - concreteComponentDescriptorProvider()}; + return { + concreteComponentDescriptorProvider(), + concreteComponentDescriptorProvider()}; } - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps @@ -91,24 +90,23 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState { - _stateTeller.setConcreteState(state); + _state = std::static_pointer_cast(state); [self setNeedsDisplay]; } - (void)prepareForRecycle { [super prepareForRecycle]; - _stateTeller.invalidate(); + _state.reset(); } - (void)drawRect:(CGRect)rect { - auto data = _stateTeller.getData(); - if (!data.hasValue()) { + if (!_state) { return; } - auto textLayoutManager = data.value().layoutManager; + auto textLayoutManager = _state->getData().layoutManager; assert(textLayoutManager && "TextLayoutManager must not be `nullptr`."); if (!textLayoutManager) { @@ -120,32 +118,34 @@ - (void)drawRect:(CGRect)rect CGRect frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame()); - [nativeTextLayoutManager drawAttributedString:data.value().attributedString + [nativeTextLayoutManager drawAttributedString:_state->getData().attributedString paragraphAttributes:_paragraphAttributes frame:frame]; } #pragma mark - Accessibility -- (NSString *)accessibilityLabel +- (BOOL)isAccessibilityElement { - NSString *superAccessibilityLabel = RCTNSStringFromStringNilIfEmpty(_props->accessibilityLabel); - if (superAccessibilityLabel) { - return superAccessibilityLabel; - } + // All accessibility functionality of the component is implemented in `accessibilityElements` method below. + // Hence to avoid calling all other methods from `UIAccessibilityContainer` protocol (most of them have default + // implementations), we return here `NO`. + return NO; +} - auto data = _stateTeller.getData(); +- (NSArray *)accessibilityElements +{ + auto const ¶graphProps = *std::static_pointer_cast(_props); - if (!data.hasValue()) { - return nil; + // If the component is not `accessible`, we return an empty array. + // We do this because logically all nested components represent the content of the component; + // in other words, all nested components individually have no sense without the . + if (!_state || !paragraphProps.accessible) { + return [NSArray new]; } - return RCTNSStringFromString(data.value().attributedString.getString()); -} + auto &data = _state->getData(); -- (NSArray *)accessibilityElements -{ - auto data = _stateTeller.getData().value(); if (![_accessibilityProvider isUpToDate:data.attributedString]) { RCTTextLayoutManager *textLayoutManager = (RCTTextLayoutManager *)unwrapManagedObject(data.layoutManager->getNativeTextLayoutManager()); @@ -157,7 +157,6 @@ - (NSArray *)accessibilityElements view:self]; } - self.isAccessibilityElement = NO; return _accessibilityProvider.accessibilityElements; } @@ -166,14 +165,15 @@ - (UIAccessibilityTraits)accessibilityTraits return [super accessibilityTraits] | UIAccessibilityTraitStaticText; } +#pragma mark - RCTTouchableComponentViewProtocol + - (SharedTouchEventEmitter)touchEventEmitterAtPoint:(CGPoint)point { - auto data = _stateTeller.getData(); - if (!data.hasValue()) { + if (!_state) { return _eventEmitter; } - auto textLayoutManager = data.value().layoutManager; + auto textLayoutManager = _state->getData().layoutManager; assert(textLayoutManager && "TextLayoutManager must not be `nullptr`."); @@ -185,7 +185,7 @@ - (SharedTouchEventEmitter)touchEventEmitterAtPoint:(CGPoint)point (RCTTextLayoutManager *)unwrapManagedObject(textLayoutManager->getNativeTextLayoutManager()); CGRect frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame()); - auto eventEmitter = [nativeTextLayoutManager getEventEmitterWithAttributeString:data.value().attributedString + auto eventEmitter = [nativeTextLayoutManager getEventEmitterWithAttributeString:_state->getData().attributedString paragraphAttributes:_paragraphAttributes frame:frame atPoint:point]; diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 013226237a6436..f5d280a59e9206 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -29,7 +29,7 @@ @interface RCTTextInputComponentView () *_backedTextInputView; NSUInteger _mostRecentEventCount; NSAttributedString *_lastStringStateWasUpdatedWith; @@ -210,25 +210,27 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & } [super updateProps:props oldProps:oldProps]; + + [self setDefaultInputAccessoryView]; } - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState { - _stateTeller.setConcreteState(state); + _state = std::static_pointer_cast(state); - if (!_stateTeller.isValid()) { + if (!_state) { assert(false && "State is `null` for component."); _backedTextInputView.attributedText = nil; return; } - auto data = _stateTeller.getData().value(); + auto data = _state->getData(); if (!oldState) { - _mostRecentEventCount = data.mostRecentEventCount; + _mostRecentEventCount = _state->getData().mostRecentEventCount; } - if (_mostRecentEventCount == data.mostRecentEventCount) { + if (_mostRecentEventCount == _state->getData().mostRecentEventCount) { _comingFromJS = YES; [self _setAttributedString:RCTNSAttributedStringFromAttributedStringBox(data.attributedStringBox)]; _comingFromJS = NO; @@ -249,7 +251,7 @@ - (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics - (void)prepareForRecycle { [super prepareForRecycle]; - _stateTeller.invalidate(); + _state.reset(); _backedTextInputView.attributedText = nil; _mostRecentEventCount = 0; _comingFromJS = NO; @@ -429,6 +431,50 @@ - (void)setTextAndSelection:(NSInteger)eventCount _comingFromJS = NO; } +#pragma mark - Default input accessory view + +- (void)setDefaultInputAccessoryView +{ + UIKeyboardType keyboardType = _backedTextInputView.keyboardType; + + // These keyboard types (all are number pads) don't have a "Done" button by default, + // so we create an `inputAccessoryView` with this button for them. + BOOL shouldHaveInputAccesoryView = + (keyboardType == UIKeyboardTypeNumberPad || keyboardType == UIKeyboardTypePhonePad || + keyboardType == UIKeyboardTypeDecimalPad || keyboardType == UIKeyboardTypeASCIICapableNumberPad) && + _backedTextInputView.returnKeyType == UIReturnKeyDone; + + if ((_backedTextInputView.inputAccessoryView != nil) == shouldHaveInputAccesoryView) { + return; + } + + if (shouldHaveInputAccesoryView) { + UIToolbar *toolbarView = [[UIToolbar alloc] init]; + [toolbarView sizeToFit]; + UIBarButtonItem *flexibleSpace = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + UIBarButtonItem *doneButton = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(handleInputAccessoryDoneButton)]; + toolbarView.items = @[ flexibleSpace, doneButton ]; + _backedTextInputView.inputAccessoryView = toolbarView; + } else { + _backedTextInputView.inputAccessoryView = nil; + } + + if (_backedTextInputView.isFirstResponder) { + [_backedTextInputView reloadInputViews]; + } +} + +- (void)handleInputAccessoryDoneButton +{ + if ([self textInputShouldReturn]) { + [_backedTextInputView endEditing:YES]; + } +} + #pragma mark - Other - (TextInputMetrics)_textInputMetrics @@ -442,17 +488,16 @@ - (TextInputMetrics)_textInputMetrics - (void)_updateState { - if (!_stateTeller.isValid()) { + if (!_state) { return; } - NSAttributedString *attributedString = _backedTextInputView.attributedText; - auto data = _stateTeller.getData().value(); + auto data = _state->getData(); _lastStringStateWasUpdatedWith = attributedString; data.attributedStringBox = RCTAttributedStringBoxFromNSAttributedString(attributedString); _mostRecentEventCount += _comingFromJS ? 0 : 1; data.mostRecentEventCount = _mostRecentEventCount; - _stateTeller.updateState(std::move(data)); + _state->updateState(std::move(data)); } - (AttributedString::Range)_selectionRange @@ -468,7 +513,9 @@ - (void)_updateState - (void)_setAttributedString:(NSAttributedString *)attributedString { UITextRange *selectedRange = [_backedTextInputView selectedTextRange]; - _backedTextInputView.attributedText = attributedString; + if (![self _textOf:attributedString equals:_backedTextInputView.attributedText]) { + _backedTextInputView.attributedText = attributedString; + } if (_lastStringStateWasUpdatedWith.length == attributedString.length) { // Calling `[_backedTextInputView setAttributedText]` moves caret // to the end of text input field. This cancels any selection as well @@ -490,6 +537,38 @@ - (void)_setMultiline:(BOOL)multiline [self addSubview:_backedTextInputView]; } +- (BOOL)_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText +{ + // When the dictation is running we can't update the attributed text on the backed up text view + // because setting the attributed string will kill the dictation. This means that we can't impose + // the settings on a dictation. + // Similarly, when the user is in the middle of inputting some text in Japanese/Chinese, there will be styling on the + // text that we should disregard. See + // https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange?language=objc for more info. If + // the user added an emoji, the system adds a font attribute for the emoji and stores the original font in + // NSOriginalFont. Lastly, when entering a password, etc., there will be additional styling on the field as the native + // text view handles showing the last character for a split second. + __block BOOL fontHasBeenUpdatedBySystem = false; + [oldText enumerateAttribute:@"NSOriginalFont" + inRange:NSMakeRange(0, oldText.length) + options:0 + usingBlock:^(id value, NSRange range, BOOL *stop) { + if (value) { + fontHasBeenUpdatedBySystem = true; + } + }]; + + BOOL shouldFallbackToBareTextComparison = + [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || + _backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem; + + if (shouldFallbackToBareTextComparison) { + return ([newText.string isEqualToString:oldText.string]); + } else { + return ([newText isEqualToAttributedString:oldText]); + } +} + @end Class RCTTextInputCls(void) diff --git a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm index d7eaa6c62a54fc..04e426d7ab9e5b 100644 --- a/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/UnimplementedView/RCTUnimplementedViewComponentView.mm @@ -16,7 +16,7 @@ #import -#import "FBRCTFabricComponentsPlugins.h" +#import "RCTFabricComponentsPlugins.h" using namespace facebook::react; diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index c574b1752c7ff8..a58d7f288c6d73 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -8,6 +8,7 @@ #import #import +#import #import #import #import diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index f90289c4d6c060..dce5d37e5c91a8 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -7,10 +7,12 @@ #import "RCTViewComponentView.h" +#import +#import + #import #import #import -#import #import #import #import @@ -21,6 +23,7 @@ @implementation RCTViewComponentView { UIColor *_backgroundColor; CALayer *_borderLayer; BOOL _needsInvalidateLayer; + NSSet *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN; } - (instancetype)initWithFrame:(CGRect)frame @@ -28,6 +31,7 @@ - (instancetype)initWithFrame:(CGRect)frame if (self = [super initWithFrame:frame]) { static auto const defaultProps = std::make_shared(); _props = defaultProps; + self.multipleTouchEnabled = YES; } return self; } @@ -83,6 +87,8 @@ + (ComponentDescriptorProvider)componentDescriptorProvider - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps { + RCTAssert(props, @"`props` must not be `null`."); + #ifndef NS_BLOCK_ASSERTIONS auto propsRawPtr = _props.get(); RCTAssert( @@ -100,7 +106,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & BOOL needsInvalidateLayer = NO; // `opacity` - if (oldViewProps.opacity != newViewProps.opacity) { + if (oldViewProps.opacity != newViewProps.opacity && + ![_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"opacity"]) { self.layer.opacity = (CGFloat)newViewProps.opacity; needsInvalidateLayer = YES; } @@ -118,7 +125,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // `shadowColor` if (oldViewProps.shadowColor != newViewProps.shadowColor) { - CGColorRef shadowColor = RCTCGColorRefFromSharedColor(newViewProps.shadowColor); + CGColorRef shadowColor = RCTCreateCGColorRefFromSharedColor(newViewProps.shadowColor); self.layer.shadowColor = shadowColor; CGColorRelease(shadowColor); needsInvalidateLayer = YES; @@ -159,17 +166,19 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & } // `transform` - if (oldViewProps.transform != newViewProps.transform) { + if (oldViewProps.transform != newViewProps.transform && + ![_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"transform"]) { self.layer.transform = RCTCATransform3DFromTransformMatrix(newViewProps.transform); self.layer.allowsEdgeAntialiasing = newViewProps.transform != Transform::Identity(); } // `hitSlop` if (oldViewProps.hitSlop != newViewProps.hitSlop) { - self.hitTestEdgeInsets = {-newViewProps.hitSlop.top, - -newViewProps.hitSlop.left, - -newViewProps.hitSlop.bottom, - -newViewProps.hitSlop.right}; + self.hitTestEdgeInsets = { + -newViewProps.hitSlop.top, + -newViewProps.hitSlop.left, + -newViewProps.hitSlop.bottom, + -newViewProps.hitSlop.right}; } // `overflow` @@ -240,6 +249,11 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & #endif } + // `testId` + if (oldViewProps.testId != newViewProps.testId) { + self.accessibilityIdentifier = RCTNSStringFromString(newViewProps.testId); + } + _needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer; _props = std::static_pointer_cast(props); @@ -284,9 +298,30 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask - (void)prepareForRecycle { [super prepareForRecycle]; + + // If view was managed by animated, its props need to align with UIView's properties. + auto const &props = *std::static_pointer_cast(_props); + if ([_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"transform"]) { + self.layer.transform = RCTCATransform3DFromTransformMatrix(props.transform); + } + if ([_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"opacity"]) { + self.layer.opacity = (CGFloat)props.opacity; + } + + _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = nil; _eventEmitter.reset(); } +- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(NSSet *_Nullable)props +{ + _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = props; +} + +- (NSSet *_Nullable)propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN +{ + return _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN; +} + - (UIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event { // This is a classic textbook implementation of `hitTest:` with a couple of improvements: @@ -301,7 +336,13 @@ - (UIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event BOOL isPointInside = [self pointInside:point withEvent:event]; - if (self.clipsToBounds && !isPointInside) { + BOOL clipsToBounds = self.clipsToBounds; + + if (RCTExperimentGetOptimizedHitTesting()) { + clipsToBounds = clipsToBounds || _layoutMetrics.overflowInset == EdgeInsets{}; + } + + if (clipsToBounds && !isPointInside) { return nil; } @@ -332,18 +373,28 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event static RCTCornerRadii RCTCornerRadiiFromBorderRadii(BorderRadii borderRadii) { - return RCTCornerRadii{.topLeft = (CGFloat)borderRadii.topLeft, - .topRight = (CGFloat)borderRadii.topRight, - .bottomLeft = (CGFloat)borderRadii.bottomLeft, - .bottomRight = (CGFloat)borderRadii.bottomRight}; + return RCTCornerRadii{ + .topLeft = (CGFloat)borderRadii.topLeft, + .topRight = (CGFloat)borderRadii.topRight, + .bottomLeft = (CGFloat)borderRadii.bottomLeft, + .bottomRight = (CGFloat)borderRadii.bottomRight}; +} + +static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(BorderColors borderColors) +{ + return RCTBorderColors{ + .top = RCTCreateCGColorRefFromSharedColor(borderColors.top), + .left = RCTCreateCGColorRefFromSharedColor(borderColors.left), + .bottom = RCTCreateCGColorRefFromSharedColor(borderColors.bottom), + .right = RCTCreateCGColorRefFromSharedColor(borderColors.right)}; } -static RCTBorderColors RCTBorderColorsFromBorderColors(BorderColors borderColors) +static void RCTReleaseRCTBorderColors(RCTBorderColors borderColors) { - return RCTBorderColors{.top = RCTCGColorRefUnretainedFromSharedColor(borderColors.top), - .left = RCTCGColorRefUnretainedFromSharedColor(borderColors.left), - .bottom = RCTCGColorRefUnretainedFromSharedColor(borderColors.bottom), - .right = RCTCGColorRefUnretainedFromSharedColor(borderColors.right)}; + CGColorRelease(borderColors.top); + CGColorRelease(borderColors.left); + CGColorRelease(borderColors.bottom); + CGColorRelease(borderColors.right); } static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) @@ -406,7 +457,7 @@ - (void)invalidateLayer } layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left; - CGColorRef borderColor = RCTCGColorRefFromSharedColor(borderMetrics.borderColors.left); + CGColorRef borderColor = RCTCreateCGColorRefFromSharedColor(borderMetrics.borderColors.left); layer.borderColor = borderColor; CGColorRelease(borderColor); layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft; @@ -425,23 +476,27 @@ - (void)invalidateLayer layer.borderColor = nil; layer.cornerRadius = 0; + RCTBorderColors borderColors = RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors); + UIImage *image = RCTGetBorderImage( RCTBorderStyleFromBorderStyle(borderMetrics.borderStyles.left), layer.bounds.size, RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths), - RCTBorderColorsFromBorderColors(borderMetrics.borderColors), + borderColors, _backgroundColor.CGColor, self.clipsToBounds); + RCTReleaseRCTBorderColors(borderColors); + if (image == nil) { _borderLayer.contents = nil; } else { CGSize imageSize = image.size; UIEdgeInsets imageCapInsets = image.capInsets; - CGRect contentsCenter = - CGRect{CGPoint{imageCapInsets.left / imageSize.width, imageCapInsets.top / imageSize.height}, - CGSize{(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}}; + CGRect contentsCenter = CGRect{ + CGPoint{imageCapInsets.left / imageSize.width, imageCapInsets.top / imageSize.height}, + CGSize{(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}}; _borderLayer.contents = (id)image.CGImage; _borderLayer.contentsScale = image.scale; @@ -549,6 +604,11 @@ - (NSString *)accessibilityValue #pragma mark - Accessibility Events +- (BOOL)shouldGroupAccessibilityChildren +{ + return YES; +} + - (NSArray *)accessibilityCustomActions { auto const &accessibilityActions = _props->accessibilityActions; diff --git a/React/Fabric/Mounting/RCTComponentViewFactory.mm b/React/Fabric/Mounting/RCTComponentViewFactory.mm index 88489f2b3cd900..1c857b440c9d95 100644 --- a/React/Fabric/Mounting/RCTComponentViewFactory.mm +++ b/React/Fabric/Mounting/RCTComponentViewFactory.mm @@ -117,6 +117,7 @@ - (RCTComponentViewClassDescriptor)_componentViewClassDescriptorFromClass:(Class - (void)registerComponentViewClass:(Class)componentViewClass { + RCTAssert(componentViewClass, @"RCTComponentViewFactory: Provided `componentViewClass` is `nil`."); std::unique_lock lock(_mutex); auto componentDescriptorProvider = [componentViewClass componentDescriptorProvider]; diff --git a/React/Fabric/Mounting/RCTComponentViewProtocol.h b/React/Fabric/Mounting/RCTComponentViewProtocol.h index 9c6a862aeaa449..8183e419202a0d 100644 --- a/React/Fabric/Mounting/RCTComponentViewProtocol.h +++ b/React/Fabric/Mounting/RCTComponentViewProtocol.h @@ -111,11 +111,17 @@ typedef NS_OPTIONS(NSInteger, RNComponentViewUpdateMask) { */ - (void)prepareForRecycle; -/** +/* * Read the last props used to update the view. */ - (facebook::react::SharedProps)props; +/* + * This is broken. Do not use. + */ +- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(nullable NSSet *)props; +- (nullable NSSet *)propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.mm b/React/Fabric/Mounting/RCTComponentViewRegistry.mm index ac6d4d7095a380..5deb2375bb9421 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.mm +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.mm @@ -9,6 +9,7 @@ #import #import +#import #import "RCTImageComponentView.h" #import "RCTParagraphComponentView.h" @@ -34,6 +35,10 @@ - (instancetype)init selector:@selector(handleApplicationDidReceiveMemoryWarningNotification) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleApplicationDidEnterBackgroundNotification) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // Calling this a bit later, when the main thread is probably idle while JavaScript thread is busy. @@ -46,6 +51,10 @@ - (instancetype)init - (void)preallocateViewComponents { + if (RCTExperimentGetPreemptiveViewAllocationDisabled()) { + return; + } + // This data is based on empirical evidence which should represent the reality pretty well. // Regular `` has magnitude equals to `1` by definition. std::vector> componentMagnitudes = { @@ -157,4 +166,11 @@ - (void)handleApplicationDidReceiveMemoryWarningNotification _recyclePool.clear(); } +- (void)handleApplicationDidEnterBackgroundNotification +{ + if (RCTExperimentGetReleaseResourcesWhenBackgrounded()) { + _recyclePool.clear(); + } +} + @end diff --git a/React/Fabric/Mounting/RCTMountingManager.h b/React/Fabric/Mounting/RCTMountingManager.h index 0166914bed2949..986d47c040bcfb 100644 --- a/React/Fabric/Mounting/RCTMountingManager.h +++ b/React/Fabric/Mounting/RCTMountingManager.h @@ -38,6 +38,12 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)dispatchCommand:(ReactTag)reactTag commandName:(NSString *)commandName args:(NSArray *)args; +/** + * Dispatch an accessibility event to be performed on the main thread. + * Can be called from any thread. + */ +- (void)sendAccessibilityEvent:(ReactTag)reactTag eventType:(NSString *)eventType; + - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag changedProps:(NSDictionary *)props componentDescriptor:(const facebook::react::ComponentDescriptor &)componentDescriptor; diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index 6a886530487ad0..4edc91d4e6d871 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -11,6 +11,7 @@ #import #import +#import #import #import #import @@ -66,6 +67,8 @@ static void RCTPerformMountInstructions( UIView *newChildComponentView = newChildViewDescriptor.view; + RCTAssert(newChildShadowView.props, @"`newChildShadowView.props` must not be null."); + [newChildComponentView updateProps:newChildShadowView.props oldProps:oldChildShadowView.props]; [newChildComponentView updateEventEmitter:newChildShadowView.eventEmitter]; [newChildComponentView updateState:newChildShadowView.state oldState:oldChildShadowView.state]; @@ -94,6 +97,8 @@ static void RCTPerformMountInstructions( auto mask = RNComponentViewUpdateMask{}; + RCTAssert(newChildShadowView.props, @"`newChildShadowView.props` must not be null."); + if (oldChildShadowView.props != newChildShadowView.props) { [newChildComponentView updateProps:newChildShadowView.props oldProps:oldChildShadowView.props]; mask |= RNComponentViewUpdateMaskProps; @@ -175,6 +180,22 @@ - (void)dispatchCommand:(ReactTag)reactTag commandName:(NSString *)commandName a }); } +- (void)sendAccessibilityEvent:(ReactTag)reactTag eventType:(NSString *)eventType +{ + if (RCTIsMainQueue()) { + // Already on the proper thread, so: + // * No need to do a thread jump; + // * No need to allocate a block. + [self synchronouslyDispatchAccessbilityEventOnUIThread:reactTag eventType:eventType]; + return; + } + + RCTExecuteOnMainQueue(^{ + RCTAssertMainQueue(); + [self synchronouslyDispatchAccessbilityEventOnUIThread:reactTag eventType:eventType]; + }); +} + - (void)initiateTransaction:(MountingCoordinator::Shared const &)mountingCoordinator { SystraceSection s("-[RCTMountingManager initiateTransaction:]"); @@ -222,7 +243,25 @@ - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag UIView *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag]; SharedProps oldProps = [componentView props]; SharedProps newProps = componentDescriptor.cloneProps(oldProps, RawProps(convertIdToFollyDynamic(props))); + + NSSet *propKeys = componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN ?: [NSSet new]; + propKeys = [propKeys setByAddingObjectsFromArray:props.allKeys]; + componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = nil; [componentView updateProps:newProps oldProps:oldProps]; + componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = propKeys; + + const auto &newViewProps = *std::static_pointer_cast(newProps); + + if (props[@"transform"] && + !CATransform3DEqualToTransform( + RCTCATransform3DFromTransformMatrix(newViewProps.transform), componentView.layer.transform)) { + RCTLogWarn(@"transform was not applied during [RCTViewComponentView updateProps:oldProps:]"); + componentView.layer.transform = RCTCATransform3DFromTransformMatrix(newViewProps.transform); + } + if (props[@"opacity"] && componentView.layer.opacity != (float)newViewProps.opacity) { + RCTLogWarn(@"opacity was not applied during [RCTViewComponentView updateProps:oldProps:]"); + componentView.layer.opacity = newViewProps.opacity; + } } - (void)synchronouslyDispatchCommandOnUIThread:(ReactTag)reactTag @@ -234,4 +273,12 @@ - (void)synchronouslyDispatchCommandOnUIThread:(ReactTag)reactTag [componentView handleCommand:commandName args:args]; } +- (void)synchronouslyDispatchAccessbilityEventOnUIThread:(ReactTag)reactTag eventType:(NSString *)eventType +{ + if ([@"focus" isEqualToString:eventType]) { + UIView *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, componentView); + } +} + @end diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h index ab8219555b24bb..3cb45b8f7b7b93 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.h +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.h @@ -39,6 +39,9 @@ NS_ASSUME_NONNULL_BEGIN - (facebook::react::SharedProps)props; +- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(nullable NSSet *)props; +- (nullable NSSet *)propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN; + @end NS_ASSUME_NONNULL_END diff --git a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm index c0de92d8c21df9..c10dfbc8654024 100644 --- a/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm +++ b/React/Fabric/Mounting/UIView+ComponentViewProtocol.mm @@ -132,4 +132,14 @@ - (void)prepareForRecycle return nullptr; } +- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(nullable NSSet *)propKeys +{ + // Default implementation does nothing. +} + +- (nullable NSSet *)propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN +{ + return nil; +} + @end diff --git a/React/Fabric/RCTConversions.h b/React/Fabric/RCTConversions.h index f1dc7ee2910f17..d8169ec2cffc91 100644 --- a/React/Fabric/RCTConversions.h +++ b/React/Fabric/RCTConversions.h @@ -35,20 +35,32 @@ inline std::string RCTStringFromNSString(NSString *string) return std::string{string.UTF8String ?: ""}; } -inline UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor) +inline UIColor *_Nullable RCTUIColorFromSharedColor(facebook::react::SharedColor const &sharedColor) { - return sharedColor ? [UIColor colorWithCGColor:sharedColor.get()] : nil; -} + if (!sharedColor) { + return nil; + } -inline CF_RETURNS_NOT_RETAINED CGColorRef -RCTCGColorRefUnretainedFromSharedColor(const facebook::react::SharedColor &sharedColor) -{ - return sharedColor ? sharedColor.get() : nil; + if (*facebook::react::clearColor() == *sharedColor) { + return [UIColor clearColor]; + } + + if (*facebook::react::blackColor() == *sharedColor) { + return [UIColor blackColor]; + } + + if (*facebook::react::whiteColor() == *sharedColor) { + return [UIColor whiteColor]; + } + + auto components = facebook::react::colorComponentsFromColor(sharedColor); + return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; } -inline CF_RETURNS_RETAINED CGColorRef RCTCGColorRefFromSharedColor(const facebook::react::SharedColor &sharedColor) +inline CF_RETURNS_RETAINED CGColorRef +RCTCreateCGColorRefFromSharedColor(const facebook::react::SharedColor &sharedColor) { - return sharedColor ? CGColorCreateCopy(sharedColor.get()) : nil; + return CGColorRetain(RCTUIColorFromSharedColor(sharedColor).CGColor); } inline CGPoint RCTCGPointFromPoint(const facebook::react::Point &point) @@ -134,22 +146,23 @@ inline UIAccessibilityTraits RCTUIAccessibilityTraitsFromAccessibilityTraits( inline CATransform3D RCTCATransform3DFromTransformMatrix(const facebook::react::Transform &transformMatrix) { - return {(CGFloat)transformMatrix.matrix[0], - (CGFloat)transformMatrix.matrix[1], - (CGFloat)transformMatrix.matrix[2], - (CGFloat)transformMatrix.matrix[3], - (CGFloat)transformMatrix.matrix[4], - (CGFloat)transformMatrix.matrix[5], - (CGFloat)transformMatrix.matrix[6], - (CGFloat)transformMatrix.matrix[7], - (CGFloat)transformMatrix.matrix[8], - (CGFloat)transformMatrix.matrix[9], - (CGFloat)transformMatrix.matrix[10], - (CGFloat)transformMatrix.matrix[11], - (CGFloat)transformMatrix.matrix[12], - (CGFloat)transformMatrix.matrix[13], - (CGFloat)transformMatrix.matrix[14], - (CGFloat)transformMatrix.matrix[15]}; + return { + (CGFloat)transformMatrix.matrix[0], + (CGFloat)transformMatrix.matrix[1], + (CGFloat)transformMatrix.matrix[2], + (CGFloat)transformMatrix.matrix[3], + (CGFloat)transformMatrix.matrix[4], + (CGFloat)transformMatrix.matrix[5], + (CGFloat)transformMatrix.matrix[6], + (CGFloat)transformMatrix.matrix[7], + (CGFloat)transformMatrix.matrix[8], + (CGFloat)transformMatrix.matrix[9], + (CGFloat)transformMatrix.matrix[10], + (CGFloat)transformMatrix.matrix[11], + (CGFloat)transformMatrix.matrix[12], + (CGFloat)transformMatrix.matrix[13], + (CGFloat)transformMatrix.matrix[14], + (CGFloat)transformMatrix.matrix[15]}; } inline facebook::react::Point RCTPointFromCGPoint(const CGPoint &point) diff --git a/React/Fabric/RCTImageResponseDelegate.h b/React/Fabric/RCTImageResponseDelegate.h index eea1fabf953a7d..29f641518043d2 100644 --- a/React/Fabric/RCTImageResponseDelegate.h +++ b/React/Fabric/RCTImageResponseDelegate.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol RCTImageResponseDelegate -- (void)didReceiveImage:(UIImage *)image fromObserver:(void const *)observer; +- (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(void const *)observer; - (void)didReceiveProgress:(float)progress fromObserver:(void const *)observer; - (void)didReceiveFailureFromObserver:(void const *)observer; diff --git a/React/Fabric/RCTImageResponseObserverProxy.mm b/React/Fabric/RCTImageResponseObserverProxy.mm index 4c74e2ea42f2bd..ffb68fbdef7502 100644 --- a/React/Fabric/RCTImageResponseObserverProxy.mm +++ b/React/Fabric/RCTImageResponseObserverProxy.mm @@ -23,10 +23,11 @@ void RCTImageResponseObserverProxy::didReceiveImage(ImageResponse const &imageResponse) const { UIImage *image = (UIImage *)unwrapManagedObject(imageResponse.getImage()); + id metadata = unwrapManagedObject(imageResponse.getMetadata()); id delegate = delegate_; auto this_ = this; RCTExecuteOnMainQueue(^{ - [delegate didReceiveImage:image fromObserver:this_]; + [delegate didReceiveImage:image metadata:metadata fromObserver:this_]; }); } diff --git a/React/Fabric/RCTScheduler.h b/React/Fabric/RCTScheduler.h index 20536137226c74..d68a01e47c0573 100644 --- a/React/Fabric/RCTScheduler.h +++ b/React/Fabric/RCTScheduler.h @@ -31,6 +31,9 @@ NS_ASSUME_NONNULL_BEGIN commandName:(std::string const &)commandName args:(folly::dynamic const)args; +- (void)schedulerDidSendAccessibilityEvent:(facebook::react::ShadowView const &)shadowView + eventType:(std::string const &)eventType; + @end /** diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 31190002461596..bac276ca04020b 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -59,6 +59,12 @@ void schedulerDidClearJSResponder() override // Does nothing for now. } + void schedulerDidSendAccessibilityEvent(const ShadowView &shadowView, std::string const &eventType) override + { + RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_; + [scheduler.delegate schedulerDidSendAccessibilityEvent:shadowView eventType:eventType]; + } + private: void *scheduler_; }; @@ -83,8 +89,8 @@ void onAllAnimationsComplete() override [scheduler onAllAnimationsComplete]; } - void activityDidChange(RunLoopObserver::Delegate const *delegate, RunLoopObserver::Activity activity) const - noexcept override + void activityDidChange(RunLoopObserver::Delegate const *delegate, RunLoopObserver::Activity activity) + const noexcept override { RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_; [scheduler animationTick]; @@ -150,8 +156,10 @@ - (void)startSurfaceWithSurfaceId:(SurfaceId)surfaceId SystraceSection s("-[RCTScheduler startSurfaceWithSurfaceId:...]"); auto props = convertIdToFollyDynamic(initialProps); - _scheduler->startSurface( - surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext, _animationDriver); + _scheduler->startSurface(surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext); + + _scheduler->findMountingCoordinator(surfaceId)->setMountingOverrideDelegate(_animationDriver); + _scheduler->renderTemplateToSurface( surfaceId, props.getDefault("navigationConfig").getDefault("initialUITemplate", "").getString()); } diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 79a12af1be5a1a..191622f72104f4 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -35,10 +35,8 @@ #import #import -#import "MainRunLoopEventBeat.h" #import "PlatformRunLoopObserver.h" #import "RCTConversions.h" -#import "RuntimeEventBeat.h" using namespace facebook::react; @@ -53,11 +51,12 @@ static inline LayoutConstraints RCTGetLayoutConstraintsForSize(CGSize minimumSiz static inline LayoutContext RCTGetLayoutContext(CGPoint viewportOffset) { - return {.pointScaleFactor = RCTScreenScale(), - .swapLeftAndRightInRTL = - [[RCTI18nUtil sharedInstance] isRTL] && [[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL], - .fontSizeMultiplier = RCTFontSizeMultiplier(), - .viewportOffset = RCTPointFromCGPoint(viewportOffset)}; + return { + .pointScaleFactor = RCTScreenScale(), + .swapLeftAndRightInRTL = + [[RCTI18nUtil sharedInstance] isRTL] && [[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL], + .fontSizeMultiplier = RCTFontSizeMultiplier(), + .viewportOffset = RCTPointFromCGPoint(viewportOffset)}; } static dispatch_queue_t RCTGetBackgroundQueue() @@ -322,14 +321,22 @@ - (RCTScheduler *)_createScheduler { auto reactNativeConfig = _contextContainer->at>("ReactNativeConfig"); - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:sync_performance_flag_ios")) { - RCTExperimentSetSyncPerformanceFlag(YES); - } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:scrollview_on_demand_mounting_ios")) { RCTExperimentSetOnDemandViewMounting(YES); } + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:optimized_hit_testing_ios")) { + RCTExperimentSetOptimizedHitTesting(YES); + } + + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:preemptive_view_allocation_disabled_ios")) { + RCTExperimentSetPreemptiveViewAllocationDisabled(YES); + } + + if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:release_resources_when_backgrounded_ios")) { + RCTExperimentSetReleaseResourcesWhenBackgrounded(YES); + } + auto componentRegistryFactory = [factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)]( EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) { @@ -352,27 +359,17 @@ - (RCTScheduler *)_createScheduler toolbox.backgroundExecutor = RCTGetBackgroundExecutor(); } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_run_loop_based_event_beat_ios")) { - toolbox.synchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { - auto runLoopObserver = - std::make_unique(RunLoopObserver::Activity::BeforeWaiting, ownerBox->owner); - return std::make_unique(std::move(runLoopObserver), runtimeExecutor); - }; - - toolbox.asynchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { - auto runLoopObserver = - std::make_unique(RunLoopObserver::Activity::BeforeWaiting, ownerBox->owner); - return std::make_unique(std::move(runLoopObserver), runtimeExecutor); - }; - } else { - toolbox.synchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { - return std::make_unique(ownerBox, runtimeExecutor); - }; - - toolbox.asynchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { - return std::make_unique(ownerBox, runtimeExecutor); - }; - } + toolbox.synchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { + auto runLoopObserver = + std::make_unique(RunLoopObserver::Activity::BeforeWaiting, ownerBox->owner); + return std::make_unique(std::move(runLoopObserver), runtimeExecutor); + }; + + toolbox.asynchronousEventBeatFactory = [runtimeExecutor](EventBeat::SharedOwnerBox const &ownerBox) { + auto runLoopObserver = + std::make_unique(RunLoopObserver::Activity::BeforeWaiting, ownerBox->owner); + return std::make_unique(std::move(runLoopObserver), runtimeExecutor); + }; RCTScheduler *scheduler = [[RCTScheduler alloc] initWithToolbox:toolbox]; scheduler.delegate = self; @@ -473,6 +470,15 @@ - (void)schedulerDidDispatchCommand:(ShadowView const &)shadowView [self->_mountingManager dispatchCommand:tag commandName:commandStr args:argsArray]; } +- (void)schedulerDidSendAccessibilityEvent:(const facebook::react::ShadowView &)shadowView + eventType:(const std::string &)eventType +{ + ReactTag tag = shadowView.tag; + NSString *eventTypeStr = [[NSString alloc] initWithUTF8String:eventType.c_str()]; + + [self->_mountingManager sendAccessibilityEvent:tag eventType:eventTypeStr]; +} + - (void)addObserver:(id)observer { std::unique_lock lock(_observerListMutex); diff --git a/React/Fabric/RCTSurfaceTouchHandler.h b/React/Fabric/RCTSurfaceTouchHandler.h index 1c642be78f5b7f..b20e195322ab94 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.h +++ b/React/Fabric/RCTSurfaceTouchHandler.h @@ -11,6 +11,10 @@ NS_ASSUME_NONNULL_BEGIN @interface RCTSurfaceTouchHandler : UIGestureRecognizer +/* + * Attaches (and detaches) a view to the touch handler. + * The receiver does not retain the provided view. + */ - (void)attachToView:(UIView *)view; - (void)detachFromView:(UIView *)view; diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index c3edd4eed628d1..eb5d126eda3370 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -96,24 +96,27 @@ static void UpdateActiveTouchWithUITouch( activeTouch.touch.timestamp = uiTouch.timestamp; if (RCTForceTouchAvailable()) { - activeTouch.touch.force = uiTouch.force / uiTouch.maximumPossibleForce; + activeTouch.touch.force = RCTZeroIfNaN(uiTouch.force / uiTouch.maximumPossibleForce); } } static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponentView, CGPoint rootViewOriginOffset) { - UIView *componentView = uiTouch.view; - ActiveTouch activeTouch = {}; - if ([componentView respondsToSelector:@selector(touchEventEmitterAtPoint:)]) { - activeTouch.eventEmitter = [(id)componentView - touchEventEmitterAtPoint:[uiTouch locationInView:componentView]]; - activeTouch.touch.target = (Tag)componentView.tag; + // Find closest Fabric-managed touchable view + UIView *componentView = uiTouch.view; + while (componentView) { + if ([componentView respondsToSelector:@selector(touchEventEmitterAtPoint:)]) { + activeTouch.eventEmitter = [(id)componentView + touchEventEmitterAtPoint:[uiTouch locationInView:componentView]]; + activeTouch.touch.target = (Tag)componentView.tag; + activeTouch.componentView = componentView; + break; + } + componentView = componentView.superview; } - activeTouch.componentView = componentView; - UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView, rootViewOriginOffset); return activeTouch; } @@ -159,7 +162,10 @@ @implementation RCTSurfaceTouchHandler { std::unordered_map<__unsafe_unretained UITouch *, ActiveTouch, PointerHasher<__unsafe_unretained UITouch *>> _activeTouches; - UIView *_rootComponentView; + /* + * We hold the view weakly to prevent a retain cycle. + */ + __weak UIView *_rootComponentView; IdentifierPool<11> _identifierPool; } @@ -404,4 +410,22 @@ - (BOOL)gestureRecognizer:(__unused UIGestureRecognizer *)gestureRecognizer return [self canBePreventedByGestureRecognizer:otherGestureRecognizer]; } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer + shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + BOOL canBePrevented = [self canBePreventedByGestureRecognizer:otherGestureRecognizer]; + if (canBePrevented) { + [self _cancelTouches]; + } + return NO; +} + +#pragma mark - + +- (void)_cancelTouches +{ + [self setEnabled:NO]; + [self setEnabled:YES]; +} + @end diff --git a/React/Fabric/Surface/RCTFabricSurface.h b/React/Fabric/Surface/RCTFabricSurface.h index d4dd93c91197a5..1c3e4af43f71dd 100644 --- a/React/Fabric/Surface/RCTFabricSurface.h +++ b/React/Fabric/Surface/RCTFabricSurface.h @@ -70,6 +70,13 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)start; - (BOOL)stop; +/** + * EXPERIMENTAL + * Reset's the Surface to it's initial stage. + * It uses the passed in surface presenter, and whatever else was passed in init. + */ +- (void)resetWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter; + #pragma mark - Layout: Setting the size constrains /** diff --git a/React/Fabric/Surface/RCTFabricSurface.mm b/React/Fabric/Surface/RCTFabricSurface.mm index f8ea1c39faeea4..993985c4846392 100644 --- a/React/Fabric/Surface/RCTFabricSurface.mm +++ b/React/Fabric/Surface/RCTFabricSurface.mm @@ -24,7 +24,7 @@ @implementation RCTFabricSurface { // Immutable - RCTSurfacePresenter *_surfacePresenter; + __weak RCTSurfacePresenter *_surfacePresenter; NSString *_moduleName; // Protected by the `_mutex` @@ -58,14 +58,19 @@ - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter _maximumSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); - _touchHandler = [RCTSurfaceTouchHandler new]; - _stage = RCTSurfaceStageSurfaceDidInitialize; } return self; } +- (void)resetWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter +{ + _surfacePresenter = surfacePresenter; + _stage = RCTSurfaceStageSurfaceDidInitialize; + _view = nil; +} + - (BOOL)start { if (![self _setStage:RCTSurfaceStageStarted]) { @@ -106,6 +111,7 @@ - (RCTSurfaceView *)view if (!_view) { _view = [[RCTSurfaceView alloc] initWithSurface:(RCTSurface *)self]; + _touchHandler = [RCTSurfaceTouchHandler new]; [_touchHandler attachToView:_view]; } diff --git a/React/Fabric/Utils/MainRunLoopEventBeat.h b/React/Fabric/Utils/MainRunLoopEventBeat.h deleted file mode 100644 index b0b7751f06ce7c..00000000000000 --- a/React/Fabric/Utils/MainRunLoopEventBeat.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -/* - * Event beat associated with main run loop cycle. - * The callback is always called on the main thread. - */ -class MainRunLoopEventBeat final : public EventBeat { - public: - MainRunLoopEventBeat( - EventBeat::SharedOwnerBox const &ownerBox, - RuntimeExecutor runtimeExecutor); - ~MainRunLoopEventBeat(); - - void induce() const override; - - private: - void lockExecutorAndBeat() const; - - const RuntimeExecutor runtimeExecutor_; - CFRunLoopObserverRef mainRunLoopObserver_; -}; - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Utils/MainRunLoopEventBeat.mm b/React/Fabric/Utils/MainRunLoopEventBeat.mm deleted file mode 100644 index 563cebde21d38b..00000000000000 --- a/React/Fabric/Utils/MainRunLoopEventBeat.mm +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "MainRunLoopEventBeat.h" - -#import -#import - -namespace facebook { -namespace react { - -MainRunLoopEventBeat::MainRunLoopEventBeat(EventBeat::SharedOwnerBox const &ownerBox, RuntimeExecutor runtimeExecutor) - : EventBeat(ownerBox), runtimeExecutor_(std::move(runtimeExecutor)) -{ - mainRunLoopObserver_ = CFRunLoopObserverCreateWithHandler( - NULL /* allocator */, - kCFRunLoopBeforeWaiting /* activities */, - true /* repeats */, - 0 /* order */, - ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { - if (!this->isRequested_) { - return; - } - - this->lockExecutorAndBeat(); - }); - - assert(mainRunLoopObserver_); - - CFRunLoopAddObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); -} - -MainRunLoopEventBeat::~MainRunLoopEventBeat() -{ - CFRunLoopRemoveObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); - CFRelease(mainRunLoopObserver_); -} - -void MainRunLoopEventBeat::induce() const -{ - if (!this->isRequested_) { - return; - } - - RCTExecuteOnMainQueue(^{ - this->lockExecutorAndBeat(); - }); -} - -void MainRunLoopEventBeat::lockExecutorAndBeat() const -{ - auto owner = ownerBox_->owner.lock(); - if (!owner) { - return; - } - - executeSynchronouslyOnSameThread_CAN_DEADLOCK(runtimeExecutor_, [this](jsi::Runtime &runtime) { beat(runtime); }); -} - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Utils/RuntimeEventBeat.h b/React/Fabric/Utils/RuntimeEventBeat.h deleted file mode 100644 index 8bfdd0cdf9c472..00000000000000 --- a/React/Fabric/Utils/RuntimeEventBeat.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -/* - * Event beat associated with JavaScript runtime. - * The beat is called on `RuntimeExecutor`'s thread induced by the main thread - * event loop. - */ -class RuntimeEventBeat : public EventBeat { - public: - RuntimeEventBeat( - EventBeat::SharedOwnerBox const &ownerBox, - RuntimeExecutor runtimeExecutor); - ~RuntimeEventBeat(); - - void induce() const override; - - private: - const RuntimeExecutor runtimeExecutor_; - CFRunLoopObserverRef mainRunLoopObserver_; - mutable std::atomic isBusy_{false}; -}; - -} // namespace react -} // namespace facebook diff --git a/React/Fabric/Utils/RuntimeEventBeat.mm b/React/Fabric/Utils/RuntimeEventBeat.mm deleted file mode 100644 index 0cd3a3c5bb71a2..00000000000000 --- a/React/Fabric/Utils/RuntimeEventBeat.mm +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "RuntimeEventBeat.h" - -namespace facebook { -namespace react { - -RuntimeEventBeat::RuntimeEventBeat(EventBeat::SharedOwnerBox const &ownerBox, RuntimeExecutor runtimeExecutor) - : EventBeat(ownerBox), runtimeExecutor_(std::move(runtimeExecutor)) -{ - mainRunLoopObserver_ = CFRunLoopObserverCreateWithHandler( - NULL /* allocator */, - kCFRunLoopBeforeWaiting /* activities */, - true /* repeats */, - 0 /* order */, - ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { - // Note: We only `induce` beat here; actual beat will be performed on - // a different thread. - this->induce(); - }); - - assert(mainRunLoopObserver_); - - CFRunLoopAddObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); -} - -RuntimeEventBeat::~RuntimeEventBeat() -{ - CFRunLoopRemoveObserver(CFRunLoopGetMain(), mainRunLoopObserver_, kCFRunLoopCommonModes); - CFRelease(mainRunLoopObserver_); -} - -void RuntimeEventBeat::induce() const -{ - if (!isRequested_ || isBusy_) { - return; - } - - isBusy_ = true; - runtimeExecutor_([this, ownerBox = ownerBox_](jsi::Runtime &runtime) mutable { - auto owner = ownerBox->owner.lock(); - if (!owner) { - return; - } - - this->beat(runtime); - isBusy_ = false; - }); -} - -} // namespace react -} // namespace facebook diff --git a/React/Modules/RCTEventEmitter.h b/React/Modules/RCTEventEmitter.h index 700368c599d016..ea7b69c3d8804e 100644 --- a/React/Modules/RCTEventEmitter.h +++ b/React/Modules/RCTEventEmitter.h @@ -12,9 +12,13 @@ * RCTEventEmitter is an abstract base class to be used for modules that emit * events to be observed by JS. */ -@interface RCTEventEmitter : NSObject +@interface RCTEventEmitter : NSObject @property (nonatomic, weak) RCTBridge *bridge; +@property (nonatomic, weak) RCTModuleRegistry *moduleRegistry; +@property (nonatomic, weak) RCTViewRegistry *viewRegistry_DEPRECATED; + +- (instancetype)initWithDisabledObservation; /** * Override this method to return an array of supported event names. Attempting @@ -37,6 +41,8 @@ - (void)startObserving; - (void)stopObserving; +- (void)invalidate NS_REQUIRES_SUPER; + - (void)addListener:(NSString *)eventName; - (void)removeListeners:(double)count; diff --git a/React/Modules/RCTEventEmitter.m b/React/Modules/RCTEventEmitter.m index 7717ddbdcac451..c3cc596e13ca18 100644 --- a/React/Modules/RCTEventEmitter.m +++ b/React/Modules/RCTEventEmitter.m @@ -12,6 +12,7 @@ @implementation RCTEventEmitter { NSInteger _listenerCount; + BOOL _observationDisabled; } @synthesize invokeJS = _invokeJS; @@ -32,6 +33,13 @@ + (void)initialize } } +- (instancetype)initWithDisabledObservation +{ + self = [super init]; + _observationDisabled = YES; + return self; +} + - (NSArray *)supportedEvents { return nil; @@ -56,12 +64,15 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]); } - if (_listenerCount > 0 && _bridge) { + + BOOL shouldEmitEvent = (_observationDisabled || _listenerCount > 0); + + if (shouldEmitEvent && _bridge) { [_bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:body ? @[ eventName, body ] : @[ eventName ] completion:NULL]; - } else if (_listenerCount > 0 && _invokeJS) { + } else if (shouldEmitEvent && _invokeJS) { _invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ eventName, body ] : @[ eventName ]); } else { RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName); @@ -78,8 +89,12 @@ - (void)stopObserving // Does nothing } -- (void)dealloc +- (void)invalidate { + if (_observationDisabled) { + return; + } + if (_listenerCount > 0) { [self stopObserving]; } @@ -87,6 +102,10 @@ - (void)dealloc RCT_EXPORT_METHOD(addListener : (NSString *)eventName) { + if (_observationDisabled) { + return; + } + if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) { RCTLogError( @"`%@` is not a supported event type for %@. Supported events are: `%@`", @@ -102,6 +121,10 @@ - (void)dealloc RCT_EXPORT_METHOD(removeListeners : (double)count) { + if (_observationDisabled) { + return; + } + int currentCount = (int)count; if (RCT_DEBUG && currentCount > _listenerCount) { RCTLogError(@"Attempted to remove more %@ listeners than added", [self class]); diff --git a/React/Modules/RCTLayoutAnimation.m b/React/Modules/RCTLayoutAnimation.m index 7ad88992d9ec87..7b702c18d80dcb 100644 --- a/React/Modules/RCTLayoutAnimation.m +++ b/React/Modules/RCTLayoutAnimation.m @@ -39,7 +39,6 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim // `UIKeyboardWillChangeFrameNotification`s. + (void)initializeStatics { -#if !TARGET_OS_TV static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [[NSNotificationCenter defaultCenter] addObserver:self @@ -47,15 +46,12 @@ + (void)initializeStatics name:UIKeyboardWillChangeFrameNotification object:nil]; }); -#endif } + (void)keyboardWillChangeFrame:(NSNotification *)notification { -#if !TARGET_OS_TV NSDictionary *userInfo = notification.userInfo; _currentKeyboardAnimationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; -#endif } - (instancetype)initWithDuration:(NSTimeInterval)duration diff --git a/React/Modules/RCTRedBoxExtraDataViewController.m b/React/Modules/RCTRedBoxExtraDataViewController.m index 240aa5e9b033ad..9b006ec68c1ef3 100644 --- a/React/Modules/RCTRedBoxExtraDataViewController.m +++ b/React/Modules/RCTRedBoxExtraDataViewController.m @@ -33,10 +33,8 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStr self.keyLabel.textColor = [UIColor whiteColor]; self.keyLabel.numberOfLines = 0; -#if !TARGET_OS_TV self.keyLabel.lineBreakMode = NSLineBreakByWordWrapping; self.keyLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:12.0f]; -#endif self.valueLabel = [UILabel new]; [self.contentView addSubview:self.valueLabel]; @@ -48,10 +46,8 @@ - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStr self.valueLabel.textColor = [UIColor whiteColor]; self.valueLabel.numberOfLines = 0; -#if !TARGET_OS_TV self.valueLabel.lineBreakMode = NSLineBreakByWordWrapping; self.valueLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:12.0f]; -#endif } return self; } @@ -82,9 +78,7 @@ - (instancetype)init _tableView.dataSource = self; _tableView.backgroundColor = [UIColor clearColor]; _tableView.estimatedRowHeight = 200; -#if !TARGET_OS_TV _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; -#endif _tableView.rowHeight = UITableViewAutomaticDimension; _tableView.allowsSelection = NO; diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 2079bbb7f6c215..47399cc6916a88 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -17,7 +17,7 @@ #import "RCTComponentData.h" #import "RCTConvert.h" #import "RCTDefines.h" -#import "RCTEventDispatcher.h" +#import "RCTEventDispatcherProtocol.h" #import "RCTLayoutAnimation.h" #import "RCTLayoutAnimationGroup.h" #import "RCTLog.h" @@ -81,6 +81,7 @@ @implementation RCTUIManager { } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -179,12 +180,10 @@ - (void)setBridge:(RCTBridge *)bridge object:[self->_bridge moduleForName:@"AccessibilityManager" lazilyLoadIfNecessary:YES]]; }); -#if !TARGET_OS_TV [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(namedOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil]; -#endif [RCTLayoutAnimation initializeStatics]; } @@ -198,7 +197,8 @@ - (void)didReceiveNewContentSizeMultiplier id multiplier = [[self->_bridge moduleForName:@"AccessibilityManager" lazilyLoadIfNecessary:YES] valueForKey:@"multiplier"]; if (multiplier) { - [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateContentSizeMultiplier" body:multiplier]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"didUpdateContentSizeMultiplier" + body:multiplier]; } #pragma clang diagnostic pop @@ -210,7 +210,6 @@ - (void)didReceiveNewContentSizeMultiplier }); } -#if !TARGET_OS_TV // Names and coordinate system from html5 spec: // https://developer.mozilla.org/en-US/docs/Web/API/Screen.orientation // https://developer.mozilla.org/en-US/docs/Web/API/Screen.lockOrientation @@ -259,10 +258,10 @@ - (void)namedOrientationDidChange #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendDeviceEventWithName:@"namedOrientationDidChange" body:orientationEvent]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"namedOrientationDidChange" + body:orientationEvent]; #pragma clang diagnostic pop } -#endif - (dispatch_queue_t)methodQueue { @@ -556,11 +555,12 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView * for (RCTShadowView *shadowView in affectedShadowViews) { reactTags[index] = shadowView.reactTag; RCTLayoutMetrics layoutMetrics = shadowView.layoutMetrics; - frameDataArray[index++] = (RCTFrameData){layoutMetrics.frame, - layoutMetrics.layoutDirection, - shadowView.isNewView, - shadowView.superview.isNewView, - layoutMetrics.displayType}; + frameDataArray[index++] = (RCTFrameData){ + layoutMetrics.frame, + layoutMetrics.layoutDirection, + shadowView.isNewView, + shadowView.superview.isNewView, + layoutMetrics.displayType}; } } diff --git a/React/Profiler/RCTProfile.m b/React/Profiler/RCTProfile.m index 149451ad6bfeee..d57c098e098925 100644 --- a/React/Profiler/RCTProfile.m +++ b/React/Profiler/RCTProfile.m @@ -393,7 +393,6 @@ + (void)toggle:(UIButton *)target RCTProfileEnd(RCTProfilingBridge(), ^(NSString *result) { NSString *outFile = [NSTemporaryDirectory() stringByAppendingString:@"tmp_trace.json"]; [result writeToFile:outFile atomically:YES encoding:NSUTF8StringEncoding error:nil]; -#if !TARGET_OS_TV UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[ [NSURL fileURLWithPath:outFile] ] applicationActivities:nil]; @@ -410,7 +409,6 @@ + (void)toggle:(UIButton *)target animated:YES completion:nil]; }); -#endif }); } else { RCTProfileInit(RCTProfilingBridge()); @@ -471,14 +469,15 @@ void RCTProfileInit(RCTBridge *bridge) NSArray *orderedThreads = @[ @"JS async", @"RCTPerformanceLogger", @"com.facebook.react.JavaScript", @(RCTUIManagerQueueName), @"main" ]; [orderedThreads enumerateObjectsUsingBlock:^(NSString *thread, NSUInteger idx, __unused BOOL *stop) { - RCTProfileAddEvent(kProfileTraceEvents, - @"ph" - : @"M", // metadata event - @"name" - : @"thread_sort_index", @"tid" - : thread, @"args" - : - @{@"sort_index" : @(-1000 + (NSInteger)idx)}); + RCTProfileAddEvent( + kProfileTraceEvents, + @"ph" + : @"M", // metadata event + @"name" + : @"thread_sort_index", @"tid" + : thread, @"args" + : + @{@"sort_index" : @(-1000 + (NSInteger)idx)}); }]; }); @@ -747,7 +746,6 @@ void RCTProfileSendResult(RCTBridge *bridge, NSString *route, NSData *data) NSString *message = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; if (message.length) { -#if !TARGET_OS_TV dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Profile" @@ -758,7 +756,6 @@ void RCTProfileSendResult(RCTBridge *bridge, NSString *route, NSData *data) handler:nil]]; [RCTPresentedViewController() presentViewController:alertController animated:YES completion:nil]; }); -#endif } } }]; diff --git a/React/React-RCTFabric.podspec b/React/React-RCTFabric.podspec index 34d1096c413d9e..833d67cd364e56 100644 --- a/React/React-RCTFabric.podspec +++ b/React/React-RCTFabric.podspec @@ -28,10 +28,9 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.source = source - s.source_files = "Fabric/**/*.{c,h,m,mm,S,cpp}", - "Tests/**/*.{mm}" + s.source_files = "Fabric/**/*.{c,h,m,mm,S,cpp}" s.exclude_files = "**/tests/*", "**/android/*", s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags @@ -45,5 +44,10 @@ Pod::Spec.new do |s| s.dependency "React-Core", version s.dependency "React-Fabric", version s.dependency "React-RCTImage", version - s.dependency "Folly/Fabric", folly_version + s.dependency "RCT-Folly/Fabric", folly_version + + s.test_spec 'Tests' do |test_spec| + test_spec.source_files = "Tests/**/*.{mm}" + test_spec.framework = "XCTest" + end end diff --git a/React/Tests/Mounting/RCTComponentViewRegistryTests.mm b/React/Tests/Mounting/RCTComponentViewRegistryTests.mm new file mode 100644 index 00000000000000..b76038969b2995 --- /dev/null +++ b/React/Tests/Mounting/RCTComponentViewRegistryTests.mm @@ -0,0 +1,86 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +@interface RCTComponentViewRegistryTests : XCTestCase +@end + +using namespace facebook::react; + +@implementation RCTComponentViewRegistryTests { + RCTComponentViewRegistry *_componentViewRegistry; +} + +- (void)setUp +{ + [super setUp]; + _componentViewRegistry = [RCTComponentViewRegistry new]; +} + +- (void)testComponentViewDescriptorWithTag +{ + XCTAssertThrows( + ^{ + Tag nonExistingTag = 12; + [self->_componentViewRegistry componentViewDescriptorWithTag:nonExistingTag]; + }(), + @"Should throw: `Attempt to query unregistered component`"); + + Tag existingTag = 2; + auto newViewDescriptor = [_componentViewRegistry + dequeueComponentViewWithComponentHandle:[RCTViewComponentView componentDescriptorProvider].handle + tag:existingTag]; + + XCTAssertNoThrow(^{ + auto componentDescriptor = [self->_componentViewRegistry componentViewDescriptorWithTag:existingTag]; + XCTAssertEqual(newViewDescriptor, componentDescriptor); + }()); +} + +- (void)testFindComponentViewWithTag +{ + Tag nonExistingTag = 12; + XCTAssertNil([_componentViewRegistry findComponentViewWithTag:nonExistingTag]); + + Tag existingTag = 2; + auto newViewDescriptor = [_componentViewRegistry + dequeueComponentViewWithComponentHandle:[RCTViewComponentView componentDescriptorProvider].handle + tag:existingTag]; + + XCTAssertEqual(newViewDescriptor.view, [_componentViewRegistry findComponentViewWithTag:existingTag]); +} + +- (void)testDequeueAndEnqueue +{ + Tag existingTag = 2; + auto newViewDescriptor = [_componentViewRegistry + dequeueComponentViewWithComponentHandle:[RCTViewComponentView componentDescriptorProvider].handle + tag:existingTag]; + + XCTAssertThrows( + ^{ + [self->_componentViewRegistry + dequeueComponentViewWithComponentHandle:[RCTViewComponentView componentDescriptorProvider].handle + tag:existingTag]; + }(), + @"Should throw: `Attempt to dequeue already registered component`"); + + XCTAssertThrows( + ^{ + Tag nonExistingTag = 12; + [self->_componentViewRegistry + enqueueComponentViewWithComponentHandle:[RCTViewComponentView componentDescriptorProvider].handle + tag:nonExistingTag + componentViewDescriptor:newViewDescriptor]; + }(), + @"Should throw: `Attempt to enqueue unregistered component`"); +} + +@end diff --git a/React/Tests/Text/RCTParagraphComponentViewTests.mm b/React/Tests/Text/RCTParagraphComponentViewTests.mm index 02aa19fa47e84f..4bc04029269f14 100644 --- a/React/Tests/Text/RCTParagraphComponentViewTests.mm +++ b/React/Tests/Text/RCTParagraphComponentViewTests.mm @@ -9,24 +9,24 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import @interface RCTParagraphComponentAccessibilityProviderTests : XCTestCase @@ -130,6 +130,7 @@ - (void)setUp .props([] { auto sharedProps = std::make_shared(); auto &props = *sharedProps; + props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; @@ -209,6 +210,7 @@ - (void)setUp .props([] { auto sharedProps = std::make_shared(); auto &props = *sharedProps; + props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; @@ -252,6 +254,7 @@ - (void)setUp .props([] { auto sharedProps = std::make_shared(); auto &props = *sharedProps; + props.accessible = true; auto &yogaStyle = props.yogaStyle; yogaStyle.positionType() = YGPositionTypeAbsolute; yogaStyle.position()[YGEdgeLeft] = YGValue{0, YGUnitPoint}; @@ -320,14 +323,17 @@ - (void)testAttributedString { ParagraphShadowNode::ConcreteState::Shared _stateA = stateWithShadowNode(ParagrahShadowNodeA_); RCTParagraphComponentView *paragraphComponentViewA = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentViewA updateProps:ParagrahShadowNodeA_->getProps() oldProps:nullptr]; [paragraphComponentViewA updateState:_stateA oldState:nil]; ParagraphShadowNode::ConcreteState::Shared _stateB = stateWithShadowNode(ParagrahShadowNodeB_); RCTParagraphComponentView *paragraphComponentViewB = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentViewB updateProps:ParagrahShadowNodeB_->getProps() oldProps:nullptr]; [paragraphComponentViewB updateState:_stateB oldState:nil]; ParagraphShadowNode::ConcreteState::Shared _stateC = stateWithShadowNode(ParagrahShadowNodeC_); RCTParagraphComponentView *paragraphComponentViewC = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentViewC updateProps:ParagrahShadowNodeC_->getProps() oldProps:nullptr]; [paragraphComponentViewC updateState:_stateC oldState:nil]; // Check the correctness of attributedString @@ -353,6 +359,7 @@ - (void)testAccessibilityMultipleLinks // initialize the paragraphComponentView to get the accessibilityElements ParagraphShadowNode::ConcreteState::Shared _state = stateWithShadowNode(ParagrahShadowNodeA_); RCTParagraphComponentView *paragraphComponentView = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentView updateProps:ParagrahShadowNodeA_->getProps() oldProps:nullptr]; [paragraphComponentView updateState:_state oldState:nil]; NSArray *elements = [paragraphComponentView accessibilityElements]; @@ -373,6 +380,7 @@ - (void)testAccessibilityLinkWrappingMultipleLines { ParagraphShadowNode::ConcreteState::Shared _state = stateWithShadowNode(ParagrahShadowNodeB_); RCTParagraphComponentView *paragraphComponentView = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentView updateProps:ParagrahShadowNodeB_->getProps() oldProps:nullptr]; [paragraphComponentView updateState:_state oldState:nil]; NSArray *elements = [paragraphComponentView accessibilityElements]; @@ -386,6 +394,7 @@ - (void)testAccessibilityTruncatedText { ParagraphShadowNode::ConcreteState::Shared _state = stateWithShadowNode(ParagrahShadowNodeC_); RCTParagraphComponentView *paragraphComponentView = [[RCTParagraphComponentView alloc] init]; + [paragraphComponentView updateProps:ParagrahShadowNodeC_->getProps() oldProps:nullptr]; [paragraphComponentView updateState:_state oldState:nil]; NSArray *elements = [paragraphComponentView accessibilityElements]; diff --git a/React/UIUtils/RCTUIUtils.m b/React/UIUtils/RCTUIUtils.m index 2d3243c57832f1..ba9443e298a033 100644 --- a/React/UIUtils/RCTUIUtils.m +++ b/React/UIUtils/RCTUIUtils.m @@ -16,7 +16,8 @@ RCTDimensions RCTGetDimensions(CGFloat fontScale) UIView *mainWindow; mainWindow = RCTKeyWindow(); - CGSize windowSize = mainWindow.bounds.size; + // We fallback to screen size if a key window is not found. + CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize; RCTDimensions result; typeof(result.screen) dimsScreen = { diff --git a/React/Views/RCTBorderDrawing.m b/React/Views/RCTBorderDrawing.m index 8d84b86c6da3b9..afc99f41a472b4 100644 --- a/React/Views/RCTBorderDrawing.m +++ b/React/Views/RCTBorderDrawing.m @@ -33,22 +33,23 @@ BOOL RCTBorderColorsAreEqual(RCTBorderColors borderColors) RCTCornerInsets RCTGetCornerInsets(RCTCornerRadii cornerRadii, UIEdgeInsets edgeInsets) { - return (RCTCornerInsets){{ - MAX(0, cornerRadii.topLeft - edgeInsets.left), - MAX(0, cornerRadii.topLeft - edgeInsets.top), - }, - { - MAX(0, cornerRadii.topRight - edgeInsets.right), - MAX(0, cornerRadii.topRight - edgeInsets.top), - }, - { - MAX(0, cornerRadii.bottomLeft - edgeInsets.left), - MAX(0, cornerRadii.bottomLeft - edgeInsets.bottom), - }, - { - MAX(0, cornerRadii.bottomRight - edgeInsets.right), - MAX(0, cornerRadii.bottomRight - edgeInsets.bottom), - }}; + return (RCTCornerInsets){ + { + MAX(0, cornerRadii.topLeft - edgeInsets.left), + MAX(0, cornerRadii.topLeft - edgeInsets.top), + }, + { + MAX(0, cornerRadii.topRight - edgeInsets.right), + MAX(0, cornerRadii.topRight - edgeInsets.top), + }, + { + MAX(0, cornerRadii.bottomLeft - edgeInsets.left), + MAX(0, cornerRadii.bottomLeft - edgeInsets.bottom), + }, + { + MAX(0, cornerRadii.bottomRight - edgeInsets.right), + MAX(0, cornerRadii.bottomRight - edgeInsets.bottom), + }}; } static UIEdgeInsets RCTRoundInsetsToPixel(UIEdgeInsets edgeInsets) @@ -206,11 +207,11 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn (borderInsets.top + cornerInsets.topRight.height + borderInsets.bottom + cornerInsets.bottomLeft.height <= viewSize.height); - UIEdgeInsets edgeInsets = - (UIEdgeInsets){borderInsets.top + MAX(cornerInsets.topLeft.height, cornerInsets.topRight.height), - borderInsets.left + MAX(cornerInsets.topLeft.width, cornerInsets.bottomLeft.width), - borderInsets.bottom + MAX(cornerInsets.bottomLeft.height, cornerInsets.bottomRight.height), - borderInsets.right + MAX(cornerInsets.bottomRight.width, cornerInsets.topRight.width)}; + UIEdgeInsets edgeInsets = (UIEdgeInsets){ + borderInsets.top + MAX(cornerInsets.topLeft.height, cornerInsets.topRight.height), + borderInsets.left + MAX(cornerInsets.topLeft.width, cornerInsets.bottomLeft.width), + borderInsets.bottom + MAX(cornerInsets.bottomLeft.height, cornerInsets.bottomRight.height), + borderInsets.right + MAX(cornerInsets.bottomRight.width, cornerInsets.topRight.width)}; if (hasCornerRadii) { // Asymmetrical edgeInsets cause strange artifacting on iOS 10 and earlier. @@ -271,8 +272,9 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn if (cornerInsets.bottomLeft.width > 0 && cornerInsets.bottomLeft.height > 0) { CGPoint points[2]; RCTEllipseGetIntersectionsWithLine( - (CGRect){{bottomLeft.x, bottomLeft.y - 2 * cornerInsets.bottomLeft.height}, - {2 * cornerInsets.bottomLeft.width, 2 * cornerInsets.bottomLeft.height}}, + (CGRect){ + {bottomLeft.x, bottomLeft.y - 2 * cornerInsets.bottomLeft.height}, + {2 * cornerInsets.bottomLeft.width, 2 * cornerInsets.bottomLeft.height}}, (CGPoint){0, size.height}, bottomLeft, points); @@ -285,8 +287,9 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn if (cornerInsets.topRight.width > 0 && cornerInsets.topRight.height > 0) { CGPoint points[2]; RCTEllipseGetIntersectionsWithLine( - (CGRect){{topRight.x - 2 * cornerInsets.topRight.width, topRight.y}, - {2 * cornerInsets.topRight.width, 2 * cornerInsets.topRight.height}}, + (CGRect){ + {topRight.x - 2 * cornerInsets.topRight.width, topRight.y}, + {2 * cornerInsets.topRight.width, 2 * cornerInsets.topRight.height}}, (CGPoint){size.width, 0}, topRight, points); diff --git a/React/Views/RCTComponentData.m b/React/Views/RCTComponentData.m index c8c893863e2b32..5a8600cf5b55ab 100644 --- a/React/Views/RCTComponentData.m +++ b/React/Views/RCTComponentData.m @@ -70,9 +70,7 @@ - (UIView *)createViewWithTag:(nullable NSNumber *)tag rootTag:(nullable NSNumbe UIView *view = [self.manager view]; view.reactTag = tag; view.rootTag = rootTag; -#if !TARGET_OS_TV view.multipleTouchEnabled = YES; -#endif view.userInteractionEnabled = YES; // required for touch handling view.layer.allowsGroupOpacity = YES; // required for touch handling return view; diff --git a/React/Views/RCTConvert+CoreLocation.m b/React/Views/RCTConvert+CoreLocation.m index 95ec773d32fb99..0fd6bb13a13868 100644 --- a/React/Views/RCTConvert+CoreLocation.m +++ b/React/Views/RCTConvert+CoreLocation.m @@ -15,8 +15,8 @@ @implementation RCTConvert (CoreLocation) + (CLLocationCoordinate2D)CLLocationCoordinate2D:(id)json { json = [self NSDictionary:json]; - return (CLLocationCoordinate2D){[self CLLocationDegrees:json[@"latitude"]], - [self CLLocationDegrees:json[@"longitude"]]}; + return (CLLocationCoordinate2D){ + [self CLLocationDegrees:json[@"latitude"]], [self CLLocationDegrees:json[@"longitude"]]}; } @end diff --git a/React/Views/RCTDatePicker.m b/React/Views/RCTDatePicker.m index 1a921c556a0918..064191b3e8aa1c 100644 --- a/React/Views/RCTDatePicker.m +++ b/React/Views/RCTDatePicker.m @@ -7,9 +7,20 @@ #import "RCTDatePicker.h" +#import +#import + #import "RCTUtils.h" #import "UIView+React.h" +#ifndef __IPHONE_14_0 +#define __IPHONE_14_0 140000 +#endif // __IPHONE_14_0 + +#ifndef RCT_IOS_14_0_SDK_OR_LATER +#define RCT_IOS_14_0_SDK_OR_LATER (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0) +#endif // RCT_IOS_14_0_SDK_OR_LATER + @interface RCTDatePicker () @property (nonatomic, copy) RCTBubblingEventBlock onChange; @@ -24,6 +35,12 @@ - (instancetype)initWithFrame:(CGRect)frame if ((self = [super initWithFrame:frame])) { [self addTarget:self action:@selector(didChange) forControlEvents:UIControlEventValueChanged]; _reactMinuteInterval = 1; + +#if RCT_IOS_14_0_SDK_OR_LATER + if (@available(iOS 14, *)) { + self.preferredDatePickerStyle = UIDatePickerStyleWheels; + } +#endif // RCT_IOS_14_0_SDK_OR_LATER } return self; } diff --git a/React/Views/RCTDatePickerManager.m b/React/Views/RCTDatePickerManager.m index 198a4ef77ef772..38f662463f6b3a 100644 --- a/React/Views/RCTDatePickerManager.m +++ b/React/Views/RCTDatePickerManager.m @@ -10,7 +10,6 @@ #import #import "RCTBridge.h" #import "RCTDatePicker.h" -#import "RCTEventDispatcher.h" #import "UIView+React.h" @implementation RCTConvert (UIDatePicker) diff --git a/React/Views/RCTLayout.m b/React/Views/RCTLayout.m index 0ca11c7b8ea55d..b6e66d409623de 100644 --- a/React/Views/RCTLayout.m +++ b/React/Views/RCTLayout.m @@ -14,27 +14,31 @@ RCTLayoutMetrics RCTLayoutMetricsFromYogaNode(YGNodeRef yogaNode) { RCTLayoutMetrics layoutMetrics; - CGRect frame = (CGRect){(CGPoint){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetLeft(yogaNode)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetTop(yogaNode))}, - (CGSize){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(yogaNode)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(yogaNode))}}; - - UIEdgeInsets padding = - (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))}; - - UIEdgeInsets borderWidth = - (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))}; - - UIEdgeInsets compoundInsets = (UIEdgeInsets){borderWidth.top + padding.top, - borderWidth.left + padding.left, - borderWidth.bottom + padding.bottom, - borderWidth.right + padding.right}; + CGRect frame = (CGRect){ + (CGPoint){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetLeft(yogaNode)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetTop(yogaNode))}, + (CGSize){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetWidth(yogaNode)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetHeight(yogaNode))}}; + + UIEdgeInsets padding = (UIEdgeInsets){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))}; + + UIEdgeInsets borderWidth = (UIEdgeInsets){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))}; + + UIEdgeInsets compoundInsets = (UIEdgeInsets){ + borderWidth.top + padding.top, + borderWidth.left + padding.left, + borderWidth.bottom + padding.bottom, + borderWidth.right + padding.right}; CGRect bounds = (CGRect){CGPointZero, frame.size}; CGRect contentFrame = UIEdgeInsetsInsetRect(bounds, compoundInsets); diff --git a/React/Views/RCTModalHostView.h b/React/Views/RCTModalHostView.h index 4e61886dba54ef..c54c1c69c94413 100644 --- a/React/Views/RCTModalHostView.h +++ b/React/Views/RCTModalHostView.h @@ -13,7 +13,6 @@ @class RCTBridge; @class RCTModalHostViewController; -@class RCTTVRemoteHandler; @protocol RCTModalHostViewInteractor; @@ -32,11 +31,6 @@ @property (nonatomic, copy) NSArray *supportedOrientations; @property (nonatomic, copy) RCTDirectEventBlock onOrientationChange; -#if TARGET_OS_TV -@property (nonatomic, copy) RCTDirectEventBlock onRequestClose; -@property (nonatomic, strong) RCTTVRemoteHandler *tvRemoteHandler; -#endif - - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; @end diff --git a/React/Views/RCTModalHostView.m b/React/Views/RCTModalHostView.m index 6a153301038853..0cfa69a99aab6f 100644 --- a/React/Views/RCTModalHostView.m +++ b/React/Views/RCTModalHostView.m @@ -16,9 +16,6 @@ #import "RCTUIManager.h" #import "RCTUtils.h" #import "UIView+React.h" -#if TARGET_OS_TV -#import "RCTTVRemoteHandler.h" -#endif @implementation RCTModalHostView { __weak RCTBridge *_bridge; @@ -26,11 +23,7 @@ @implementation RCTModalHostView { RCTModalHostViewController *_modalViewController; RCTTouchHandler *_touchHandler; UIView *_reactSubview; -#if TARGET_OS_TV - UITapGestureRecognizer *_menuButtonGestureRecognizer; -#else UIInterfaceOrientation _lastKnownOrientation; -#endif } RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame) @@ -45,12 +38,6 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; _modalViewController.view = containerView; _touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge]; -#if TARGET_OS_TV - _menuButtonGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(menuButtonPressed:)]; - _menuButtonGestureRecognizer.allowedPressTypes = @[ @(UIPressTypeMenu) ]; - self.tvRemoteHandler = [RCTTVRemoteHandler new]; -#endif _isPresented = NO; __weak typeof(self) weakSelf = self; @@ -62,27 +49,6 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge return self; } -#if TARGET_OS_TV -- (void)menuButtonPressed:(__unused UIGestureRecognizer *)gestureRecognizer -{ - if (_onRequestClose) { - _onRequestClose(nil); - } -} - -- (void)setOnRequestClose:(RCTDirectEventBlock)onRequestClose -{ - _onRequestClose = onRequestClose; - if (_reactSubview) { - if (_onRequestClose && _menuButtonGestureRecognizer) { - [_reactSubview addGestureRecognizer:_menuButtonGestureRecognizer]; - } else { - [_reactSubview removeGestureRecognizer:_menuButtonGestureRecognizer]; - } - } -} -#endif - - (void)notifyForBoundsChange:(CGRect)newBounds { if (_reactSubview && _isPresented) { @@ -93,7 +59,6 @@ - (void)notifyForBoundsChange:(CGRect)newBounds - (void)notifyForOrientationChange { -#if !TARGET_OS_TV if (!_onOrientationChange) { return; } @@ -110,7 +75,6 @@ - (void)notifyForOrientationChange @"orientation" : isPortrait ? @"portrait" : @"landscape", }; _onOrientationChange(eventPayload); -#endif } - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex @@ -118,16 +82,6 @@ - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex RCTAssert(_reactSubview == nil, @"Modal view can only have one subview"); [super insertReactSubview:subview atIndex:atIndex]; [_touchHandler attachToView:subview]; -#if TARGET_OS_TV - for (NSString *key in [self.tvRemoteHandler.tvRemoteGestureRecognizers allKeys]) { - if (![key isEqualToString:RCTTVRemoteEventMenu]) { - [subview addGestureRecognizer:self.tvRemoteHandler.tvRemoteGestureRecognizers[key]]; - } - } - if (_onRequestClose) { - [subview addGestureRecognizer:_menuButtonGestureRecognizer]; - } -#endif [_modalViewController.view insertSubview:subview atIndex:0]; _reactSubview = subview; @@ -139,14 +93,6 @@ - (void)removeReactSubview:(UIView *)subview // Superclass (category) removes the `subview` from actual `superview`. [super removeReactSubview:subview]; [_touchHandler detachFromView:subview]; -#if TARGET_OS_TV - if (_menuButtonGestureRecognizer) { - [subview removeGestureRecognizer:_menuButtonGestureRecognizer]; - } - for (UIGestureRecognizer *gr in self.tvRemoteHandler.tvRemoteGestureRecognizers) { - [subview removeGestureRecognizer:gr]; - } -#endif _reactSubview = nil; } @@ -176,9 +122,8 @@ - (void)didMoveToWindow if (!_isPresented && self.window) { RCTAssert(self.reactViewController, @"Can't present modal view controller without a presenting view controller"); -#if !TARGET_OS_TV _modalViewController.supportedInterfaceOrientations = [self supportedOrientationsMask]; -#endif + if ([self.animationType isEqualToString:@"fade"]) { _modalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; } else if ([self.animationType isEqualToString:@"slide"]) { @@ -228,7 +173,6 @@ - (void)setTransparent:(BOOL)transparent transparent ? UIModalPresentationOverFullScreen : UIModalPresentationFullScreen; } -#if !TARGET_OS_TV - (UIInterfaceOrientationMask)supportedOrientationsMask { if (_supportedOrientations.count == 0) { @@ -255,6 +199,5 @@ - (UIInterfaceOrientationMask)supportedOrientationsMask } return supportedOrientations; } -#endif @end diff --git a/React/Views/RCTModalHostViewController.h b/React/Views/RCTModalHostViewController.h index 0a4a82968075c5..a3f66b6b068336 100644 --- a/React/Views/RCTModalHostViewController.h +++ b/React/Views/RCTModalHostViewController.h @@ -11,8 +11,6 @@ @property (nonatomic, copy) void (^boundsDidChangeBlock)(CGRect newBounds); -#if !TARGET_OS_TV @property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations; -#endif @end diff --git a/React/Views/RCTModalHostViewController.m b/React/Views/RCTModalHostViewController.m index 112bc17c4d85bf..00c149d3db8474 100644 --- a/React/Views/RCTModalHostViewController.m +++ b/React/Views/RCTModalHostViewController.m @@ -12,10 +12,8 @@ @implementation RCTModalHostViewController { CGRect _lastViewFrame; -#if !TARGET_OS_TV UIStatusBarStyle _preferredStatusBarStyle; BOOL _preferredStatusBarHidden; -#endif } - (instancetype)init @@ -31,10 +29,8 @@ - (instancetype)init } #endif -#if !TARGET_OS_TV _preferredStatusBarStyle = [RCTSharedApplication() statusBarStyle]; _preferredStatusBarHidden = [RCTSharedApplication() isStatusBarHidden]; -#endif return self; } @@ -49,7 +45,6 @@ - (void)viewDidLayoutSubviews } } -#if !TARGET_OS_TV - (UIStatusBarStyle)preferredStatusBarStyle { return _preferredStatusBarStyle; @@ -78,6 +73,5 @@ - (UIInterfaceOrientationMask)supportedInterfaceOrientations return _supportedInterfaceOrientations; } #endif // RCT_DEV -#endif // !TARGET_OS_TV @end diff --git a/React/Views/RCTModalHostViewManager.m b/React/Views/RCTModalHostViewManager.m index 4698139f90102b..91d83aabbdc604 100644 --- a/React/Views/RCTModalHostViewManager.m +++ b/React/Views/RCTModalHostViewManager.m @@ -10,6 +10,7 @@ #import "RCTBridge.h" #import "RCTModalHostView.h" #import "RCTModalHostViewController.h" +#import "RCTModalManager.h" #import "RCTShadowView.h" #import "RCTUtils.h" @@ -19,10 +20,8 @@ @implementation RCTConvert (RCTModalHostView) UIModalPresentationStyle, (@{ @"fullScreen" : @(UIModalPresentationFullScreen), -#if !TARGET_OS_TV @"pageSheet" : @(UIModalPresentationPageSheet), @"formSheet" : @(UIModalPresentationFormSheet), -#endif @"overFullScreen" : @(UIModalPresentationOverFullScreen), }), UIModalPresentationFullScreen, @@ -48,8 +47,6 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex @interface RCTModalHostViewManager () -@property (nonatomic, copy) dispatch_block_t dismissWaitingBlock; - @end @implementation RCTModalHostViewManager { @@ -81,16 +78,9 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView if (_presentationBlock) { _presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock); } else { - __weak typeof(self) weakself = self; [[modalHostView reactViewController] presentViewController:viewController animated:animated - completion:^{ - !completionBlock ?: completionBlock(); - __strong typeof(weakself) strongself = weakself; - !strongself.dismissWaitingBlock - ?: strongself.dismissWaitingBlock(); - strongself.dismissWaitingBlock = nil; - }]; + completion:completionBlock]; } } @@ -98,16 +88,15 @@ - (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated { + dispatch_block_t completionBlock = ^{ + if (modalHostView.identifier) { + [[self.bridge moduleForClass:[RCTModalManager class]] modalDismissed:modalHostView.identifier]; + } + }; if (_dismissalBlock) { - _dismissalBlock([modalHostView reactViewController], viewController, animated, nil); + _dismissalBlock([modalHostView reactViewController], viewController, animated, completionBlock); } else { - self.dismissWaitingBlock = ^{ - [viewController.presentingViewController dismissViewControllerAnimated:animated completion:nil]; - }; - if (viewController.presentingViewController) { - self.dismissWaitingBlock(); - self.dismissWaitingBlock = nil; - } + [viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock]; } } @@ -132,8 +121,4 @@ - (void)invalidate RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray) RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock) -#if TARGET_OS_TV -RCT_EXPORT_VIEW_PROPERTY(onRequestClose, RCTDirectEventBlock) -#endif - @end diff --git a/React/CoreModules/RCTTVNavigationEventEmitter.h b/React/Views/RCTModalManager.h similarity index 58% rename from React/CoreModules/RCTTVNavigationEventEmitter.h rename to React/Views/RCTModalManager.h index b3bf1d43bd07a3..4fbe6dfbd01e25 100644 --- a/React/CoreModules/RCTTVNavigationEventEmitter.h +++ b/React/Views/RCTModalManager.h @@ -5,10 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +#import + +#import #import -RCT_EXTERN NSString *const RCTTVNavigationEventNotification; +@interface RCTModalManager : RCTEventEmitter -@interface RCTTVNavigationEventEmitter : RCTEventEmitter +- (void)modalDismissed:(NSNumber *)modalID; @end diff --git a/React/Views/RCTModalManager.m b/React/Views/RCTModalManager.m new file mode 100644 index 00000000000000..992b73c62db660 --- /dev/null +++ b/React/Views/RCTModalManager.m @@ -0,0 +1,42 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTModalManager.h" + +@interface RCTModalManager () + +@property BOOL shouldEmit; + +@end + +@implementation RCTModalManager + +RCT_EXPORT_MODULE(); + +- (NSArray *)supportedEvents +{ + return @[ @"modalDismissed" ]; +} + +- (void)startObserving +{ + _shouldEmit = YES; +} + +- (void)stopObserving +{ + _shouldEmit = NO; +} + +- (void)modalDismissed:(NSNumber *)modalID +{ + if (_shouldEmit) { + [self sendEventWithName:@"modalDismissed" body:@{@"modalID" : modalID}]; + } +} + +@end diff --git a/React/Views/RCTPicker.m b/React/Views/RCTPicker.m index 774264f55f929e..dfcdbb24d05eea 100644 --- a/React/Views/RCTPicker.m +++ b/React/Views/RCTPicker.m @@ -82,11 +82,12 @@ - (UIView *)pickerView:(UIPickerView *)pickerView reusingView:(UILabel *)label { if (!label) { - label = [[UILabel alloc] initWithFrame:(CGRect){CGPointZero, - { - [pickerView rowSizeForComponent:component].width, - [pickerView rowSizeForComponent:component].height, - }}]; + label = [[UILabel alloc] initWithFrame:(CGRect){ + CGPointZero, + { + [pickerView rowSizeForComponent:component].width, + [pickerView rowSizeForComponent:component].height, + }}]; } label.font = _font; diff --git a/React/Views/RCTProgressViewManager.m b/React/Views/RCTProgressViewManager.m index 887473cb1aa73b..ed434250101f58 100644 --- a/React/Views/RCTProgressViewManager.m +++ b/React/Views/RCTProgressViewManager.m @@ -15,9 +15,7 @@ @implementation RCTConvert (RCTProgressViewManager) UIProgressViewStyle, (@{ @"default" : @(UIProgressViewStyleDefault), -#if !TARGET_OS_TV @"bar" : @(UIProgressViewStyleBar), -#endif }), UIProgressViewStyleDefault, integerValue) diff --git a/React/Views/RCTSegmentedControl.m b/React/Views/RCTSegmentedControl.m index 10c1c745a59964..1ffdb59921a383 100644 --- a/React/Views/RCTSegmentedControl.m +++ b/React/Views/RCTSegmentedControl.m @@ -8,7 +8,6 @@ #import "RCTSegmentedControl.h" #import "RCTConvert.h" -#import "RCTEventDispatcher.h" #import "UIView+React.h" @implementation RCTSegmentedControl diff --git a/React/Views/RCTShadowView+Layout.m b/React/Views/RCTShadowView+Layout.m index 734f053fc56894..91662c0b64683f 100644 --- a/React/Views/RCTShadowView+Layout.m +++ b/React/Views/RCTShadowView+Layout.m @@ -18,19 +18,21 @@ @implementation RCTShadowView (Layout) - (UIEdgeInsets)paddingAsInsets { YGNodeRef yogaNode = self.yogaNode; - return (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))}; + return (UIEdgeInsets){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetPadding(yogaNode, YGEdgeRight))}; } - (UIEdgeInsets)borderAsInsets { YGNodeRef yogaNode = self.yogaNode; - return (UIEdgeInsets){RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)), - RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))}; + return (UIEdgeInsets){ + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeTop)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeLeft)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeBottom)), + RCTCoreGraphicsFloatFromYogaFloat(YGNodeLayoutGetBorder(yogaNode, YGEdgeRight))}; } - (UIEdgeInsets)compoundInsets @@ -38,10 +40,11 @@ - (UIEdgeInsets)compoundInsets UIEdgeInsets borderAsInsets = self.borderAsInsets; UIEdgeInsets paddingAsInsets = self.paddingAsInsets; - return (UIEdgeInsets){borderAsInsets.top + paddingAsInsets.top, - borderAsInsets.left + paddingAsInsets.left, - borderAsInsets.bottom + paddingAsInsets.bottom, - borderAsInsets.right + paddingAsInsets.right}; + return (UIEdgeInsets){ + borderAsInsets.top + paddingAsInsets.top, + borderAsInsets.left + paddingAsInsets.left, + borderAsInsets.bottom + paddingAsInsets.bottom, + borderAsInsets.right + paddingAsInsets.right}; } - (CGSize)availableSize diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index 61894cdd7b8415..af103bb1f0d0bc 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -267,8 +267,9 @@ - (void)layoutWithMinimumSize:(CGSize)minimumSize { YGNodeRef yogaNode = _yogaNode; - CGSize oldMinimumSize = (CGSize){RCTCoreGraphicsFloatFromYogaValue(YGNodeStyleGetMinWidth(yogaNode), 0.0), - RCTCoreGraphicsFloatFromYogaValue(YGNodeStyleGetMinHeight(yogaNode), 0.0)}; + CGSize oldMinimumSize = (CGSize){ + RCTCoreGraphicsFloatFromYogaValue(YGNodeStyleGetMinWidth(yogaNode), 0.0), + RCTCoreGraphicsFloatFromYogaValue(YGNodeStyleGetMinHeight(yogaNode), 0.0)}; if (!CGSizeEqualToSize(oldMinimumSize, minimumSize)) { YGNodeStyleSetMinWidth(yogaNode, RCTYogaFloatFromCoreGraphicsFloat(minimumSize.width)); diff --git a/React/Views/RCTSliderManager.m b/React/Views/RCTSliderManager.m index a3a6795957505a..e2c2810110214b 100644 --- a/React/Views/RCTSliderManager.m +++ b/React/Views/RCTSliderManager.m @@ -8,7 +8,6 @@ #import "RCTSliderManager.h" #import "RCTBridge.h" -#import "RCTEventDispatcher.h" #import "RCTSlider.h" #import "UIView+React.h" diff --git a/React/Views/RCTSwitch.m b/React/Views/RCTSwitch.m index 80475480d13801..8abd4d5afba92b 100644 --- a/React/Views/RCTSwitch.m +++ b/React/Views/RCTSwitch.m @@ -7,7 +7,6 @@ #import "RCTSwitch.h" -#import "RCTEventDispatcher.h" #import "UIView+React.h" @implementation RCTSwitch diff --git a/React/Views/RCTSwitchManager.m b/React/Views/RCTSwitchManager.m index 04f7006c74f646..f37df49c4dfadc 100644 --- a/React/Views/RCTSwitchManager.m +++ b/React/Views/RCTSwitchManager.m @@ -9,7 +9,6 @@ #import #import "RCTBridge.h" -#import "RCTEventDispatcher.h" #import "RCTSwitch.h" #import "UIView+React.h" @@ -42,12 +41,7 @@ - (void)onChange:(RCTSwitch *)sender if ([view isKindOfClass:[UISwitch class]]) { [(UISwitch *)view setOn:value animated:NO]; } else { - UIView *subview = view.subviews.firstObject; - if ([subview isKindOfClass:[UISwitch class]]) { - [(UISwitch *)subview setOn:value animated:NO]; - } else { - RCTLogError(@"view type must be UISwitch"); - } + RCTLogError(@"view type must be UISwitch"); } }]; } diff --git a/React/Views/RCTTVView.h b/React/Views/RCTTVView.h deleted file mode 100644 index a421e6fc61f173..00000000000000 --- a/React/Views/RCTTVView.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import -#import - -#import - -// A RCTView with additional properties and methods for user interaction using the Apple TV focus engine. -@interface RCTTVView : RCTView - -/** - * TV event handlers - */ -@property (nonatomic, assign) BOOL isTVSelectable; // True if this view is TV-focusable - -/** - * Properties for Apple TV focus parallax effects - */ -@property (nonatomic, copy) NSDictionary *tvParallaxProperties; - -/** - * TV preferred focus - */ -@property (nonatomic, assign) BOOL hasTVPreferredFocus; - -@end diff --git a/React/Views/RCTTVView.m b/React/Views/RCTTVView.m deleted file mode 100644 index 6f06b9a1f411d2..00000000000000 --- a/React/Views/RCTTVView.m +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTTVView.h" - -#import "RCTAutoInsetsProtocol.h" -#import "RCTBorderDrawing.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTRootViewInternal.h" -#import "RCTTVNavigationEventEmitter.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "UIView+React.h" - -@implementation RCTTVView { - UITapGestureRecognizer *_selectRecognizer; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - if (self = [super initWithFrame:frame]) { - dispatch_once(&onceToken, ^{ - defaultTVParallaxProperties = @{ - @"enabled" : @YES, - @"shiftDistanceX" : @2.0f, - @"shiftDistanceY" : @2.0f, - @"tiltAngle" : @0.05f, - @"magnification" : @1.0f, - @"pressMagnification" : @1.0f, - @"pressDuration" : @0.3f, - @"pressDelay" : @0.0f - }; - }); - self.tvParallaxProperties = defaultTVParallaxProperties; - } - - return self; -} - -static NSDictionary *defaultTVParallaxProperties = nil; -static dispatch_once_t onceToken; - -- (void)setTvParallaxProperties:(NSDictionary *)tvParallaxProperties -{ - if (_tvParallaxProperties == nil) { - _tvParallaxProperties = [defaultTVParallaxProperties copy]; - return; - } - - NSMutableDictionary *newParallaxProperties = [NSMutableDictionary dictionaryWithDictionary:_tvParallaxProperties]; - for (NSString *k in [defaultTVParallaxProperties allKeys]) { - if (tvParallaxProperties[k]) { - newParallaxProperties[k] = tvParallaxProperties[k]; - } - } - _tvParallaxProperties = [newParallaxProperties copy]; -} - -RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused) - -- (void)setIsTVSelectable:(BOOL)isTVSelectable -{ - self->_isTVSelectable = isTVSelectable; - if (isTVSelectable) { - UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(handleSelect:)]; - recognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ]; - _selectRecognizer = recognizer; - [self addGestureRecognizer:_selectRecognizer]; - } else { - if (_selectRecognizer) { - [self removeGestureRecognizer:_selectRecognizer]; - } - } -} - -- (void)handleSelect:(__unused UIGestureRecognizer *)r -{ - if ([self.tvParallaxProperties[@"enabled"] boolValue] == YES) { - float magnification = [self.tvParallaxProperties[@"magnification"] floatValue]; - float pressMagnification = [self.tvParallaxProperties[@"pressMagnification"] floatValue]; - - // Duration of press animation - float pressDuration = [self.tvParallaxProperties[@"pressDuration"] floatValue]; - - // Delay of press animation - float pressDelay = [self.tvParallaxProperties[@"pressDelay"] floatValue]; - - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:pressDelay]]; - - [UIView animateWithDuration:(pressDuration / 2) - animations:^{ - self.transform = CGAffineTransformMakeScale(pressMagnification, pressMagnification); - } - completion:^(__unused BOOL finished1) { - [UIView animateWithDuration:(pressDuration / 2) - animations:^{ - self.transform = CGAffineTransformMakeScale(magnification, magnification); - } - completion:^(__unused BOOL finished2) { - [[NSNotificationCenter defaultCenter] - postNotificationName:RCTTVNavigationEventNotification - object:@{@"eventType" : @"select", @"tag" : self.reactTag}]; - }]; - }]; - - } else { - [[NSNotificationCenter defaultCenter] postNotificationName:RCTTVNavigationEventNotification - object:@{@"eventType" : @"select", @"tag" : self.reactTag}]; - } -} - -- (BOOL)isUserInteractionEnabled -{ - return YES; -} - -- (BOOL)canBecomeFocused -{ - return (self.isTVSelectable); -} - -- (void)addParallaxMotionEffects -{ - // Size of shift movements - CGFloat const shiftDistanceX = [self.tvParallaxProperties[@"shiftDistanceX"] floatValue]; - CGFloat const shiftDistanceY = [self.tvParallaxProperties[@"shiftDistanceY"] floatValue]; - - // Make horizontal movements shift the centre left and right - UIInterpolatingMotionEffect *xShift = - [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" - type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - xShift.minimumRelativeValue = @(shiftDistanceX * -1.0f); - xShift.maximumRelativeValue = @(shiftDistanceX); - - // Make vertical movements shift the centre up and down - UIInterpolatingMotionEffect *yShift = - [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" - type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - yShift.minimumRelativeValue = @(shiftDistanceY * -1.0f); - yShift.maximumRelativeValue = @(shiftDistanceY); - - // Size of tilt movements - CGFloat const tiltAngle = [self.tvParallaxProperties[@"tiltAngle"] floatValue]; - - // Now make horizontal movements effect a rotation about the Y axis for side-to-side rotation. - UIInterpolatingMotionEffect *xTilt = - [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform" - type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - - // CATransform3D value for minimumRelativeValue - CATransform3D transMinimumTiltAboutY = CATransform3DIdentity; - transMinimumTiltAboutY.m34 = 1.0 / 500; - transMinimumTiltAboutY = CATransform3DRotate(transMinimumTiltAboutY, tiltAngle * -1.0, 0, 1, 0); - - // CATransform3D value for minimumRelativeValue - CATransform3D transMaximumTiltAboutY = CATransform3DIdentity; - transMaximumTiltAboutY.m34 = 1.0 / 500; - transMaximumTiltAboutY = CATransform3DRotate(transMaximumTiltAboutY, tiltAngle, 0, 1, 0); - - // Set the transform property boundaries for the interpolation - xTilt.minimumRelativeValue = [NSValue valueWithCATransform3D:transMinimumTiltAboutY]; - xTilt.maximumRelativeValue = [NSValue valueWithCATransform3D:transMaximumTiltAboutY]; - - // Now make vertical movements effect a rotation about the X axis for up and down rotation. - UIInterpolatingMotionEffect *yTilt = - [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform" - type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - - // CATransform3D value for minimumRelativeValue - CATransform3D transMinimumTiltAboutX = CATransform3DIdentity; - transMinimumTiltAboutX.m34 = 1.0 / 500; - transMinimumTiltAboutX = CATransform3DRotate(transMinimumTiltAboutX, tiltAngle * -1.0, 1, 0, 0); - - // CATransform3D value for minimumRelativeValue - CATransform3D transMaximumTiltAboutX = CATransform3DIdentity; - transMaximumTiltAboutX.m34 = 1.0 / 500; - transMaximumTiltAboutX = CATransform3DRotate(transMaximumTiltAboutX, tiltAngle, 1, 0, 0); - - // Set the transform property boundaries for the interpolation - yTilt.minimumRelativeValue = [NSValue valueWithCATransform3D:transMinimumTiltAboutX]; - yTilt.maximumRelativeValue = [NSValue valueWithCATransform3D:transMaximumTiltAboutX]; - - // Add all of the motion effects to this group - self.motionEffects = @[ xShift, yShift, xTilt, yTilt ]; - - float magnification = [self.tvParallaxProperties[@"magnification"] floatValue]; - - [UIView animateWithDuration:0.2 - animations:^{ - self.transform = CGAffineTransformMakeScale(magnification, magnification); - }]; -} - -- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context - withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator -{ - if (context.nextFocusedView == self && self.isTVSelectable) { - [self becomeFirstResponder]; - [coordinator - addCoordinatedAnimations:^(void) { - if ([self.tvParallaxProperties[@"enabled"] boolValue]) { - [self addParallaxMotionEffects]; - } - [[NSNotificationCenter defaultCenter] - postNotificationName:RCTTVNavigationEventNotification - object:@{@"eventType" : @"focus", @"tag" : self.reactTag}]; - } - completion:^(void){ - }]; - } else { - [coordinator - addCoordinatedAnimations:^(void) { - [[NSNotificationCenter defaultCenter] postNotificationName:RCTTVNavigationEventNotification - object:@{@"eventType" : @"blur", @"tag" : self.reactTag}]; - [UIView animateWithDuration:0.2 - animations:^{ - self.transform = CGAffineTransformMakeScale(1, 1); - }]; - - for (UIMotionEffect *effect in [self.motionEffects copy]) { - [self removeMotionEffect:effect]; - } - } - completion:^(void){ - }]; - [self resignFirstResponder]; - } -} - -- (void)setHasTVPreferredFocus:(BOOL)hasTVPreferredFocus -{ - _hasTVPreferredFocus = hasTVPreferredFocus; - if (hasTVPreferredFocus) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - UIView *rootview = self; - while (![rootview isReactRootView] && rootview != nil) { - rootview = [rootview superview]; - } - if (rootview == nil) - return; - - rootview = [rootview superview]; - - [rootview setNeedsFocusUpdate]; - [rootview updateFocusIfNeeded]; - }); - } -} - -@end diff --git a/React/Views/RCTViewManager.h b/React/Views/RCTViewManager.h index b35ceb23f73239..5c1eba4d80a935 100644 --- a/React/Views/RCTViewManager.h +++ b/React/Views/RCTViewManager.h @@ -10,7 +10,7 @@ #import #import #import -#import +#import #import #import diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index 8b948eb5eb9ab8..48dcd0a06ce4a3 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -11,7 +11,6 @@ #import "RCTBridge.h" #import "RCTConvert+Transform.h" #import "RCTConvert.h" -#import "RCTEventDispatcher.h" #import "RCTLog.h" #import "RCTShadowView.h" #import "RCTUIManager.h" @@ -20,10 +19,6 @@ #import "RCTView.h" #import "UIView+React.h" -#if TARGET_OS_TV -#import "RCTTVView.h" -#endif - @implementation RCTConvert (UIAccessibilityTraits) RCT_MULTI_ENUM_CONVERTER( @@ -83,11 +78,7 @@ - (dispatch_queue_t)methodQueue - (UIView *)view { -#if TARGET_OS_TV - return [RCTTVView new]; -#else return [RCTView new]; -#endif } - (RCTShadowView *)shadowView @@ -118,13 +109,6 @@ - (RCTShadowView *)shadowView #pragma mark - View properties -#if TARGET_OS_TV -// TODO: Delete props for Apple TV. -RCT_EXPORT_VIEW_PROPERTY(isTVSelectable, BOOL) -RCT_EXPORT_VIEW_PROPERTY(hasTVPreferredFocus, BOOL) -RCT_EXPORT_VIEW_PROPERTY(tvParallaxProperties, NSDictionary) -#endif - // Accessibility related properties RCT_REMAP_VIEW_PROPERTY(accessible, reactAccessibilityElement.isAccessibilityElement, BOOL) RCT_REMAP_VIEW_PROPERTY(accessibilityActions, reactAccessibilityElement.accessibilityActions, NSDictionaryArray) diff --git a/React/Views/RCTWrapperViewController.m b/React/Views/RCTWrapperViewController.m index fc9eaa6c507275..20dd2101e9180a 100644 --- a/React/Views/RCTWrapperViewController.m +++ b/React/Views/RCTWrapperViewController.m @@ -10,14 +10,12 @@ #import #import "RCTAutoInsetsProtocol.h" -#import "RCTEventDispatcher.h" #import "RCTUtils.h" #import "UIView+React.h" @implementation RCTWrapperViewController { UIView *_wrapperView; UIView *_contentView; - RCTEventDispatcher *_eventDispatcher; CGFloat _previousTopLayoutLength; CGFloat _previousBottomLayoutLength; diff --git a/React/Views/ScrollView/RCTScrollContentView.m b/React/Views/ScrollView/RCTScrollContentView.m index cf6a0b1f17953d..8006540a70f136 100644 --- a/React/Views/ScrollView/RCTScrollContentView.m +++ b/React/Views/ScrollView/RCTScrollContentView.m @@ -26,7 +26,7 @@ - (void)reactSetFrame:(CGRect)frame RCTAssert([scrollView isKindOfClass:[RCTScrollView class]], @"Unexpected view hierarchy of RCTScrollView component."); - [scrollView updateContentOffsetIfNeeded]; + [scrollView updateContentSizeIfNeeded]; } @end diff --git a/React/Views/ScrollView/RCTScrollEvent.h b/React/Views/ScrollView/RCTScrollEvent.h index 8494f0e6e8035e..29a645d30c697e 100644 --- a/React/Views/ScrollView/RCTScrollEvent.h +++ b/React/Views/ScrollView/RCTScrollEvent.h @@ -6,7 +6,7 @@ */ #import -#import +#import @interface RCTScrollEvent : NSObject diff --git a/React/Views/ScrollView/RCTScrollView.h b/React/Views/ScrollView/RCTScrollView.h index d5ac000284e4fa..765d3b3378a5a6 100644 --- a/React/Views/ScrollView/RCTScrollView.h +++ b/React/Views/ScrollView/RCTScrollView.h @@ -8,7 +8,8 @@ #import #import -#import +#import +#import #import #import @@ -16,7 +17,7 @@ @interface RCTScrollView : RCTView -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithEventDispatcher:(id)eventDispatcher NS_DESIGNATED_INITIALIZER; /** * The `RCTScrollView` may have at most one single subview. This will ensure @@ -27,12 +28,6 @@ */ @property (nonatomic, readonly) UIView *contentView; -/** - * If the `contentSize` is not specified (or is specified as {0, 0}, then the - * `contentSize` will automatically be determined by the size of the subview. - */ -@property (nonatomic, assign) CGSize contentSize; - /** * The underlying scrollView (TODO: can we remove this?) */ @@ -67,15 +62,8 @@ @interface RCTScrollView (Internal) -- (void)updateContentOffsetIfNeeded; +- (void)updateContentSizeIfNeeded; @end -@interface RCTEventDispatcher (RCTScrollView) - -/** - * Send a fake scroll event. - */ -- (void)sendFakeScrollEvent:(NSNumber *)reactTag; - -@end +RCT_EXTERN void RCTSendFakeScrollEvent(id eventDispatcher, NSNumber *reactTag); diff --git a/React/Views/ScrollView/RCTScrollView.m b/React/Views/ScrollView/RCTScrollView.m index 7e341219a63984..77f1c62b5a1b66 100644 --- a/React/Views/ScrollView/RCTScrollView.m +++ b/React/Views/ScrollView/RCTScrollView.m @@ -11,6 +11,7 @@ #import "RCTConvert.h" #import "RCTLog.h" +#import "RCTRefreshControl.h" #import "RCTScrollEvent.h" #import "RCTUIManager.h" #import "RCTUIManagerObserverCoordinator.h" @@ -19,10 +20,6 @@ #import "UIView+Private.h" #import "UIView+React.h" -#if !TARGET_OS_TV -#import "RCTRefreshControl.h" -#endif - /** * Include a custom scroll view subclass because we want to limit certain * default UIKit behaviors such as textFields automatically scrolling @@ -31,10 +28,8 @@ @interface RCTCustomScrollView : UIScrollView @property (nonatomic, assign) BOOL centerContent; -#if !TARGET_OS_TV @property (nonatomic, strong) UIView *customRefreshControl; @property (nonatomic, assign) BOOL pinchGestureEnabled; -#endif @end @@ -52,9 +47,7 @@ - (instancetype)initWithFrame:(CGRect)frame self.semanticContentAttribute = UISemanticContentAttributeForceLeftToRight; } -#if !TARGET_OS_TV _pinchGestureEnabled = YES; -#endif } return self; } @@ -223,7 +216,6 @@ - (void)setFrame:(CGRect)frame } } -#if !TARGET_OS_TV - (void)setCustomRefreshControl:(UIView *)refreshControl { if (_customRefreshControl) { @@ -256,7 +248,6 @@ - (void)didMoveToWindow // in the setter gets overridden when the view loads. self.pinchGestureRecognizer.enabled = _pinchGestureEnabled; } -#endif // TARGET_OS_TV - (BOOL)shouldGroupAccessibilityChildren { @@ -270,7 +261,7 @@ @interface RCTScrollView () @end @implementation RCTScrollView { - RCTEventDispatcher *_eventDispatcher; + id _eventDispatcher; CGRect _prevFirstVisibleFrame; __weak UIView *_firstVisibleView; RCTCustomScrollView *_scrollView; @@ -284,7 +275,7 @@ @implementation RCTScrollView { NSHashTable *_scrollListeners; } -- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher +- (instancetype)initWithEventDispatcher:(id)eventDispatcher { RCTAssertParam(eventDispatcher); @@ -310,7 +301,6 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher _automaticallyAdjustContentInsets = YES; _contentInset = UIEdgeInsetsZero; - _contentSize = CGSizeZero; _lastClippedToRect = CGRectNull; _scrollEventThrottle = 0.0; @@ -351,15 +341,12 @@ - (void)setRemoveClippedSubviews:(__unused BOOL)removeClippedSubviews - (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex { [super insertReactSubview:view atIndex:atIndex]; -#if !TARGET_OS_TV if ([view conformsToProtocol:@protocol(RCTCustomRefreshContolProtocol)]) { [_scrollView setCustomRefreshControl:(UIView *)view]; if (![view isKindOfClass:[UIRefreshControl class]] && [view conformsToProtocol:@protocol(UIScrollViewDelegate)]) { [self addScrollListener:(UIView *)view]; } - } else -#endif - { + } else { RCTAssert( _contentView == nil, @"RCTScrollView may only contain a single subview, the already set subview looks like: %@", @@ -373,16 +360,13 @@ - (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex - (void)removeReactSubview:(UIView *)subview { [super removeReactSubview:subview]; -#if !TARGET_OS_TV if ([subview conformsToProtocol:@protocol(RCTCustomRefreshContolProtocol)]) { [_scrollView setCustomRefreshControl:nil]; if (![subview isKindOfClass:[UIRefreshControl class]] && [subview conformsToProtocol:@protocol(UIScrollViewDelegate)]) { [self removeScrollListener:(UIView *)subview]; } - } else -#endif - { + } else { RCTAssert(_contentView == subview, @"Attempted to remove non-existent subview"); _contentView = nil; } @@ -396,7 +380,7 @@ - (void)didUpdateReactSubviews - (void)didSetProps:(NSArray *)changedProps { if ([changedProps containsObject:@"contentSize"]) { - [self updateContentOffsetIfNeeded]; + [self updateContentSizeIfNeeded]; } } @@ -730,9 +714,9 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView // Pick snap point based on direction and proximity CGFloat fractionalIndex = (targetContentOffsetAlongAxis + alignmentOffset) / snapToIntervalF; - NSInteger snapIndex = velocityAlongAxis > 0.0 - ? ceil(fractionalIndex) - : velocityAlongAxis < 0.0 ? floor(fractionalIndex) : round(fractionalIndex); + NSInteger snapIndex = velocityAlongAxis > 0.0 ? ceil(fractionalIndex) + : velocityAlongAxis < 0.0 ? floor(fractionalIndex) + : round(fractionalIndex); CGFloat newTargetContentOffset = (snapIndex * snapToIntervalF) - alignmentOffset; // Set new targetContentOffset @@ -814,8 +798,6 @@ - (UIView *)viewForZoomingInScrollView:(__unused UIScrollView *)scrollView return _contentView; } -#pragma mark - Setters - - (CGSize)_calculateViewportSize { CGSize viewportSize = self.bounds.size; @@ -828,71 +810,16 @@ - (CGSize)_calculateViewportSize return viewportSize; } -- (CGPoint)calculateOffsetForContentSize:(CGSize)newContentSize -{ - CGPoint oldOffset = _scrollView.contentOffset; - CGPoint newOffset = oldOffset; - - CGSize oldContentSize = _scrollView.contentSize; - CGSize viewportSize = [self _calculateViewportSize]; - - BOOL fitsinViewportY = oldContentSize.height <= viewportSize.height && newContentSize.height <= viewportSize.height; - if (newContentSize.height < oldContentSize.height && !fitsinViewportY) { - CGFloat offsetHeight = oldOffset.y + viewportSize.height; - if (oldOffset.y < 0) { - // overscrolled on top, leave offset alone - } else if (offsetHeight > oldContentSize.height) { - // overscrolled on the bottom, preserve overscroll amount - newOffset.y = MAX(0, oldOffset.y - (oldContentSize.height - newContentSize.height)); - } else if (offsetHeight > newContentSize.height) { - // offset falls outside of bounds, scroll back to end of list - newOffset.y = MAX(0, newContentSize.height - viewportSize.height); - } - } - - BOOL fitsinViewportX = oldContentSize.width <= viewportSize.width && newContentSize.width <= viewportSize.width; - if (newContentSize.width < oldContentSize.width && !fitsinViewportX) { - CGFloat offsetHeight = oldOffset.x + viewportSize.width; - if (oldOffset.x < 0) { - // overscrolled at the beginning, leave offset alone - } else if (offsetHeight > oldContentSize.width && newContentSize.width > viewportSize.width) { - // overscrolled at the end, preserve overscroll amount as much as possible - newOffset.x = MAX(0, oldOffset.x - (oldContentSize.width - newContentSize.width)); - } else if (offsetHeight > newContentSize.width) { - // offset falls outside of bounds, scroll back to end - newOffset.x = MAX(0, newContentSize.width - viewportSize.width); - } - } - - // all other cases, offset doesn't change - return newOffset; -} - -/** - * Once you set the `contentSize`, to a nonzero value, it is assumed to be - * managed by you, and we'll never automatically compute the size for you, - * unless you manually reset it back to {0, 0} - */ - (CGSize)contentSize { - if (!CGSizeEqualToSize(_contentSize, CGSizeZero)) { - return _contentSize; - } - return _contentView.frame.size; } -- (void)updateContentOffsetIfNeeded +- (void)updateContentSizeIfNeeded { CGSize contentSize = self.contentSize; if (!CGSizeEqualToSize(_scrollView.contentSize, contentSize)) { - // When contentSize is set manually, ScrollView internals will reset - // contentOffset to {0, 0}. Since we potentially set contentSize whenever - // anything in the ScrollView updates, we workaround this issue by manually - // adjusting contentOffset whenever this happens - CGPoint newOffset = [self calculateOffsetForContentSize:contentSize]; _scrollView.contentSize = contentSize; - _scrollView.contentOffset = newOffset; } } @@ -994,10 +921,8 @@ -(type)getter \ RCT_SET_AND_PRESERVE_OFFSET(setMaximumZoomScale, maximumZoomScale, CGFloat) RCT_SET_AND_PRESERVE_OFFSET(setMinimumZoomScale, minimumZoomScale, CGFloat) RCT_SET_AND_PRESERVE_OFFSET(setScrollEnabled, isScrollEnabled, BOOL) -#if !TARGET_OS_TV RCT_SET_AND_PRESERVE_OFFSET(setPagingEnabled, isPagingEnabled, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setScrollsToTop, scrollsToTop, BOOL) -#endif RCT_SET_AND_PRESERVE_OFFSET(setShowsHorizontalScrollIndicator, showsHorizontalScrollIndicator, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setShowsVerticalScrollIndicator, showsVerticalScrollIndicator, BOOL) RCT_SET_AND_PRESERVE_OFFSET(setZoomScale, zoomScale, CGFloat); @@ -1039,9 +964,7 @@ - (void)sendScrollEventWithName:(NSString *)eventName @end -@implementation RCTEventDispatcher (RCTScrollView) - -- (void)sendFakeScrollEvent:(NSNumber *)reactTag +void RCTSendFakeScrollEvent(id eventDispatcher, NSNumber *reactTag) { // Use the selector here in case the onScroll block property is ever renamed NSString *eventName = NSStringFromSelector(@selector(onScroll)); @@ -1054,7 +977,5 @@ - (void)sendFakeScrollEvent:(NSNumber *)reactTag scrollViewZoomScale:0 userData:nil coalescingKey:0]; - [self sendEvent:fakeScrollEvent]; + [eventDispatcher sendEvent:fakeScrollEvent]; } - -@end diff --git a/React/Views/ScrollView/RCTScrollViewManager.m b/React/Views/ScrollView/RCTScrollViewManager.m index a176d1068609ba..086a05450cbd6d 100644 --- a/React/Views/ScrollView/RCTScrollViewManager.m +++ b/React/Views/ScrollView/RCTScrollViewManager.m @@ -78,11 +78,9 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(maximumZoomScale, CGFloat) RCT_EXPORT_VIEW_PROPERTY(minimumZoomScale, CGFloat) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) -#if !TARGET_OS_TV RCT_EXPORT_VIEW_PROPERTY(pagingEnabled, BOOL) RCT_REMAP_VIEW_PROPERTY(pinchGestureEnabled, scrollView.pinchGestureEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollsToTop, BOOL) -#endif RCT_EXPORT_VIEW_PROPERTY(showsHorizontalScrollIndicator, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsVerticalScrollIndicator, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEventThrottle, NSTimeInterval) diff --git a/ReactAndroid/Android-prebuilt.mk b/ReactAndroid/Android-prebuilt.mk new file mode 100644 index 00000000000000..6a704c2bc0855a --- /dev/null +++ b/ReactAndroid/Android-prebuilt.mk @@ -0,0 +1,160 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This configuration provides access to most common React Native prebuilt .so files +# to avoid recompiling each of the libraries outside of ReactAndroid NDK compilation. +# Hosting app's/library's Android.mk can include this Android-prebuilt.mk file to +# get access to those .so to depend on. +# NOTES: +# * Currently, it assumes building React Native from source. +# * Not every .so is listed here (yet). +# * Static libs are not covered here (yet). + +LOCAL_PATH := $(call my-dir) + +FIRST_PARTY_NDK_DIR := $(REACT_ANDROID_DIR)/src/main/jni/first-party +THIRD_PARTY_NDK_DIR := $(REACT_ANDROID_BUILD_DIR)/third-party-ndk +REACT_ANDROID_SRC_DIR := $(REACT_ANDROID_DIR)/src/main +REACT_COMMON_DIR := $(REACT_ANDROID_DIR)/../ReactCommon +REACT_GENERATED_SRC_DIR := $(REACT_ANDROID_BUILD_DIR)/generated/source +# Note: this only have .so, not .a +REACT_NDK_EXPORT_DIR := $(PROJECT_BUILD_DIR)/react-ndk/exported + +# fb +include $(CLEAR_VARS) +LOCAL_MODULE := fb +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libfb.so +LOCAL_EXPORT_C_INCLUDES := $(FIRST_PARTY_NDK_DIR)/fb/include +include $(PREBUILT_SHARED_LIBRARY) + +# folly_json +include $(CLEAR_VARS) +LOCAL_MODULE := folly_json +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libfolly_json.so +LOCAL_EXPORT_C_INCLUDES := \ + $(THIRD_PARTY_NDK_DIR)/boost/boost_1_63_0 \ + $(THIRD_PARTY_NDK_DIR)/double-conversion \ + $(THIRD_PARTY_NDK_DIR)/folly +# Note: Sync with folly/Android.mk. +FOLLY_FLAGS := \ + -DFOLLY_NO_CONFIG=1 \ + -DFOLLY_HAVE_CLOCK_GETTIME=1 \ + -DFOLLY_HAVE_MEMRCHR=1 \ + -DFOLLY_USE_LIBCPP=1 \ + -DFOLLY_MOBILE=1 \ + -DFOLLY_HAVE_XSI_STRERROR_R=1 +LOCAL_CFLAGS += $(FOLLY_FLAGS) +LOCAL_EXPORT_CPPFLAGS := $(FOLLY_FLAGS) +include $(PREBUILT_SHARED_LIBRARY) + +# folly_futures +include $(CLEAR_VARS) +LOCAL_MODULE := folly_futures +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libfolly_futures.so +LOCAL_SHARED_LIBRARIES := liblibfolly_json +include $(PREBUILT_SHARED_LIBRARY) + +# glog +include $(CLEAR_VARS) +LOCAL_MODULE := glog +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libglog.so +LOCAL_EXPORT_C_INCLUDES := $(THIRD_PARTY_NDK_DIR)/glog/exported +LOCAL_SHARED_LIBRARIES := libglog +include $(PREBUILT_SHARED_LIBRARY) + +# yoga +include $(CLEAR_VARS) +LOCAL_MODULE := yoga +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libyoga.so +LOCAL_EXPORT_C_INCLUDES := \ + $(FIRST_PARTY_NDK_DIR)/yogajni/jni \ + $(REACT_COMMON_DIR)/yoga +# Note: Sync with yogajni/Android.mk +LOCAL_CFLAGS += -fvisibility=hidden -fexceptions -frtti -O3 +LOCAL_LDLIBS += -landroid -llog +include $(PREBUILT_SHARED_LIBRARY) + +# react_nativemodule_core +include $(CLEAR_VARS) +LOCAL_MODULE := react_nativemodule_core +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_nativemodule_core.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_ANDROID_SRC_DIR)/jni \ + $(REACT_COMMON_DIR)/callinvoker \ + $(REACT_COMMON_DIR)/jsi \ + $(REACT_COMMON_DIR)/react/nativemodule/core \ + $(REACT_COMMON_DIR)/react/nativemodule/core/platform/android +LOCAL_SHARED_LIBRARIES := libfolly_json +include $(PREBUILT_SHARED_LIBRARY) + +# turbomodulejsijni +include $(CLEAR_VARS) +LOCAL_MODULE := turbomodulejsijni +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libturbomodulejsijni.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_ANDROID_SRC_DIR)/java/com/facebook/react/turbomodule/core/jni +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_core +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_core +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_core.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR) \ + $(REACT_COMMON_DIR)/react/renderer/core +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_debug +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_debug +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_debug.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/react/renderer/debug +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_graphics +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_graphics +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_graphics.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/react/renderer/graphics \ + $(REACT_COMMON_DIR)/react/renderer/graphics/platform/cxx +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_imagemanager +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_imagemanager +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_imagemanager.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/react/renderer/imagemanager \ + $(REACT_COMMON_DIR)/react/renderer/imagemanager/platform/cxx +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_mounting +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_mounting +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_mounting.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/react/renderer/mounting +include $(PREBUILT_SHARED_LIBRARY) + +# react_render_components_view +include $(CLEAR_VARS) +LOCAL_MODULE := react_render_components_view +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_render_components_view.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_COMMON_DIR)/react/renderer/components/view +include $(PREBUILT_SHARED_LIBRARY) + +# react_codegen_rncore +include $(CLEAR_VARS) +LOCAL_MODULE := react_codegen_rncore +LOCAL_SRC_FILES := $(REACT_NDK_EXPORT_DIR)/$(TARGET_ARCH_ABI)/libreact_codegen_rncore.so +LOCAL_EXPORT_C_INCLUDES := \ + $(REACT_GENERATED_SRC_DIR)/codegen/jni +include $(PREBUILT_SHARED_LIBRARY) + +# fbjni +include $(FIRST_PARTY_NDK_DIR)/fbjni/Android.mk diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 1189ead6e9a4c4..8b8a05d29e4738 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -33,11 +33,6 @@ def thirdPartyNdkDir = new File("$buildDir/third-party-ndk") // - glog-0.3.5 def dependenciesPath = System.getenv("REACT_NATIVE_DEPENDENCIES") -// The 'USE_FABRIC' environment variable will build Fabric C++ code into the bundle -// USE_FABRIC=0 will build RN excluding fabric -// USE_FABRIC=1 will build RN including fabric -def enableFabric = (System.getenv('USE_FABRIC') ?: '0').toBoolean() - // The Boost library is a very large download (>100MB). // If Boost is already present on your system, define the REACT_NATIVE_BOOST_PATH env variable // and the build will use that. @@ -247,26 +242,28 @@ def getNdkBuildName() { } def findNdkBuildFullPath() { + // android.ndkDirectory should return project.android.ndkVersion ndkDirectory + def ndkDir = android.ndkDirectory ? android.ndkDirectory.absolutePath : null + if (ndkDir) { + return new File(ndkDir, getNdkBuildName()).getAbsolutePath() + } + // we allow to provide full path to ndk-build tool if (hasProperty("ndk.command")) { return property("ndk.command") } // or just a path to the containing directory if (hasProperty("ndk.path")) { - def ndkDir = property("ndk.path") + ndkDir = property("ndk.path") return new File(ndkDir, getNdkBuildName()).getAbsolutePath() } + // @TODO ANDROID_NDK && ndk.dir is deprecated and will be removed in the future. if (System.getenv("ANDROID_NDK") != null) { - def ndkDir = System.getenv("ANDROID_NDK") + ndkDir = System.getenv("ANDROID_NDK") return new File(ndkDir, getNdkBuildName()).getAbsolutePath() } - def ndkDir = android.ndkDirectory ? android.ndkDirectory.absolutePath : null - - if (ndkDir) { - return new File(ndkDir, getNdkBuildName()).getAbsolutePath() - } return null } @@ -301,9 +298,11 @@ def getNdkBuildFullPath() { def buildReactNdkLib = tasks.register("buildReactNdkLib", Exec) { dependsOn(prepareJSC, prepareHermes, prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog, extractAARHeaders, extractJNIFiles) + dependsOn("generateCodegenArtifactsFromSchema"); inputs.dir("$projectDir/../ReactCommon") inputs.dir("src/main/jni") + inputs.dir("src/main/java/com/facebook/react/turbomodule/core/jni") inputs.dir("src/main/java/com/facebook/react/modules/blob") outputs.dir("$buildDir/react-ndk/all") commandLine(getNdkBuildFullPath(), @@ -314,8 +313,8 @@ def buildReactNdkLib = tasks.register("buildReactNdkLib", Exec) { "NDK_LIBS_OUT=$buildDir/react-ndk/all", "THIRD_PARTY_NDK_DIR=$thirdPartyNdkDir", "REACT_COMMON_DIR=$projectDir/../ReactCommon", + "REACT_GENERATED_SRC_DIR=$buildDir/generated/source", "REACT_SRC_DIR=$projectDir/src/main/java/com/facebook/react", - "BUILD_FABRIC=$enableFabric", "-C", file("src/main/jni/react/jni").absolutePath, "--jobs", project.findProperty("jobs") ?: Runtime.runtime.availableProcessors() ) @@ -380,14 +379,14 @@ task extractJNIFiles { android { compileSdkVersion 29 - + ndkVersion ANDROID_NDK_VERSION compileOptions { sourceCompatibility(JavaVersion.VERSION_1_8) targetCompatibility(JavaVersion.VERSION_1_8) } defaultConfig { - minSdkVersion(19) + minSdkVersion(21) targetSdkVersion(28) versionCode(1) versionName("1.0") @@ -396,6 +395,7 @@ android { buildConfigField("boolean", "IS_INTERNAL_BUILD", "false") buildConfigField("int", "EXOPACKAGE_FLAGS", "0") + buildConfigField("int", "HERMES_BYTECODE_VERSION", "0") resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort() resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort() @@ -434,6 +434,7 @@ android { configurations { extractHeaders extractJNI + javadocDeps.extendsFrom api } } @@ -445,21 +446,24 @@ dependencies { api("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") api("com.facebook.fresco:fresco:${FRESCO_VERSION}") api("com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}") + api("com.facebook.fresco:ui-common:${FRESCO_VERSION}") api("com.facebook.soloader:soloader:${SO_LOADER_VERSION}") 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.15.0") + api("com.squareup.okio:okio:1.17.5") api("com.facebook.fbjni:fbjni-java-only:0.0.3") extractHeaders("com.facebook.fbjni:fbjni:0.0.2:headers") extractJNI("com.facebook.fbjni:fbjni:0.0.2") + javadocDeps("com.squareup:javapoet:1.13.0") + testImplementation("junit:junit:${JUNIT_VERSION}") testImplementation("org.powermock:powermock-api-mockito2:${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.easytesting:fest-assert-core:2.0M10") testImplementation("org.robolectric:robolectric:${ROBOLECTRIC_VERSION}") androidTestImplementation(fileTree(dir: "src/main/third-party/java/buck-android-support/", include: ["*.jar"])) @@ -471,8 +475,10 @@ dependencies { apply(from: "release.gradle") react { - enableCodegen = System.getenv("USE_CODEGEN") ?: false + // TODO: The library name is chosen for parity with Fabric components & iOS + // This should be changed to a more generic name, e.g. `ReactCoreSpec`. + libraryName = "rncore" jsRootDir = file("../Libraries") - reactNativeRootDir = file("$rootDir") + reactNativeRootDir = file("$projectDir/..") useJavaGenerator = System.getenv("USE_CODEGEN_JAVAPOET") ?: false } diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 04ef27362cf6fc..2ae9344c3b8557 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -7,13 +7,12 @@ POM_PACKAGING=aar MOCKITO_CORE_VERSION=2.26.0 POWERMOCK_VERSION=2.0.2 -ROBOLECTRIC_VERSION=4.3.1 +ROBOLECTRIC_VERSION=4.4 JUNIT_VERSION=4.12 -FEST_ASSERT_CORE_VERSION=2.0M10 ANDROIDX_TEST_VERSION=1.1.0 -FRESCO_VERSION=2.0.0 -OKHTTP_VERSION=3.12.12 +FRESCO_VERSION=2.3.0 +OKHTTP_VERSION=3.14.9 SO_LOADER_VERSION=0.9.0 BOOST_VERSION=1_63_0 @@ -23,4 +22,3 @@ GLOG_VERSION=0.3.5 android.useAndroidX=true android.enableJetifier=true -android.enableR8=false diff --git a/ReactAndroid/proguard-rules.pro b/ReactAndroid/proguard-rules.pro index e13dfef7ec70ad..93a74c617b83fa 100644 --- a/ReactAndroid/proguard-rules.pro +++ b/ReactAndroid/proguard-rules.pro @@ -50,17 +50,11 @@ -dontwarn com.facebook.react.** -keep,includedescriptorclasses class com.facebook.react.bridge.** { *; } +-keep,includedescriptorclasses class com.facebook.react.turbomodule.core.** { *; } # hermes -keep class com.facebook.jni.** { *; } -# okhttp - --keepattributes Signature --keepattributes *Annotation* --keep class okhttp3.** { *; } --keep interface okhttp3.** { *; } --dontwarn okhttp3.** # okio diff --git a/ReactAndroid/release.gradle b/ReactAndroid/release.gradle index bf3db45264580c..9ddc7cfc78be21 100644 --- a/ReactAndroid/release.gradle +++ b/ReactAndroid/release.gradle @@ -20,18 +20,6 @@ def isReleaseBuild() { return VERSION_NAME.contains("SNAPSHOT") == false } -def getRepositoryUrl() { - return project.findProperty("repositoryUrl") ?: "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - -def getRepositoryUsername() { - return project.findProperty("repositoryUsername") ?: "" -} - -def getRepositoryPassword() { - return project.findProperty("repositoryPassword") ?: "" -} - def configureReactNativePom(def pom) { pom.project { name(POM_NAME) @@ -72,26 +60,6 @@ if (JavaVersion.current().isJava8Compatible()) { } afterEvaluate { project -> - - task androidJavadoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += files(android.bootClasspath) - classpath += files(project.getConfigurations().getByName("compile").asList()) - include("**/*.java") - exclude("**/ReactBuildConfig.java") - } - - task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) { - classifier = "javadoc" - from(androidJavadoc.destinationDir) - } - - task androidSourcesJar(type: Jar) { - classifier = "sources" - from(android.sourceSets.main.java.srcDirs) - include("**/*.java") - } - android.libraryVariants.all { variant -> def name = variant.name.capitalize() task "jar${name}"(type: Jar, dependsOn: variant.javaCompileProvider.get()) { @@ -99,11 +67,6 @@ afterEvaluate { project -> } } - artifacts { - archives(androidSourcesJar) - archives(androidJavadocJar) - } - version = VERSION_NAME group = GROUP @@ -112,24 +75,6 @@ afterEvaluate { project -> sign(configurations.archives) } - uploadArchives { - configuration = configurations.archives - repositories.mavenDeployer { - beforeDeployment { - MavenDeployment deployment -> signing.signPom(deployment) - } - - repository(url: getRepositoryUrl()) { - authentication( - userName: getRepositoryUsername(), - password: getRepositoryPassword()) - - } - - configureReactNativePom(pom) - } - } - task installArchives(type: Upload) { configuration = configurations.archives repositories.mavenDeployer { diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/BUCK index 6d16a702ecf400..a7162899373bd1 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/BUCK @@ -9,6 +9,7 @@ rn_android_library( "network/**/*.java", ], ), + autoglob = False, is_androidx = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/idledetection/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/idledetection/BUCK index 80a28b690ef50f..b3ed32bb4e9de7 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/idledetection/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/idledetection/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "idledetection", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK index 980eda5d8d0601..d8e68b3f29aa64 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/network/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "network", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK index 1bf0b3c7a8ab15..86d2074e0e1e0a 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/testing/rule/BUCK @@ -11,6 +11,7 @@ load( rn_android_library( name = "rule", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK index 0b29ef31268c22..6cd9d22f56df70 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_int rn_android_library( name = "tests", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/TextInputTestCase.java b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/TextInputTestCase.java index 920ce021812192..88e0cf51e09d74 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/TextInputTestCase.java +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/TextInputTestCase.java @@ -259,8 +259,7 @@ public void run() { /** * Test that the mentions input has colors displayed correctly. Removed for being flaky in open * source, December 2016 public void testMetionsInputColors() throws Throwable { EventDispatcher - * eventDispatcher = - * getReactContext().getNativeModule(UIManagerModule.class).getEventDispatcher(); ReactEditText + * eventDispatcher = UIManagerHelper.getEventEmitterForReactTag(reactContext, tag); ReactEditText * reactEditText = getViewByTestId("tokenizedInput"); String newText = "#Things and more #things"; * int contentWidth = reactEditText.getWidth(); int contentHeight = reactEditText.getHeight(); int * start = 0; int count = newText.length(); diff --git a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK index 0c2c6a3781d998..2aa06b7cbf83ba 100644 --- a/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK +++ b/ReactAndroid/src/androidTest/java/com/facebook/react/tests/core/BUCK @@ -11,6 +11,7 @@ load( rn_android_library( name = "core", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, deps = ([ react_native_dep("third-party/android/androidx:test-espresso-core"), diff --git a/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js b/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js index 3a6a887919bf26..11ee033dc84987 100644 --- a/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js +++ b/ReactAndroid/src/androidTest/js/ScrollViewTestModule.js @@ -30,7 +30,7 @@ import type {PressEvent} from 'react-native/Libraries/Types/CoreEventTypes'; // Shared by integration tests for ScrollView and HorizontalScrollView -let scrollViewApp; +let scrollViewApp: ScrollViewTestApp | HorizontalScrollViewTestApp; type ItemProps = $ReadOnly<{| onPress: (event: PressEvent) => void, diff --git a/ReactAndroid/src/main/java/com/facebook/BUCK b/ReactAndroid/src/main/java/com/facebook/BUCK index a7461d145d8fc2..f24e877ad0ad4f 100644 --- a/ReactAndroid/src/main/java/com/facebook/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "yoga", srcs = glob(["yoga/*.java"]), + autoglob = False, visibility = ["PUBLIC"], deps = [ react_native_dep("libraries/fbjni:java"), diff --git a/ReactAndroid/src/main/java/com/facebook/debug/debugoverlay/model/BUCK b/ReactAndroid/src/main/java/com/facebook/debug/debugoverlay/model/BUCK index a161001ec1cab1..3ccc5d058d7d85 100644 --- a/ReactAndroid/src/main/java/com/facebook/debug/debugoverlay/model/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/debug/debugoverlay/model/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "model", srcs = glob(["*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK b/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK index 2daef176010bf5..13c5da59066b27 100644 --- a/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/debug/holder/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "holder", srcs = glob(["*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK b/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK index 3e2e015c78e8d2..2133f0f6b9978b 100644 --- a/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/debug/tags/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "tags", srcs = glob(["*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK deleted file mode 100644 index 94067e4f20f33d..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/BUCK +++ /dev/null @@ -1,58 +0,0 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "IS_OSS_BUILD", "react_native_dep", "react_native_target", "react_native_xplat_target", "rn_android_library", "rn_xplat_cxx_library") - -rn_android_library( - name = "FBReactNativeSpec", - srcs = glob(["*.java"]), - labels = ["supermodule:xplat/default/public.react_native.infra"], - visibility = ["PUBLIC"], - deps = [ - react_native_dep("third-party/java/jsr-305:jsr-305"), - react_native_dep("third-party/java/jsr-330:jsr-330"), - react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_target("java/com/facebook/react/common:common"), - ], - exported_deps = [ - react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), - ], -) - -rn_xplat_cxx_library( - name = "FBReactNativeSpec-jni", - srcs = [ - "jni/FBReactNativeSpec-generated.cpp", - ], - headers = { - "FBReactNativeSpec/FBReactNativeSpec.h": "jni/FBReactNativeSpec.h", - }, - header_namespace = "", - exported_headers = { - "FBReactNativeSpec/FBReactNativeSpec.h": "jni/FBReactNativeSpec.h", - }, - compiler_flags = [ - "-fexceptions", - "-frtti", - "-std=c++14", - "-Wall", - ], - labels = ["supermodule:xplat/default/public.react_native.infra"], - platforms = (ANDROID,), - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - visibility = [ - "PUBLIC", - ], - deps = [ - FBJNI_TARGET, - "//xplat/folly:molly", - "//xplat/jsi:JSIDynamic", - react_native_target("jni/react/jni:jni"), - react_native_xplat_target("cxxreact:bridge"), - ], - exported_deps = ([ - react_native_xplat_target("turbomodule/core:core"), - ]) + ([ - "//xplat/jsi:jsi", - ]) if not IS_OSS_BUILD else [], -) diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityInfoSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityInfoSpec.java deleted file mode 100644 index 28b6ffd9dec794..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityInfoSpec.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAccessibilityInfoSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAccessibilityInfoSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void announceForAccessibility(String announcement); - - @ReactMethod - public abstract void isReduceMotionEnabled(Callback onSuccess); - - @ReactMethod - public abstract void isTouchExplorationEnabled(Callback onSuccess); - - @ReactMethod - public abstract void setAccessibilityFocus(double reactTag); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityManagerSpec.java deleted file mode 100644 index 55a5b4864dec36..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAccessibilityManagerSpec.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAccessibilityManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAccessibilityManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void announceForAccessibility(String announcement); - - @ReactMethod - public abstract void getCurrentBoldTextState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void getCurrentGrayscaleState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void getCurrentInvertColorsState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void getCurrentReduceMotionState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void getCurrentReduceTransparencyState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void getCurrentVoiceOverState(Callback onSuccess, Callback onError); - - @ReactMethod - public abstract void setAccessibilityContentSizeMultipliers(ReadableMap JSMultipliers); - - @ReactMethod - public abstract void setAccessibilityFocus(double reactTag); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeActionSheetManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeActionSheetManagerSpec.java deleted file mode 100644 index 4fd38854928645..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeActionSheetManagerSpec.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeActionSheetManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeActionSheetManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void showActionSheetWithOptions(ReadableMap options, Callback callback); - - @ReactMethod - public abstract void showShareActionSheetWithOptions(ReadableMap options, - Callback failureCallback, Callback successCallback); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAlertManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAlertManagerSpec.java deleted file mode 100644 index 312556634f478c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAlertManagerSpec.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAlertManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAlertManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void alertWithArgs(ReadableMap args, Callback callback); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedModuleSpec.java deleted file mode 100644 index a39644253321de..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedModuleSpec.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAnimatedModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAnimatedModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addAnimatedEventToView(double viewTag, String eventName, - ReadableMap eventMapping); - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void connectAnimatedNodeToView(double nodeTag, double viewTag); - - @ReactMethod - public abstract void connectAnimatedNodes(double parentTag, double childTag); - - @ReactMethod - public abstract void createAnimatedNode(double tag, ReadableMap config); - - @ReactMethod - public abstract void disconnectAnimatedNodeFromView(double nodeTag, double viewTag); - - @ReactMethod - public abstract void disconnectAnimatedNodes(double parentTag, double childTag); - - @ReactMethod - public abstract void dropAnimatedNode(double tag); - - @ReactMethod - public abstract void extractAnimatedNodeOffset(double nodeTag); - - @ReactMethod - public abstract void finishOperationBatch(); - - @ReactMethod - public abstract void flattenAnimatedNodeOffset(double nodeTag); - - @ReactMethod - public abstract void getValue(double tag, Callback saveValueCallback); - - @ReactMethod - public abstract void removeAnimatedEventFromView(double viewTag, String eventName, - double animatedNodeTag); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void restoreDefaultValues(double nodeTag); - - @ReactMethod - public abstract void setAnimatedNodeOffset(double nodeTag, double offset); - - @ReactMethod - public abstract void setAnimatedNodeValue(double nodeTag, double value); - - @ReactMethod - public abstract void startAnimatingNode(double animationId, double nodeTag, ReadableMap config, - Callback endCallback); - - @ReactMethod - public abstract void startListeningToAnimatedNodeValue(double tag); - - @ReactMethod - public abstract void startOperationBatch(); - - @ReactMethod - public abstract void stopAnimation(double animationId); - - @ReactMethod - public abstract void stopListeningToAnimatedNodeValue(double tag); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedTurboModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedTurboModuleSpec.java deleted file mode 100644 index 7b2cbe8f0fb31c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimatedTurboModuleSpec.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAnimatedTurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAnimatedTurboModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addAnimatedEventToView(double viewTag, String eventName, - ReadableMap eventMapping); - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void connectAnimatedNodeToView(double nodeTag, double viewTag); - - @ReactMethod - public abstract void connectAnimatedNodes(double parentTag, double childTag); - - @ReactMethod - public abstract void createAnimatedNode(double tag, ReadableMap config); - - @ReactMethod - public abstract void disconnectAnimatedNodeFromView(double nodeTag, double viewTag); - - @ReactMethod - public abstract void disconnectAnimatedNodes(double parentTag, double childTag); - - @ReactMethod - public abstract void dropAnimatedNode(double tag); - - @ReactMethod - public abstract void extractAnimatedNodeOffset(double nodeTag); - - @ReactMethod - public abstract void finishOperationBatch(); - - @ReactMethod - public abstract void flattenAnimatedNodeOffset(double nodeTag); - - @ReactMethod - public abstract void getValue(double tag, Callback saveValueCallback); - - @ReactMethod - public abstract void removeAnimatedEventFromView(double viewTag, String eventName, - double animatedNodeTag); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void restoreDefaultValues(double nodeTag); - - @ReactMethod - public abstract void setAnimatedNodeOffset(double nodeTag, double offset); - - @ReactMethod - public abstract void setAnimatedNodeValue(double nodeTag, double value); - - @ReactMethod - public abstract void startAnimatingNode(double animationId, double nodeTag, ReadableMap config, - Callback endCallback); - - @ReactMethod - public abstract void startListeningToAnimatedNodeValue(double tag); - - @ReactMethod - public abstract void startOperationBatch(); - - @ReactMethod - public abstract void stopAnimation(double animationId); - - @ReactMethod - public abstract void stopListeningToAnimatedNodeValue(double tag); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimationsDebugModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimationsDebugModuleSpec.java deleted file mode 100644 index 19c3a63a8726a7..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAnimationsDebugModuleSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAnimationsDebugModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAnimationsDebugModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void startRecordingFps(); - - @ReactMethod - public abstract void stopRecordingFps(double animationStopTimeMs); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppStateSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppStateSpec.java deleted file mode 100644 index 8b0afaa075cd1e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppStateSpec.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeAppStateSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAppStateSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void getCurrentAppState(Callback success, Callback error); - - @ReactMethod - public abstract void removeListeners(double count); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "initialAppState" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppearanceSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppearanceSpec.java deleted file mode 100644 index 1607303108c28a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAppearanceSpec.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import javax.annotation.Nullable; - -public abstract class NativeAppearanceSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAppearanceSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod( - isBlockingSynchronousMethod = true - ) - public abstract @Nullable String getColorScheme(); - - @ReactMethod - public abstract void removeListeners(double count); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAsyncStorageSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAsyncStorageSpec.java deleted file mode 100644 index 9c61d97d2666b0..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeAsyncStorageSpec.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeAsyncStorageSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAsyncStorageSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void clear(Callback callback); - - @ReactMethod - public abstract void getAllKeys(Callback callback); - - @ReactMethod - public abstract void multiGet(ReadableArray keys, Callback callback); - - @ReactMethod - public abstract void multiMerge(ReadableArray kvPairs, Callback callback); - - @ReactMethod - public abstract void multiRemove(ReadableArray keys, Callback callback); - - @ReactMethod - public abstract void multiSet(ReadableArray kvPairs, Callback callback); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBlobModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBlobModuleSpec.java deleted file mode 100644 index af7dcd2825f967..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBlobModuleSpec.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeBlobModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeBlobModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addNetworkingHandler(); - - @ReactMethod - public abstract void addWebSocketHandler(double id); - - @ReactMethod - public abstract void createFromParts(ReadableArray parts, String withId); - - @ReactMethod - public abstract void release(String blobId); - - @ReactMethod - public abstract void removeWebSocketHandler(double id); - - @ReactMethod - public abstract void sendOverSocket(ReadableMap blob, double socketID); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(); - Set optionalFlowConstants = new HashSet<>(Arrays.asList( - "BLOB_URI_HOST", - "BLOB_URI_SCHEME" - )); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBugReportingSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBugReportingSpec.java deleted file mode 100644 index 3ea9024d8244bb..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeBugReportingSpec.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeBugReportingSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeBugReportingSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void setCategoryID(String categoryID); - - @ReactMethod - public abstract void setExtraData(ReadableMap extraData, ReadableMap extraFiles); - - @ReactMethod - public abstract void startReportAProblemFlow(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeClipboardSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeClipboardSpec.java deleted file mode 100644 index 9f53ce9ab48951..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeClipboardSpec.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeClipboardSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeClipboardSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void getString(Promise promise); - - @ReactMethod - public abstract void setString(String content); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDatePickerAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDatePickerAndroidSpec.java deleted file mode 100644 index fb2280e2a6830c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDatePickerAndroidSpec.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDatePickerAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDatePickerAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void open(ReadableMap options, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevLoadingViewSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevLoadingViewSpec.java deleted file mode 100644 index 95a3c553a48f8f..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevLoadingViewSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDevLoadingViewSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDevLoadingViewSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void hide(); - - @ReactMethod - public abstract void showMessage(String message, Double withColor, Double withBackgroundColor); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevMenuSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevMenuSpec.java deleted file mode 100644 index a2193eb6101c1a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevMenuSpec.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDevMenuSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDevMenuSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void debugRemotely(boolean enableDebug); - - @ReactMethod - public abstract void reload(); - - @ReactMethod - public abstract void setHotLoadingEnabled(boolean enabled); - - @ReactMethod - public abstract void setProfilingEnabled(boolean enabled); - - @ReactMethod - public abstract void show(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSettingsSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSettingsSpec.java deleted file mode 100644 index 13e3264a4be9a5..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSettingsSpec.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDevSettingsSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDevSettingsSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void addMenuItem(String title); - - @ReactMethod - public void onFastRefresh() { - } - - @ReactMethod - public abstract void reload(); - - @ReactMethod - public void reloadWithReason(String reason) { - } - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void setHotLoadingEnabled(boolean isHotLoadingEnabled); - - @ReactMethod - public abstract void setIsDebuggingRemotely(boolean isDebuggingRemotelyEnabled); - - @ReactMethod - public abstract void setIsShakeToShowDevMenuEnabled(boolean enabled); - - @ReactMethod - public abstract void setProfilingEnabled(boolean isProfilingEnabled); - - @ReactMethod - public abstract void toggleElementInspector(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSplitBundleLoaderSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSplitBundleLoaderSpec.java deleted file mode 100644 index 979b134c908d27..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDevSplitBundleLoaderSpec.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDevSplitBundleLoaderSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDevSplitBundleLoaderSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void loadBundle(String bundlePath, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceEventManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceEventManagerSpec.java deleted file mode 100644 index 22c06fe9756930..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceEventManagerSpec.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeDeviceEventManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDeviceEventManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void invokeDefaultBackPressHandler(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceInfoSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceInfoSpec.java deleted file mode 100644 index a9013c5927510e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDeviceInfoSpec.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeDeviceInfoSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDeviceInfoSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "Dimensions" - )); - Set optionalFlowConstants = new HashSet<>(Arrays.asList( - "isIPhoneX_deprecated" - )); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDialogManagerAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDialogManagerAndroidSpec.java deleted file mode 100644 index 9f2f8986a51e70..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeDialogManagerAndroidSpec.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeDialogManagerAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeDialogManagerAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void showAlert(ReadableMap config, Callback onError, Callback onAction); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "buttonNeutral", - "buttonClicked", - "dismissed", - "buttonNegative", - "buttonPositive" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeExceptionsManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeExceptionsManagerSpec.java deleted file mode 100644 index 602e72a398a42a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeExceptionsManagerSpec.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeExceptionsManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public void dismissRedbox() { - } - - @ReactMethod - public void reportException(ReadableMap data) { - } - - @ReactMethod - public abstract void reportFatalException(String message, ReadableArray stack, - double exceptionId); - - @ReactMethod - public abstract void reportSoftException(String message, ReadableArray stack, double exceptionId); - - @ReactMethod - public abstract void updateExceptionMessage(String message, ReadableArray stack, - double exceptionId); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFileReaderModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFileReaderModuleSpec.java deleted file mode 100644 index a15fb30bd9698a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFileReaderModuleSpec.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeFileReaderModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeFileReaderModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void readAsDataURL(ReadableMap data, Promise promise); - - @ReactMethod - public abstract void readAsText(ReadableMap data, String encoding, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFrameRateLoggerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFrameRateLoggerSpec.java deleted file mode 100644 index 6467880edc6145..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeFrameRateLoggerSpec.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeFrameRateLoggerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeFrameRateLoggerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void beginScroll(); - - @ReactMethod - public abstract void endScroll(); - - @ReactMethod - public abstract void setContext(String context); - - @ReactMethod - public abstract void setGlobalOptions(ReadableMap options); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeadlessJsTaskSupportSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeadlessJsTaskSupportSpec.java deleted file mode 100644 index d59015eddadf3b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeadlessJsTaskSupportSpec.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeHeadlessJsTaskSupportSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeHeadlessJsTaskSupportSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void notifyTaskFinished(double taskId); - - @ReactMethod - public abstract void notifyTaskRetry(double taskId, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeapCaptureSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeapCaptureSpec.java deleted file mode 100644 index c2f84fcc59ad8a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeHeapCaptureSpec.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import javax.annotation.Nullable; - -public abstract class NativeHeapCaptureSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeHeapCaptureSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void captureComplete(String path, @Nullable String error); - - @ReactMethod - public abstract void captureHeap(String path); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeI18nManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeI18nManagerSpec.java deleted file mode 100644 index a3eec9b7d0b8db..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeI18nManagerSpec.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeI18nManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeI18nManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void allowRTL(boolean allowRTL); - - @ReactMethod - public abstract void forceRTL(boolean forceRTL); - - @ReactMethod - public abstract void swapLeftAndRightInRTL(boolean flipStyles); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "doLeftAndRightSwapInRTL", - "isRTL" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageEditorSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageEditorSpec.java deleted file mode 100644 index 9e65f7ed88d454..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageEditorSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImageEditorSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImageEditorSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void cropImage(String uri, ReadableMap cropData, Callback successCallback, - Callback errorCallback); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderAndroidSpec.java deleted file mode 100644 index 9ac42bef67e1fe..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderAndroidSpec.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImageLoaderAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImageLoaderAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void abortRequest(double requestId); - - @ReactMethod - public abstract void getSize(String uri, Promise promise); - - @ReactMethod - public abstract void getSizeWithHeaders(String uri, ReadableMap headers, Promise promise); - - @ReactMethod - public abstract void prefetchImage(String uri, double requestId, Promise promise); - - @ReactMethod - public abstract void queryCache(ReadableArray uris, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderIOSSpec.java deleted file mode 100644 index 61be2c8700664b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderIOSSpec.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImageLoaderIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImageLoaderIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void getSize(String uri, Promise promise); - - @ReactMethod - public abstract void getSizeWithHeaders(String uri, ReadableMap headers, Promise promise); - - @ReactMethod - public abstract void prefetchImage(String uri, Promise promise); - - @ReactMethod - public abstract void queryCache(ReadableArray uris, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderSpec.java deleted file mode 100644 index eabf4a29d3b355..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageLoaderSpec.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImageLoaderSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImageLoaderSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void getSize(String uri, Promise promise); - - @ReactMethod - public abstract void prefetchImage(String uri, Promise promise); - - @ReactMethod - public abstract void queryCache(ReadableArray uris, Promise promise); - - @ReactMethod - public abstract void getSizeWithHeaders(String uri, ReadableMap headers, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImagePickerIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImagePickerIOSSpec.java deleted file mode 100644 index 4c39c1bddb9939..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImagePickerIOSSpec.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImagePickerIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImagePickerIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void canRecordVideos(Callback callback); - - @ReactMethod - public abstract void canUseCamera(Callback callback); - - @ReactMethod - public abstract void clearAllPendingVideos(); - - @ReactMethod - public abstract void openCameraDialog(ReadableMap config, Callback successCallback, - Callback cancelCallback); - - @ReactMethod - public abstract void openSelectDialog(ReadableMap config, Callback successCallback, - Callback cancelCallback); - - @ReactMethod - public abstract void removePendingVideo(String url); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreSpec.java deleted file mode 100644 index b326af8a3995e3..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreSpec.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImageStoreSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImageStoreSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addImageFromBase64(String base64ImageData, Callback successCallback, - Callback errorCallback); - - @ReactMethod - public abstract void getBase64ForTag(String uri, Callback successCallback, - Callback errorCallback); - - @ReactMethod - public abstract void hasImageForTag(String uri, Callback callback); - - @ReactMethod - public abstract void removeImageForTag(String uri); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCHeapCaptureSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCHeapCaptureSpec.java deleted file mode 100644 index f74a8a12912e92..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCHeapCaptureSpec.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import javax.annotation.Nullable; - -public abstract class NativeJSCHeapCaptureSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeJSCHeapCaptureSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void captureComplete(String path, @Nullable String error); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCSamplingProfilerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCSamplingProfilerSpec.java deleted file mode 100644 index 5d4504d547df32..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSCSamplingProfilerSpec.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import javax.annotation.Nullable; - -public abstract class NativeJSCSamplingProfilerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeJSCSamplingProfilerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void operationComplete(double token, @Nullable String result, - @Nullable String error); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSDevSupportSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSDevSupportSpec.java deleted file mode 100644 index 4e76f968ae6923..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeJSDevSupportSpec.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeJSDevSupportSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeJSDevSupportSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void onFailure(double errorCode, String error); - - @ReactMethod - public abstract void onSuccess(String data); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "ERROR_CODE_EXCEPTION", - "ERROR_CODE_VIEW_NOT_FOUND" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeKeyboardObserverSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeKeyboardObserverSpec.java deleted file mode 100644 index 09b5f77b98ab93..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeKeyboardObserverSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeKeyboardObserverSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeKeyboardObserverSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void removeListeners(double count); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLinkingSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLinkingSpec.java deleted file mode 100644 index 030c478a563115..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLinkingSpec.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeLinkingSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeLinkingSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void canOpenURL(String url, Promise promise); - - @ReactMethod - public abstract void getInitialURL(Promise promise); - - @ReactMethod - public abstract void openSettings(Promise promise); - - @ReactMethod - public abstract void openURL(String url, Promise promise); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void sendIntent(String action, ReadableArray extras, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLogBoxSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLogBoxSpec.java deleted file mode 100644 index 085f0559be5f50..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeLogBoxSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeLogBoxSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeLogBoxSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void hide(); - - @ReactMethod - public abstract void show(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeModalManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeModalManagerSpec.java deleted file mode 100644 index 4fecb161c48f17..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeModalManagerSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeModalManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeModalManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void removeListeners(double count); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingAndroidSpec.java deleted file mode 100644 index dfbc2b9c0ff32a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingAndroidSpec.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeNetworkingAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeNetworkingAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void abortRequest(double requestId); - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void clearCookies(Callback callback); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void sendRequest(String method, String url, double requestId, - ReadableArray headers, ReadableMap data, String responseType, boolean useIncrementalUpdates, - double timeout, boolean withCredentials); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingIOSSpec.java deleted file mode 100644 index a6764d54b6b96c..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeNetworkingIOSSpec.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeNetworkingIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeNetworkingIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void abortRequest(double requestId); - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void clearCookies(Callback callback); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void sendRequest(ReadableMap query, Callback callback); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePermissionsAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePermissionsAndroidSpec.java deleted file mode 100644 index 9c7a3cb6e1233a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePermissionsAndroidSpec.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativePermissionsAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativePermissionsAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void checkPermission(String permission, Promise promise); - - @ReactMethod - public abstract void requestMultiplePermissions(ReadableArray permissions, Promise promise); - - @ReactMethod - public abstract void requestPermission(String permission, Promise promise); - - @ReactMethod - public abstract void shouldShowRequestPermissionRationale(String permission, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsAndroidSpec.java deleted file mode 100644 index 00d2039ade6a21..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsAndroidSpec.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativePlatformConstantsAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativePlatformConstantsAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod( - isBlockingSynchronousMethod = true - ) - public abstract String getAndroidID(); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "Brand", - "Serial", - "Fingerprint", - "uiMode", - "Version", - "reactNativeVersion", - "Model", - "Manufacturer", - "isTesting", - "Release" - )); - Set optionalFlowConstants = new HashSet<>(Arrays.asList( - "ServerHost" - )); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsIOSSpec.java deleted file mode 100644 index 454b3f75d4e016..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePlatformConstantsIOSSpec.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativePlatformConstantsIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativePlatformConstantsIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "osVersion", - "systemName", - "forceTouchAvailable", - "reactNativeVersion", - "interfaceIdiom", - "isTesting" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePushNotificationManagerIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePushNotificationManagerIOSSpec.java deleted file mode 100644 index 4cda64dd6907fe..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativePushNotificationManagerIOSSpec.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativePushNotificationManagerIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativePushNotificationManagerIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void abandonPermissions(); - - @ReactMethod - public abstract void addListener(String eventType); - - @ReactMethod - public abstract void cancelAllLocalNotifications(); - - @ReactMethod - public abstract void cancelLocalNotifications(ReadableMap userInfo); - - @ReactMethod - public abstract void checkPermissions(Callback callback); - - @ReactMethod - public abstract void getApplicationIconBadgeNumber(Callback callback); - - @ReactMethod - public abstract void getDeliveredNotifications(Callback callback); - - @ReactMethod - public abstract void getInitialNotification(Promise promise); - - @ReactMethod - public abstract void getScheduledLocalNotifications(Callback callback); - - @ReactMethod - public abstract void onFinishRemoteNotification(String notificationId, String fetchResult); - - @ReactMethod - public abstract void presentLocalNotification(ReadableMap notification); - - @ReactMethod - public abstract void removeAllDeliveredNotifications(); - - @ReactMethod - public abstract void removeDeliveredNotifications(ReadableArray identifiers); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void requestPermissions(ReadableMap permission, Promise promise); - - @ReactMethod - public abstract void scheduleLocalNotification(ReadableMap notification); - - @ReactMethod - public abstract void setApplicationIconBadgeNumber(double num); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeRedBoxSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeRedBoxSpec.java deleted file mode 100644 index 4a5223cee7325d..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeRedBoxSpec.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeRedBoxSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeRedBoxSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void dismiss(); - - @ReactMethod - public abstract void setExtraData(ReadableMap extraData, String forIdentifier); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSegmentFetcherSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSegmentFetcherSpec.java deleted file mode 100644 index 45946a5605f434..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSegmentFetcherSpec.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeSegmentFetcherSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSegmentFetcherSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void fetchSegment(double segmentId, ReadableMap options, Callback callback); - - @ReactMethod - public void getSegment(double segmentId, ReadableMap options, Callback callback) { - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSettingsManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSettingsManagerSpec.java deleted file mode 100644 index ebeeb2fc0a5d86..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSettingsManagerSpec.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeSettingsManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSettingsManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void deleteValues(ReadableArray values); - - @ReactMethod - public abstract void setValues(ReadableMap values); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "settings" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeShareModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeShareModuleSpec.java deleted file mode 100644 index ae5740bf4fe595..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeShareModuleSpec.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeShareModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeShareModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void share(ReadableMap content, String dialogTitle, Promise promise); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSoundManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSoundManagerSpec.java deleted file mode 100644 index c139b51f60e40f..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSoundManagerSpec.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeSoundManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSoundManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void playTouchSound(); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSourceCodeSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSourceCodeSpec.java deleted file mode 100644 index 7b462d4d625ad5..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeSourceCodeSpec.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeSourceCodeSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSourceCodeSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "scriptURL" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerAndroidSpec.java deleted file mode 100644 index 4550a529f3682d..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerAndroidSpec.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeStatusBarManagerAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeStatusBarManagerAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void setColor(double color, boolean animated); - - @ReactMethod - public abstract void setHidden(boolean hidden); - - @ReactMethod - public abstract void setStyle(@Nullable String statusBarStyle); - - @ReactMethod - public abstract void setTranslucent(boolean translucent); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "DEFAULT_BACKGROUND_COLOR", - "HEIGHT" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerIOSSpec.java deleted file mode 100644 index 9e4ebb50dde5e1..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerIOSSpec.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeStatusBarManagerIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeStatusBarManagerIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventType); - - @ReactMethod - public abstract void getHeight(Callback callback); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void setHidden(boolean hidden, String withAnimation); - - @ReactMethod - public abstract void setNetworkActivityIndicatorVisible(boolean visible); - - @ReactMethod - public abstract void setStyle(@Nullable String statusBarStyle, boolean animated); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "HEIGHT" - )); - Set optionalFlowConstants = new HashSet<>(Arrays.asList( - "DEFAULT_BACKGROUND_COLOR" - )); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerSpec.java deleted file mode 100644 index fa6181627b1fb8..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeStatusBarManagerSpec.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeStatusBarManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeStatusBarManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void setNetworkActivityIndicatorVisible(boolean visible); - - @ReactMethod - public abstract void setTranslucent(boolean translucent); - - @ReactMethod - public abstract void getHeight(Callback callback); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void setColor(double color, boolean animated); - - @ReactMethod - public abstract void setHidden(boolean hidden, @Nullable String withAnimation); - - @ReactMethod - public abstract void setStyle(@Nullable String statusBarStyle, Boolean animated); - - @ReactMethod - public abstract void addListener(String eventType); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "DEFAULT_BACKGROUND_COLOR", - "HEIGHT" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTVNavigationEventEmitterSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTVNavigationEventEmitterSpec.java deleted file mode 100644 index 61bdb600da1bdd..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTVNavigationEventEmitterSpec.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeTVNavigationEventEmitterSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeTVNavigationEventEmitterSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void removeListeners(double count); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTimingSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTimingSpec.java deleted file mode 100644 index f93eaf2fb6b10f..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeTimingSpec.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeTimingSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeTimingSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void createTimer(double callbackID, double duration, double jsSchedulingTime, - boolean repeats); - - @ReactMethod - public abstract void deleteTimer(double timerID); - - @ReactMethod - public abstract void setSendIdleEvents(boolean sendIdleEvents); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeToastAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeToastAndroidSpec.java deleted file mode 100644 index 43fc546e0e4dc1..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeToastAndroidSpec.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; - -public abstract class NativeToastAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeToastAndroidSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void show(String message, double duration); - - @ReactMethod - public abstract void showWithGravity(String message, double duration, double gravity); - - @ReactMethod - public abstract void showWithGravityAndOffset(String message, double duration, double gravity, - double xOffset, double yOffset); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { - Set obligatoryFlowConstants = new HashSet<>(Arrays.asList( - "CENTER", - "TOP", - "BOTTOM", - "SHORT", - "LONG" - )); - Set optionalFlowConstants = new HashSet<>(); - Set undeclaredConstants = new HashSet<>(constants.keySet()); - undeclaredConstants.removeAll(obligatoryFlowConstants); - undeclaredConstants.removeAll(optionalFlowConstants); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); - } - undeclaredConstants = obligatoryFlowConstants; - undeclaredConstants.removeAll(constants.keySet()); - if (!undeclaredConstants.isEmpty()) { - throw new IllegalStateException(String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); - } - } - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeUIManagerSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeUIManagerSpec.java deleted file mode 100644 index fa173e29538921..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeUIManagerSpec.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import java.util.Map; -import javax.annotation.Nullable; - -public abstract class NativeUIManagerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeUIManagerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void blur(Double reactTag); - - @ReactMethod - public abstract void clearJSResponder(); - - @ReactMethod - public abstract void configureNextLayoutAnimation(ReadableMap config, Callback callback, - Callback errorCallback); - - @ReactMethod - public abstract void createView(Double reactTag, String viewName, double rootTag, - ReadableMap props); - - @ReactMethod - public abstract void dismissPopupMenu(); - - @ReactMethod - public abstract void dispatchViewManagerCommand(Double reactTag, double commandID, - ReadableArray commandArgs); - - @ReactMethod - public abstract void findSubviewIn(Double reactTag, ReadableArray point, Callback callback); - - @ReactMethod - public abstract void focus(Double reactTag); - - @ReactMethod( - isBlockingSynchronousMethod = true - ) - public abstract WritableMap getConstantsForViewManager(String viewManagerName); - - @ReactMethod( - isBlockingSynchronousMethod = true - ) - public abstract WritableArray getDefaultEventTypes(); - - @ReactMethod( - isBlockingSynchronousMethod = true - ) - public abstract WritableMap lazilyLoadView(String name); - - @ReactMethod - public abstract void manageChildren(Double containerTag, ReadableArray moveFromIndices, - ReadableArray moveToIndices, ReadableArray addChildReactTags, ReadableArray addAtIndices, - ReadableArray removeAtIndices); - - @ReactMethod - public abstract void measure(Double reactTag, Callback callback); - - @ReactMethod - public abstract void measureInWindow(Double reactTag, Callback callback); - - @ReactMethod - public abstract void measureLayout(Double reactTag, Double ancestorReactTag, - Callback errorCallback, Callback callback); - - @ReactMethod - public abstract void measureLayoutRelativeToParent(Double reactTag, Callback errorCallback, - Callback callback); - - @ReactMethod - public abstract void removeSubviewsFromContainerWithID(double containerID); - - @ReactMethod - public abstract void replaceExistingNonRootView(Double reactTag, Double newReactTag); - - @ReactMethod - public abstract void sendAccessibilityEvent(Double reactTag, double eventType); - - @ReactMethod - public abstract void setChildren(Double containerTag, ReadableArray reactTags); - - @ReactMethod - public abstract void setJSResponder(Double reactTag, boolean blockNativeResponder); - - @ReactMethod - public abstract void setLayoutAnimationEnabledExperimental(boolean enabled); - - @ReactMethod - public abstract void showPopupMenu(Double reactTag, ReadableArray items, Callback error, - Callback success); - - @ReactMethod - public abstract void updateView(double reactTag, String viewName, ReadableMap props); - - @ReactMethod - public abstract void viewIsDescendantOf(Double reactTag, Double ancestorReactTag, - Callback callback); - - protected abstract Map getTypedExportedConstants(); - - @Override - public final @Nullable Map getConstants() { - Map constants = getTypedExportedConstants(); - return constants; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeVibrationSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeVibrationSpec.java deleted file mode 100644 index 286341152d56e3..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeVibrationSpec.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeVibrationSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeVibrationSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void cancel(); - - @ReactMethod - public abstract void vibrate(double pattern); - - @ReactMethod - public abstract void vibrateByPattern(ReadableArray pattern, double repeat); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeWebSocketModuleSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeWebSocketModuleSpec.java deleted file mode 100644 index 1044c55a51d181..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeWebSocketModuleSpec.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - *

Generated by an internal genrule from Flow types. - * - * @generated - * @nolint - */ - -package com.facebook.fbreact.specs; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeWebSocketModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeWebSocketModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void addListener(String eventName); - - @ReactMethod - public abstract void close(double code, String reason, double socketID); - - @ReactMethod - public abstract void connect(String url, ReadableArray protocols, ReadableMap options, - double socketID); - - @ReactMethod - public abstract void ping(double socketID); - - @ReactMethod - public abstract void removeListeners(double count); - - @ReactMethod - public abstract void send(String message, double forSocketID); - - @ReactMethod - public abstract void sendBinary(String base64String, double forSocketID); -} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp deleted file mode 100644 index 85c52d7e79592a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp +++ /dev/null @@ -1,2639 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal genrule from Flow types. - * - * We create an umbrella header (and corresponding implementation) here since - * Cxx compilation in BUCK has a limitation: source-code producing genrule()s - * must have a single output. More files => more genrule()s => slower builds. - */ -#import "FBReactNativeSpec.h" - - - -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_isReduceMotionEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "isReduceMotionEnabled", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_isTouchExplorationEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "isTouchExplorationEnabled", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_setAccessibilityFocus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAccessibilityFocus", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityInfoSpecJSI_announceForAccessibility(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "announceForAccessibility", "(Ljava/lang/String;)V", args, count); - } - - - NativeAccessibilityInfoSpecJSI::NativeAccessibilityInfoSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["isReduceMotionEnabled"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_isReduceMotionEnabled}; - - - methodMap_["isTouchExplorationEnabled"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_isTouchExplorationEnabled}; - - - methodMap_["setAccessibilityFocus"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_setAccessibilityFocus}; - - - methodMap_["announceForAccessibility"] = MethodMetadata {1, __hostFunction_NativeAccessibilityInfoSpecJSI_announceForAccessibility}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentBoldTextState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentBoldTextState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentGrayscaleState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentGrayscaleState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentInvertColorsState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentInvertColorsState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceMotionState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentReduceMotionState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceTransparencyState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentReduceTransparencyState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentVoiceOverState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentVoiceOverState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityContentSizeMultipliers(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAccessibilityContentSizeMultipliers", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityFocus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAccessibilityFocus", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAccessibilityManagerSpecJSI_announceForAccessibility(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "announceForAccessibility", "(Ljava/lang/String;)V", args, count); - } - - - NativeAccessibilityManagerSpecJSI::NativeAccessibilityManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getCurrentBoldTextState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentBoldTextState}; - - - methodMap_["getCurrentGrayscaleState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentGrayscaleState}; - - - methodMap_["getCurrentInvertColorsState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentInvertColorsState}; - - - methodMap_["getCurrentReduceMotionState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceMotionState}; - - - methodMap_["getCurrentReduceTransparencyState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentReduceTransparencyState}; - - - methodMap_["getCurrentVoiceOverState"] = MethodMetadata {2, __hostFunction_NativeAccessibilityManagerSpecJSI_getCurrentVoiceOverState}; - - - methodMap_["setAccessibilityContentSizeMultipliers"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityContentSizeMultipliers}; - - - methodMap_["setAccessibilityFocus"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_setAccessibilityFocus}; - - - methodMap_["announceForAccessibility"] = MethodMetadata {1, __hostFunction_NativeAccessibilityManagerSpecJSI_announceForAccessibility}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeActionSheetManagerSpecJSI_showActionSheetWithOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showActionSheetWithOptions", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeActionSheetManagerSpecJSI_showShareActionSheetWithOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showShareActionSheetWithOptions", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeActionSheetManagerSpecJSI::NativeActionSheetManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["showActionSheetWithOptions"] = MethodMetadata {2, __hostFunction_NativeActionSheetManagerSpecJSI_showActionSheetWithOptions}; - - - methodMap_["showShareActionSheetWithOptions"] = MethodMetadata {3, __hostFunction_NativeActionSheetManagerSpecJSI_showShareActionSheetWithOptions}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAlertManagerSpecJSI_alertWithArgs(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "alertWithArgs", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeAlertManagerSpecJSI::NativeAlertManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["alertWithArgs"] = MethodMetadata {2, __hostFunction_NativeAlertManagerSpecJSI_alertWithArgs}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startOperationBatch", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_finishOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "finishOperationBatch", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_createAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "createAnimatedNode", "(DLcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getValue", "(DLcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startListeningToAnimatedNodeValue", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_stopListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "stopListeningToAnimatedNodeValue", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "connectAnimatedNodes", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "disconnectAnimatedNodes", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startAnimatingNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startAnimatingNode", "(DDLcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_stopAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "stopAnimation", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAnimatedNodeValue", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAnimatedNodeOffset", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_flattenAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "flattenAnimatedNodeOffset", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_extractAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "extractAnimatedNodeOffset", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodeToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "connectAnimatedNodeToView", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodeFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "disconnectAnimatedNodeFromView", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_restoreDefaultValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "restoreDefaultValues", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_dropAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dropAnimatedNode", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_addAnimatedEventToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addAnimatedEventToView", "(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_removeAnimatedEventFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeAnimatedEventFromView", "(DLjava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeAnimatedModuleSpecJSI::NativeAnimatedModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["startOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedModuleSpecJSI_startOperationBatch}; - - - methodMap_["finishOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedModuleSpecJSI_finishOperationBatch}; - - - methodMap_["createAnimatedNode"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_createAnimatedNode}; - - - methodMap_["getValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_getValue}; - - - methodMap_["startListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue}; - - - methodMap_["stopListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_stopListeningToAnimatedNodeValue}; - - - methodMap_["connectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodes}; - - - methodMap_["disconnectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodes}; - - - methodMap_["startAnimatingNode"] = MethodMetadata {4, __hostFunction_NativeAnimatedModuleSpecJSI_startAnimatingNode}; - - - methodMap_["stopAnimation"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_stopAnimation}; - - - methodMap_["setAnimatedNodeValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeValue}; - - - methodMap_["setAnimatedNodeOffset"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_setAnimatedNodeOffset}; - - - methodMap_["flattenAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_flattenAnimatedNodeOffset}; - - - methodMap_["extractAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_extractAnimatedNodeOffset}; - - - methodMap_["connectAnimatedNodeToView"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_connectAnimatedNodeToView}; - - - methodMap_["disconnectAnimatedNodeFromView"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_disconnectAnimatedNodeFromView}; - - - methodMap_["restoreDefaultValues"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_restoreDefaultValues}; - - - methodMap_["dropAnimatedNode"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_dropAnimatedNode}; - - - methodMap_["addAnimatedEventToView"] = MethodMetadata {3, __hostFunction_NativeAnimatedModuleSpecJSI_addAnimatedEventToView}; - - - methodMap_["removeAnimatedEventFromView"] = MethodMetadata {3, __hostFunction_NativeAnimatedModuleSpecJSI_removeAnimatedEventFromView}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startOperationBatch", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_finishOperationBatch(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "finishOperationBatch", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_createAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "createAnimatedNode", "(DLcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getValue", "(DLcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startListeningToAnimatedNodeValue", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "stopListeningToAnimatedNodeValue", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "connectAnimatedNodes", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "disconnectAnimatedNodes", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_startAnimatingNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startAnimatingNode", "(DDLcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "stopAnimation", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAnimatedNodeValue", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setAnimatedNodeOffset", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_flattenAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "flattenAnimatedNodeOffset", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_extractAnimatedNodeOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "extractAnimatedNodeOffset", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodeToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "connectAnimatedNodeToView", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodeFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "disconnectAnimatedNodeFromView", "(DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_restoreDefaultValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "restoreDefaultValues", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_dropAnimatedNode(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dropAnimatedNode", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_addAnimatedEventToView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addAnimatedEventToView", "(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeAnimatedEventFromView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeAnimatedEventFromView", "(DLjava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeAnimatedTurboModuleSpecJSI::NativeAnimatedTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["startOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startOperationBatch}; - - - methodMap_["finishOperationBatch"] = MethodMetadata {0, __hostFunction_NativeAnimatedTurboModuleSpecJSI_finishOperationBatch}; - - - methodMap_["createAnimatedNode"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_createAnimatedNode}; - - - methodMap_["getValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_getValue}; - - - methodMap_["startListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startListeningToAnimatedNodeValue}; - - - methodMap_["stopListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopListeningToAnimatedNodeValue}; - - - methodMap_["connectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodes}; - - - methodMap_["disconnectAnimatedNodes"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodes}; - - - methodMap_["startAnimatingNode"] = MethodMetadata {4, __hostFunction_NativeAnimatedTurboModuleSpecJSI_startAnimatingNode}; - - - methodMap_["stopAnimation"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_stopAnimation}; - - - methodMap_["setAnimatedNodeValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeValue}; - - - methodMap_["setAnimatedNodeOffset"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_setAnimatedNodeOffset}; - - - methodMap_["flattenAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_flattenAnimatedNodeOffset}; - - - methodMap_["extractAnimatedNodeOffset"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_extractAnimatedNodeOffset}; - - - methodMap_["connectAnimatedNodeToView"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_connectAnimatedNodeToView}; - - - methodMap_["disconnectAnimatedNodeFromView"] = MethodMetadata {2, __hostFunction_NativeAnimatedTurboModuleSpecJSI_disconnectAnimatedNodeFromView}; - - - methodMap_["restoreDefaultValues"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_restoreDefaultValues}; - - - methodMap_["dropAnimatedNode"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_dropAnimatedNode}; - - - methodMap_["addAnimatedEventToView"] = MethodMetadata {3, __hostFunction_NativeAnimatedTurboModuleSpecJSI_addAnimatedEventToView}; - - - methodMap_["removeAnimatedEventFromView"] = MethodMetadata {3, __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeAnimatedEventFromView}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAnimationsDebugModuleSpecJSI_startRecordingFps(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startRecordingFps", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAnimationsDebugModuleSpecJSI_stopRecordingFps(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "stopRecordingFps", "(D)V", args, count); - } - - - NativeAnimationsDebugModuleSpecJSI::NativeAnimationsDebugModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["startRecordingFps"] = MethodMetadata {0, __hostFunction_NativeAnimationsDebugModuleSpecJSI_startRecordingFps}; - - - methodMap_["stopRecordingFps"] = MethodMetadata {1, __hostFunction_NativeAnimationsDebugModuleSpecJSI_stopRecordingFps}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_getCurrentAppState(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getCurrentAppState", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppStateSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeAppStateSpecJSI::NativeAppStateSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getCurrentAppState"] = MethodMetadata {2, __hostFunction_NativeAppStateSpecJSI_getCurrentAppState}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppStateSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppStateSpecJSI_removeListeners}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeAppStateSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_getColorScheme(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, StringKind, "getColorScheme", "()Ljava/lang/String;", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAppearanceSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeAppearanceSpecJSI::NativeAppearanceSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getColorScheme"] = MethodMetadata {0, __hostFunction_NativeAppearanceSpecJSI_getColorScheme}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppearanceSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppearanceSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiGet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "multiGet", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiSet(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "multiSet", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiMerge(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "multiMerge", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_multiRemove(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "multiRemove", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_clear(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "clear", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getAllKeys", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeAsyncStorageSpecJSI::NativeAsyncStorageSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["multiGet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiGet}; - - - methodMap_["multiSet"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiSet}; - - - methodMap_["multiMerge"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiMerge}; - - - methodMap_["multiRemove"] = MethodMetadata {2, __hostFunction_NativeAsyncStorageSpecJSI_multiRemove}; - - - methodMap_["clear"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_clear}; - - - methodMap_["getAllKeys"] = MethodMetadata {1, __hostFunction_NativeAsyncStorageSpecJSI_getAllKeys}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_addNetworkingHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addNetworkingHandler", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_addWebSocketHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addWebSocketHandler", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_removeWebSocketHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeWebSocketHandler", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_sendOverSocket(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "sendOverSocket", "(Lcom/facebook/react/bridge/ReadableMap;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_createFromParts(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "createFromParts", "(Lcom/facebook/react/bridge/ReadableArray;Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_release(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "release", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBlobModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeBlobModuleSpecJSI::NativeBlobModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["addNetworkingHandler"] = MethodMetadata {0, __hostFunction_NativeBlobModuleSpecJSI_addNetworkingHandler}; - - - methodMap_["addWebSocketHandler"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_addWebSocketHandler}; - - - methodMap_["removeWebSocketHandler"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_removeWebSocketHandler}; - - - methodMap_["sendOverSocket"] = MethodMetadata {2, __hostFunction_NativeBlobModuleSpecJSI_sendOverSocket}; - - - methodMap_["createFromParts"] = MethodMetadata {2, __hostFunction_NativeBlobModuleSpecJSI_createFromParts}; - - - methodMap_["release"] = MethodMetadata {1, __hostFunction_NativeBlobModuleSpecJSI_release}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeBlobModuleSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_startReportAProblemFlow(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "startReportAProblemFlow", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_setExtraData(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setExtraData", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeBugReportingSpecJSI_setCategoryID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setCategoryID", "(Ljava/lang/String;)V", args, count); - } - - - NativeBugReportingSpecJSI::NativeBugReportingSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["startReportAProblemFlow"] = MethodMetadata {0, __hostFunction_NativeBugReportingSpecJSI_startReportAProblemFlow}; - - - methodMap_["setExtraData"] = MethodMetadata {2, __hostFunction_NativeBugReportingSpecJSI_setExtraData}; - - - methodMap_["setCategoryID"] = MethodMetadata {1, __hostFunction_NativeBugReportingSpecJSI_setCategoryID}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeClipboardSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getString", "(Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeClipboardSpecJSI_setString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setString", "(Ljava/lang/String;)V", args, count); - } - - - NativeClipboardSpecJSI::NativeClipboardSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getString"] = MethodMetadata {0, __hostFunction_NativeClipboardSpecJSI_getString}; - - - methodMap_["setString"] = MethodMetadata {1, __hostFunction_NativeClipboardSpecJSI_setString}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDatePickerAndroidSpecJSI_open(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "open", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeDatePickerAndroidSpecJSI::NativeDatePickerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["open"] = MethodMetadata {1, __hostFunction_NativeDatePickerAndroidSpecJSI_open}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevLoadingViewSpecJSI_showMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showMessage", "(Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevLoadingViewSpecJSI_hide(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "hide", "()V", args, count); - } - - - NativeDevLoadingViewSpecJSI::NativeDevLoadingViewSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["showMessage"] = MethodMetadata {3, __hostFunction_NativeDevLoadingViewSpecJSI_showMessage}; - - - methodMap_["hide"] = MethodMetadata {0, __hostFunction_NativeDevLoadingViewSpecJSI_hide}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "show", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_reload(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reload", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_debugRemotely(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "debugRemotely", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_setProfilingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setProfilingEnabled", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevMenuSpecJSI_setHotLoadingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setHotLoadingEnabled", "(Z)V", args, count); - } - - - NativeDevMenuSpecJSI::NativeDevMenuSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["show"] = MethodMetadata {0, __hostFunction_NativeDevMenuSpecJSI_show}; - - - methodMap_["reload"] = MethodMetadata {0, __hostFunction_NativeDevMenuSpecJSI_reload}; - - - methodMap_["debugRemotely"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_debugRemotely}; - - - methodMap_["setProfilingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_setProfilingEnabled}; - - - methodMap_["setHotLoadingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevMenuSpecJSI_setHotLoadingEnabled}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_reload(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reload", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_reloadWithReason(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reloadWithReason", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_onFastRefresh(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "onFastRefresh", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setHotLoadingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setHotLoadingEnabled", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setIsDebuggingRemotely(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setIsDebuggingRemotely", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setProfilingEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setProfilingEnabled", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_toggleElementInspector(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "toggleElementInspector", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_addMenuItem(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addMenuItem", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDevSettingsSpecJSI_setIsShakeToShowDevMenuEnabled(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setIsShakeToShowDevMenuEnabled", "(Z)V", args, count); - } - - - NativeDevSettingsSpecJSI::NativeDevSettingsSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["reload"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_reload}; - - - methodMap_["reloadWithReason"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_reloadWithReason}; - - - methodMap_["onFastRefresh"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_onFastRefresh}; - - - methodMap_["setHotLoadingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setHotLoadingEnabled}; - - - methodMap_["setIsDebuggingRemotely"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setIsDebuggingRemotely}; - - - methodMap_["setProfilingEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setProfilingEnabled}; - - - methodMap_["toggleElementInspector"] = MethodMetadata {0, __hostFunction_NativeDevSettingsSpecJSI_toggleElementInspector}; - - - methodMap_["addMenuItem"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_addMenuItem}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_removeListeners}; - - - methodMap_["setIsShakeToShowDevMenuEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsSpecJSI_setIsShakeToShowDevMenuEnabled}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDevSplitBundleLoaderSpecJSI_loadBundle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "loadBundle", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeDevSplitBundleLoaderSpecJSI::NativeDevSplitBundleLoaderSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["loadBundle"] = MethodMetadata {1, __hostFunction_NativeDevSplitBundleLoaderSpecJSI_loadBundle}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDeviceEventManagerSpecJSI_invokeDefaultBackPressHandler(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "invokeDefaultBackPressHandler", "()V", args, count); - } - - - NativeDeviceEventManagerSpecJSI::NativeDeviceEventManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["invokeDefaultBackPressHandler"] = MethodMetadata {0, __hostFunction_NativeDeviceEventManagerSpecJSI_invokeDefaultBackPressHandler}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDeviceInfoSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeDeviceInfoSpecJSI::NativeDeviceInfoSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDeviceInfoSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeDialogManagerAndroidSpecJSI_showAlert(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showAlert", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeDialogManagerAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeDialogManagerAndroidSpecJSI::NativeDialogManagerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["showAlert"] = MethodMetadata {3, __hostFunction_NativeDialogManagerAndroidSpecJSI_showAlert}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDialogManagerAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reportFatalException", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reportSoftException", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "reportException", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "updateExceptionMessage", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dismissRedbox", "()V", args, count); - } - - - NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["reportFatalException"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; - - - methodMap_["reportSoftException"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; - - - methodMap_["reportException"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; - - - methodMap_["updateExceptionMessage"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; - - - methodMap_["dismissRedbox"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeFileReaderModuleSpecJSI_readAsDataURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "readAsDataURL", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFileReaderModuleSpecJSI_readAsText(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "readAsText", "(Lcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeFileReaderModuleSpecJSI::NativeFileReaderModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["readAsDataURL"] = MethodMetadata {1, __hostFunction_NativeFileReaderModuleSpecJSI_readAsDataURL}; - - - methodMap_["readAsText"] = MethodMetadata {2, __hostFunction_NativeFileReaderModuleSpecJSI_readAsText}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_setGlobalOptions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setGlobalOptions", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_setContext(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setContext", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_beginScroll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "beginScroll", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeFrameRateLoggerSpecJSI_endScroll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "endScroll", "()V", args, count); - } - - - NativeFrameRateLoggerSpecJSI::NativeFrameRateLoggerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["setGlobalOptions"] = MethodMetadata {1, __hostFunction_NativeFrameRateLoggerSpecJSI_setGlobalOptions}; - - - methodMap_["setContext"] = MethodMetadata {1, __hostFunction_NativeFrameRateLoggerSpecJSI_setContext}; - - - methodMap_["beginScroll"] = MethodMetadata {0, __hostFunction_NativeFrameRateLoggerSpecJSI_beginScroll}; - - - methodMap_["endScroll"] = MethodMetadata {0, __hostFunction_NativeFrameRateLoggerSpecJSI_endScroll}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskFinished(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "notifyTaskFinished", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskRetry(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "notifyTaskRetry", "(DLcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeHeadlessJsTaskSupportSpecJSI::NativeHeadlessJsTaskSupportSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["notifyTaskFinished"] = MethodMetadata {1, __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskFinished}; - - - methodMap_["notifyTaskRetry"] = MethodMetadata {1, __hostFunction_NativeHeadlessJsTaskSupportSpecJSI_notifyTaskRetry}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_allowRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "allowRTL", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_forceRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "forceRTL", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_swapLeftAndRightInRTL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "swapLeftAndRightInRTL", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeI18nManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeI18nManagerSpecJSI::NativeI18nManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["allowRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_allowRTL}; - - - methodMap_["forceRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_forceRTL}; - - - methodMap_["swapLeftAndRightInRTL"] = MethodMetadata {1, __hostFunction_NativeI18nManagerSpecJSI_swapLeftAndRightInRTL}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeI18nManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageEditorSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "cropImage", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeImageEditorSpecJSI::NativeImageEditorSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["cropImage"] = MethodMetadata {4, __hostFunction_NativeImageEditorSpecJSI_cropImage}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "abortRequest", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_getSize(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getSize", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_getSizeWithHeaders(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getSizeWithHeaders", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_prefetchImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "prefetchImage", "(Ljava/lang/String;DLcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderAndroidSpecJSI_queryCache(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "queryCache", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeImageLoaderAndroidSpecJSI::NativeImageLoaderAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_abortRequest}; - - - methodMap_["getSize"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_getSize}; - - - methodMap_["getSizeWithHeaders"] = MethodMetadata {2, __hostFunction_NativeImageLoaderAndroidSpecJSI_getSizeWithHeaders}; - - - methodMap_["prefetchImage"] = MethodMetadata {2, __hostFunction_NativeImageLoaderAndroidSpecJSI_prefetchImage}; - - - methodMap_["queryCache"] = MethodMetadata {1, __hostFunction_NativeImageLoaderAndroidSpecJSI_queryCache}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_getSize(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getSize", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_getSizeWithHeaders(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getSizeWithHeaders", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_prefetchImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "prefetchImage", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageLoaderIOSSpecJSI_queryCache(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "queryCache", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeImageLoaderIOSSpecJSI::NativeImageLoaderIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getSize"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_getSize}; - - - methodMap_["getSizeWithHeaders"] = MethodMetadata {2, __hostFunction_NativeImageLoaderIOSSpecJSI_getSizeWithHeaders}; - - - methodMap_["prefetchImage"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_prefetchImage}; - - - methodMap_["queryCache"] = MethodMetadata {1, __hostFunction_NativeImageLoaderIOSSpecJSI_queryCache}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_canRecordVideos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "canRecordVideos", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_canUseCamera(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "canUseCamera", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "openCameraDialog", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openSelectDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "openSelectDialog", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_clearAllPendingVideos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "clearAllPendingVideos", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_removePendingVideo(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removePendingVideo", "(Ljava/lang/String;)V", args, count); - } - - - NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["canRecordVideos"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_canRecordVideos}; - - - methodMap_["canUseCamera"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_canUseCamera}; - - - methodMap_["openCameraDialog"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; - - - methodMap_["openSelectDialog"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openSelectDialog}; - - - methodMap_["clearAllPendingVideos"] = MethodMetadata {0, __hostFunction_NativeImagePickerIOSSpecJSI_clearAllPendingVideos}; - - - methodMap_["removePendingVideo"] = MethodMetadata {1, __hostFunction_NativeImagePickerIOSSpecJSI_removePendingVideo}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getBase64ForTag", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "hasImageForTag", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeImageForTag", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addImageFromBase64", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeImageStoreSpecJSI::NativeImageStoreSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag}; - - - methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreSpecJSI_hasImageForTag}; - - - methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreSpecJSI_removeImageForTag}; - - - methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSCHeapCaptureSpecJSI_captureComplete(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "captureComplete", "(Ljava/lang/String;Ljava/lang/String;)V", args, count); - } - - - NativeJSCHeapCaptureSpecJSI::NativeJSCHeapCaptureSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["captureComplete"] = MethodMetadata {2, __hostFunction_NativeJSCHeapCaptureSpecJSI_captureComplete}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSCSamplingProfilerSpecJSI_operationComplete(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "operationComplete", "(DLjava/lang/String;Ljava/lang/String;)V", args, count); - } - - - NativeJSCSamplingProfilerSpecJSI::NativeJSCSamplingProfilerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["operationComplete"] = MethodMetadata {3, __hostFunction_NativeJSCSamplingProfilerSpecJSI_operationComplete}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_onSuccess(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "onSuccess", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_onFailure(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "onFailure", "(DLjava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeJSDevSupportSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeJSDevSupportSpecJSI::NativeJSDevSupportSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["onSuccess"] = MethodMetadata {1, __hostFunction_NativeJSDevSupportSpecJSI_onSuccess}; - - - methodMap_["onFailure"] = MethodMetadata {2, __hostFunction_NativeJSDevSupportSpecJSI_onFailure}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeJSDevSupportSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeKeyboardObserverSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeKeyboardObserverSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeKeyboardObserverSpecJSI::NativeKeyboardObserverSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeKeyboardObserverSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeKeyboardObserverSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_getInitialURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getInitialURL", "(Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_canOpenURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "canOpenURL", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_openURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "openURL", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_openSettings(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "openSettings", "(Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_sendIntent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "sendIntent", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLinkingSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeLinkingSpecJSI::NativeLinkingSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getInitialURL"] = MethodMetadata {0, __hostFunction_NativeLinkingSpecJSI_getInitialURL}; - - - methodMap_["canOpenURL"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_canOpenURL}; - - - methodMap_["openURL"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_openURL}; - - - methodMap_["openSettings"] = MethodMetadata {0, __hostFunction_NativeLinkingSpecJSI_openSettings}; - - - methodMap_["sendIntent"] = MethodMetadata {2, __hostFunction_NativeLinkingSpecJSI_sendIntent}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeLinkingSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "show", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_hide(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "hide", "()V", args, count); - } - - - NativeLogBoxSpecJSI::NativeLogBoxSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["show"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_show}; - - - methodMap_["hide"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_hide}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeModalManagerSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeModalManagerSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeModalManagerSpecJSI::NativeModalManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeModalManagerSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeModalManagerSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_sendRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "sendRequest", "(Ljava/lang/String;Ljava/lang/String;DLcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;ZDZ)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "abortRequest", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_clearCookies(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "clearCookies", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingAndroidSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeNetworkingAndroidSpecJSI::NativeNetworkingAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["sendRequest"] = MethodMetadata {9, __hostFunction_NativeNetworkingAndroidSpecJSI_sendRequest}; - - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_abortRequest}; - - - methodMap_["clearCookies"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_clearCookies}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeNetworkingAndroidSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_sendRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "sendRequest", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_abortRequest(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "abortRequest", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_clearCookies(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "clearCookies", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeNetworkingIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeNetworkingIOSSpecJSI::NativeNetworkingIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["sendRequest"] = MethodMetadata {2, __hostFunction_NativeNetworkingIOSSpecJSI_sendRequest}; - - - methodMap_["abortRequest"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_abortRequest}; - - - methodMap_["clearCookies"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_clearCookies}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeNetworkingIOSSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_checkPermission(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "checkPermission", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_requestPermission(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "requestPermission", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_shouldShowRequestPermissionRationale(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "shouldShowRequestPermissionRationale", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePermissionsAndroidSpecJSI_requestMultiplePermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "requestMultiplePermissions", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativePermissionsAndroidSpecJSI::NativePermissionsAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["checkPermission"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_checkPermission}; - - - methodMap_["requestPermission"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_requestPermission}; - - - methodMap_["shouldShowRequestPermissionRationale"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_shouldShowRequestPermissionRationale}; - - - methodMap_["requestMultiplePermissions"] = MethodMetadata {1, __hostFunction_NativePermissionsAndroidSpecJSI_requestMultiplePermissions}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsAndroidSpecJSI_getAndroidID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, StringKind, "getAndroidID", "()Ljava/lang/String;", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativePlatformConstantsAndroidSpecJSI::NativePlatformConstantsAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getAndroidID"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsAndroidSpecJSI_getAndroidID}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePlatformConstantsIOSSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativePlatformConstantsIOSSpecJSI::NativePlatformConstantsIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativePlatformConstantsIOSSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_onFinishRemoteNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "onFinishRemoteNotification", "(Ljava/lang/String;Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_setApplicationIconBadgeNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setApplicationIconBadgeNumber", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getApplicationIconBadgeNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getApplicationIconBadgeNumber", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_requestPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "requestPermissions", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_abandonPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "abandonPermissions", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_checkPermissions(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "checkPermissions", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_presentLocalNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "presentLocalNotification", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_scheduleLocalNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "scheduleLocalNotification", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelAllLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "cancelAllLocalNotifications", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "cancelLocalNotifications", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getInitialNotification(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "getInitialNotification", "(Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getScheduledLocalNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getScheduledLocalNotifications", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeAllDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeAllDeliveredNotifications", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeDeliveredNotifications", "(Lcom/facebook/react/bridge/ReadableArray;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_getDeliveredNotifications(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getDeliveredNotifications", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativePushNotificationManagerIOSSpecJSI::NativePushNotificationManagerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["onFinishRemoteNotification"] = MethodMetadata {2, __hostFunction_NativePushNotificationManagerIOSSpecJSI_onFinishRemoteNotification}; - - - methodMap_["setApplicationIconBadgeNumber"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_setApplicationIconBadgeNumber}; - - - methodMap_["getApplicationIconBadgeNumber"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getApplicationIconBadgeNumber}; - - - methodMap_["requestPermissions"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_requestPermissions}; - - - methodMap_["abandonPermissions"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_abandonPermissions}; - - - methodMap_["checkPermissions"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_checkPermissions}; - - - methodMap_["presentLocalNotification"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_presentLocalNotification}; - - - methodMap_["scheduleLocalNotification"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_scheduleLocalNotification}; - - - methodMap_["cancelAllLocalNotifications"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelAllLocalNotifications}; - - - methodMap_["cancelLocalNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_cancelLocalNotifications}; - - - methodMap_["getInitialNotification"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getInitialNotification}; - - - methodMap_["getScheduledLocalNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getScheduledLocalNotifications}; - - - methodMap_["removeAllDeliveredNotifications"] = MethodMetadata {0, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeAllDeliveredNotifications}; - - - methodMap_["removeDeliveredNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeDeliveredNotifications}; - - - methodMap_["getDeliveredNotifications"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_getDeliveredNotifications}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativePushNotificationManagerIOSSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeRedBoxSpecJSI_setExtraData(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setExtraData", "(Lcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeRedBoxSpecJSI_dismiss(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dismiss", "()V", args, count); - } - - - NativeRedBoxSpecJSI::NativeRedBoxSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["setExtraData"] = MethodMetadata {2, __hostFunction_NativeRedBoxSpecJSI_setExtraData}; - - - methodMap_["dismiss"] = MethodMetadata {0, __hostFunction_NativeRedBoxSpecJSI_dismiss}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSegmentFetcherSpecJSI_fetchSegment(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "fetchSegment", "(DLcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSegmentFetcherSpecJSI_getSegment(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getSegment", "(DLcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - - NativeSegmentFetcherSpecJSI::NativeSegmentFetcherSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["fetchSegment"] = MethodMetadata {3, __hostFunction_NativeSegmentFetcherSpecJSI_fetchSegment}; - - - methodMap_["getSegment"] = MethodMetadata {3, __hostFunction_NativeSegmentFetcherSpecJSI_getSegment}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_setValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setValues", "(Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_deleteValues(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "deleteValues", "(Lcom/facebook/react/bridge/ReadableArray;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeSettingsManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeSettingsManagerSpecJSI::NativeSettingsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["setValues"] = MethodMetadata {1, __hostFunction_NativeSettingsManagerSpecJSI_setValues}; - - - methodMap_["deleteValues"] = MethodMetadata {1, __hostFunction_NativeSettingsManagerSpecJSI_deleteValues}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeSettingsManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeShareModuleSpecJSI_share(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, PromiseKind, "share", "(Lcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count); - } - - - NativeShareModuleSpecJSI::NativeShareModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["share"] = MethodMetadata {2, __hostFunction_NativeShareModuleSpecJSI_share}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSoundManagerSpecJSI_playTouchSound(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "playTouchSound", "()V", args, count); - } - - - NativeSoundManagerSpecJSI::NativeSoundManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["playTouchSound"] = MethodMetadata {0, __hostFunction_NativeSoundManagerSpecJSI_playTouchSound}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeSourceCodeSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeSourceCodeSpecJSI::NativeSourceCodeSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeSourceCodeSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setColor(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setColor", "(DZ)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setTranslucent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setTranslucent", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setStyle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setStyle", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setHidden(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setHidden", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeStatusBarManagerAndroidSpecJSI::NativeStatusBarManagerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["setColor"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setColor}; - - - methodMap_["setTranslucent"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setTranslucent}; - - - methodMap_["setStyle"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setStyle}; - - - methodMap_["setHidden"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_setHidden}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeStatusBarManagerAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_getHeight(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getHeight", "(Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setNetworkActivityIndicatorVisible(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setNetworkActivityIndicatorVisible", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setStyle(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setStyle", "(Ljava/lang/String;Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_setHidden(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setHidden", "(ZLjava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeStatusBarManagerIOSSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeStatusBarManagerIOSSpecJSI::NativeStatusBarManagerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getHeight"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_getHeight}; - - - methodMap_["setNetworkActivityIndicatorVisible"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setNetworkActivityIndicatorVisible}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeStatusBarManagerIOSSpecJSI_removeListeners}; - - - methodMap_["setStyle"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setStyle}; - - - methodMap_["setHidden"] = MethodMetadata {2, __hostFunction_NativeStatusBarManagerIOSSpecJSI_setHidden}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeStatusBarManagerIOSSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeTVNavigationEventEmitterSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTVNavigationEventEmitterSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeTVNavigationEventEmitterSpecJSI::NativeTVNavigationEventEmitterSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeTVNavigationEventEmitterSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeTVNavigationEventEmitterSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_createTimer(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "createTimer", "(DDDZ)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_deleteTimer(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "deleteTimer", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeTimingSpecJSI_setSendIdleEvents(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setSendIdleEvents", "(Z)V", args, count); - } - - - NativeTimingSpecJSI::NativeTimingSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["createTimer"] = MethodMetadata {4, __hostFunction_NativeTimingSpecJSI_createTimer}; - - - methodMap_["deleteTimer"] = MethodMetadata {1, __hostFunction_NativeTimingSpecJSI_deleteTimer}; - - - methodMap_["setSendIdleEvents"] = MethodMetadata {1, __hostFunction_NativeTimingSpecJSI_setSendIdleEvents}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "show", "(Ljava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_showWithGravity(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showWithGravity", "(Ljava/lang/String;DD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_showWithGravityAndOffset(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showWithGravityAndOffset", "(Ljava/lang/String;DDDD)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeToastAndroidSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeToastAndroidSpecJSI::NativeToastAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["show"] = MethodMetadata {2, __hostFunction_NativeToastAndroidSpecJSI_show}; - - - methodMap_["showWithGravity"] = MethodMetadata {3, __hostFunction_NativeToastAndroidSpecJSI_showWithGravity}; - - - methodMap_["showWithGravityAndOffset"] = MethodMetadata {5, __hostFunction_NativeToastAndroidSpecJSI_showWithGravityAndOffset}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeToastAndroidSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getConstantsForViewManager(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstantsForViewManager", "(Ljava/lang/String;)Lcom/facebook/react/bridge/WritableMap;", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getDefaultEventTypes(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ArrayKind, "getDefaultEventTypes", "()Lcom/facebook/react/bridge/WritableArray;", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_lazilyLoadView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "lazilyLoadView", "(Ljava/lang/String;)Lcom/facebook/react/bridge/WritableMap;", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_createView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "createView", "(Ljava/lang/Double;Ljava/lang/String;DLcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_updateView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "updateView", "(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_focus(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "focus", "(Ljava/lang/Double;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_blur(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "blur", "(Ljava/lang/Double;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_findSubviewIn(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "findSubviewIn", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_dispatchViewManagerCommand(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dispatchViewManagerCommand", "(Ljava/lang/Double;DLcom/facebook/react/bridge/ReadableArray;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measure(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "measure", "(Ljava/lang/Double;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureInWindow(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "measureInWindow", "(Ljava/lang/Double;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_viewIsDescendantOf(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "viewIsDescendantOf", "(Ljava/lang/Double;Ljava/lang/Double;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureLayout(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "measureLayout", "(Ljava/lang/Double;Ljava/lang/Double;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_measureLayoutRelativeToParent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "measureLayoutRelativeToParent", "(Ljava/lang/Double;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setJSResponder(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setJSResponder", "(Ljava/lang/Double;Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_clearJSResponder(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "clearJSResponder", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_configureNextLayoutAnimation(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "configureNextLayoutAnimation", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_removeSubviewsFromContainerWithID(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeSubviewsFromContainerWithID", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_replaceExistingNonRootView(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "replaceExistingNonRootView", "(Ljava/lang/Double;Ljava/lang/Double;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setChildren(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setChildren", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableArray;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_manageChildren(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "manageChildren", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableArray;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_setLayoutAnimationEnabledExperimental(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "setLayoutAnimationEnabledExperimental", "(Z)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_sendAccessibilityEvent(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "sendAccessibilityEvent", "(Ljava/lang/Double;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_showPopupMenu(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "showPopupMenu", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_dismissPopupMenu(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "dismissPopupMenu", "()V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeUIManagerSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); - } - - - NativeUIManagerSpecJSI::NativeUIManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["getConstantsForViewManager"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_getConstantsForViewManager}; - - - methodMap_["getDefaultEventTypes"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_getDefaultEventTypes}; - - - methodMap_["lazilyLoadView"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_lazilyLoadView}; - - - methodMap_["createView"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_createView}; - - - methodMap_["updateView"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_updateView}; - - - methodMap_["focus"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_focus}; - - - methodMap_["blur"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_blur}; - - - methodMap_["findSubviewIn"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_findSubviewIn}; - - - methodMap_["dispatchViewManagerCommand"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_dispatchViewManagerCommand}; - - - methodMap_["measure"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_measure}; - - - methodMap_["measureInWindow"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_measureInWindow}; - - - methodMap_["viewIsDescendantOf"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_viewIsDescendantOf}; - - - methodMap_["measureLayout"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_measureLayout}; - - - methodMap_["measureLayoutRelativeToParent"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_measureLayoutRelativeToParent}; - - - methodMap_["setJSResponder"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_setJSResponder}; - - - methodMap_["clearJSResponder"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_clearJSResponder}; - - - methodMap_["configureNextLayoutAnimation"] = MethodMetadata {3, __hostFunction_NativeUIManagerSpecJSI_configureNextLayoutAnimation}; - - - methodMap_["removeSubviewsFromContainerWithID"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_removeSubviewsFromContainerWithID}; - - - methodMap_["replaceExistingNonRootView"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_replaceExistingNonRootView}; - - - methodMap_["setChildren"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_setChildren}; - - - methodMap_["manageChildren"] = MethodMetadata {6, __hostFunction_NativeUIManagerSpecJSI_manageChildren}; - - - methodMap_["setLayoutAnimationEnabledExperimental"] = MethodMetadata {1, __hostFunction_NativeUIManagerSpecJSI_setLayoutAnimationEnabledExperimental}; - - - methodMap_["sendAccessibilityEvent"] = MethodMetadata {2, __hostFunction_NativeUIManagerSpecJSI_sendAccessibilityEvent}; - - - methodMap_["showPopupMenu"] = MethodMetadata {4, __hostFunction_NativeUIManagerSpecJSI_showPopupMenu}; - - - methodMap_["dismissPopupMenu"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_dismissPopupMenu}; - - - methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeUIManagerSpecJSI_getConstants}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_vibrate(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "vibrate", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_vibrateByPattern(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "vibrateByPattern", "(Lcom/facebook/react/bridge/ReadableArray;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeVibrationSpecJSI_cancel(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "cancel", "()V", args, count); - } - - - NativeVibrationSpecJSI::NativeVibrationSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["vibrate"] = MethodMetadata {1, __hostFunction_NativeVibrationSpecJSI_vibrate}; - - - methodMap_["vibrateByPattern"] = MethodMetadata {2, __hostFunction_NativeVibrationSpecJSI_vibrateByPattern}; - - - methodMap_["cancel"] = MethodMetadata {0, __hostFunction_NativeVibrationSpecJSI_cancel}; - - - - } - - } // namespace react -} // namespace facebook -namespace facebook { - namespace react { - - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_connect(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "connect", "(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/ReadableMap;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_send(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "send", "(Ljava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_sendBinary(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "sendBinary", "(Ljava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_ping(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "ping", "(D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_close(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "close", "(DLjava/lang/String;D)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addListener", "(Ljava/lang/String;)V", args, count); - } - - static facebook::jsi::Value __hostFunction_NativeWebSocketModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeListeners", "(D)V", args, count); - } - - - NativeWebSocketModuleSpecJSI::NativeWebSocketModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_["connect"] = MethodMetadata {4, __hostFunction_NativeWebSocketModuleSpecJSI_connect}; - - - methodMap_["send"] = MethodMetadata {2, __hostFunction_NativeWebSocketModuleSpecJSI_send}; - - - methodMap_["sendBinary"] = MethodMetadata {2, __hostFunction_NativeWebSocketModuleSpecJSI_sendBinary}; - - - methodMap_["ping"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_ping}; - - - methodMap_["close"] = MethodMetadata {3, __hostFunction_NativeWebSocketModuleSpecJSI_close}; - - - methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_addListener}; - - - methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleSpecJSI_removeListeners}; - - - - } - - } // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h deleted file mode 100644 index 940c22e2f62c94..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h +++ /dev/null @@ -1,833 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal genrule from Flow types. - * - * We create an umbrella header (and corresponding implementation) here since - * Cxx compilation in BUCK has a limitation: source-code producing genrule()s - * must have a single output. More files => more genrule()s => slower builds. - */ -#import -#import -#import -#import - - - -namespace facebook { - namespace react { - /** - * C++ class for module 'AccessibilityInfo' - */ - - class JSI_EXPORT NativeAccessibilityInfoSpecJSI : public JavaTurboModule { - public: - NativeAccessibilityInfoSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AccessibilityManager' - */ - - class JSI_EXPORT NativeAccessibilityManagerSpecJSI : public JavaTurboModule { - public: - NativeAccessibilityManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ActionSheetManager' - */ - - class JSI_EXPORT NativeActionSheetManagerSpecJSI : public JavaTurboModule { - public: - NativeActionSheetManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AlertManager' - */ - - class JSI_EXPORT NativeAlertManagerSpecJSI : public JavaTurboModule { - public: - NativeAlertManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AnimatedModule' - */ - - class JSI_EXPORT NativeAnimatedModuleSpecJSI : public JavaTurboModule { - public: - NativeAnimatedModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AnimatedTurboModule' - */ - - class JSI_EXPORT NativeAnimatedTurboModuleSpecJSI : public JavaTurboModule { - public: - NativeAnimatedTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AnimationsDebugModule' - */ - - class JSI_EXPORT NativeAnimationsDebugModuleSpecJSI : public JavaTurboModule { - public: - NativeAnimationsDebugModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AppState' - */ - - class JSI_EXPORT NativeAppStateSpecJSI : public JavaTurboModule { - public: - NativeAppStateSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'Appearance' - */ - - class JSI_EXPORT NativeAppearanceSpecJSI : public JavaTurboModule { - public: - NativeAppearanceSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'AsyncStorage' - */ - - class JSI_EXPORT NativeAsyncStorageSpecJSI : public JavaTurboModule { - public: - NativeAsyncStorageSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'BlobModule' - */ - - class JSI_EXPORT NativeBlobModuleSpecJSI : public JavaTurboModule { - public: - NativeBlobModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'BugReporting' - */ - - class JSI_EXPORT NativeBugReportingSpecJSI : public JavaTurboModule { - public: - NativeBugReportingSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'Clipboard' - */ - - class JSI_EXPORT NativeClipboardSpecJSI : public JavaTurboModule { - public: - NativeClipboardSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DatePickerAndroid' - */ - - class JSI_EXPORT NativeDatePickerAndroidSpecJSI : public JavaTurboModule { - public: - NativeDatePickerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DevLoadingView' - */ - - class JSI_EXPORT NativeDevLoadingViewSpecJSI : public JavaTurboModule { - public: - NativeDevLoadingViewSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DevMenu' - */ - - class JSI_EXPORT NativeDevMenuSpecJSI : public JavaTurboModule { - public: - NativeDevMenuSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DevSettings' - */ - - class JSI_EXPORT NativeDevSettingsSpecJSI : public JavaTurboModule { - public: - NativeDevSettingsSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DevSplitBundleLoader' - */ - - class JSI_EXPORT NativeDevSplitBundleLoaderSpecJSI : public JavaTurboModule { - public: - NativeDevSplitBundleLoaderSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DeviceEventManager' - */ - - class JSI_EXPORT NativeDeviceEventManagerSpecJSI : public JavaTurboModule { - public: - NativeDeviceEventManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DeviceInfo' - */ - - class JSI_EXPORT NativeDeviceInfoSpecJSI : public JavaTurboModule { - public: - NativeDeviceInfoSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'DialogManagerAndroid' - */ - - class JSI_EXPORT NativeDialogManagerAndroidSpecJSI : public JavaTurboModule { - public: - NativeDialogManagerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ExceptionsManager' - */ - - class JSI_EXPORT NativeExceptionsManagerSpecJSI : public JavaTurboModule { - public: - NativeExceptionsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'FileReaderModule' - */ - - class JSI_EXPORT NativeFileReaderModuleSpecJSI : public JavaTurboModule { - public: - NativeFileReaderModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'FrameRateLogger' - */ - - class JSI_EXPORT NativeFrameRateLoggerSpecJSI : public JavaTurboModule { - public: - NativeFrameRateLoggerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'HeadlessJsTaskSupport' - */ - - class JSI_EXPORT NativeHeadlessJsTaskSupportSpecJSI : public JavaTurboModule { - public: - NativeHeadlessJsTaskSupportSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'I18nManager' - */ - - class JSI_EXPORT NativeI18nManagerSpecJSI : public JavaTurboModule { - public: - NativeI18nManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ImageEditor' - */ - - class JSI_EXPORT NativeImageEditorSpecJSI : public JavaTurboModule { - public: - NativeImageEditorSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ImageLoaderAndroid' - */ - - class JSI_EXPORT NativeImageLoaderAndroidSpecJSI : public JavaTurboModule { - public: - NativeImageLoaderAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ImageLoaderIOS' - */ - - class JSI_EXPORT NativeImageLoaderIOSSpecJSI : public JavaTurboModule { - public: - NativeImageLoaderIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ImagePickerIOS' - */ - - class JSI_EXPORT NativeImagePickerIOSSpecJSI : public JavaTurboModule { - public: - NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ImageStore' - */ - - class JSI_EXPORT NativeImageStoreSpecJSI : public JavaTurboModule { - public: - NativeImageStoreSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'JSCHeapCapture' - */ - - class JSI_EXPORT NativeJSCHeapCaptureSpecJSI : public JavaTurboModule { - public: - NativeJSCHeapCaptureSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'JSCSamplingProfiler' - */ - - class JSI_EXPORT NativeJSCSamplingProfilerSpecJSI : public JavaTurboModule { - public: - NativeJSCSamplingProfilerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'JSDevSupport' - */ - - class JSI_EXPORT NativeJSDevSupportSpecJSI : public JavaTurboModule { - public: - NativeJSDevSupportSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'KeyboardObserver' - */ - - class JSI_EXPORT NativeKeyboardObserverSpecJSI : public JavaTurboModule { - public: - NativeKeyboardObserverSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'Linking' - */ - - class JSI_EXPORT NativeLinkingSpecJSI : public JavaTurboModule { - public: - NativeLinkingSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'LogBox' - */ - - class JSI_EXPORT NativeLogBoxSpecJSI : public JavaTurboModule { - public: - NativeLogBoxSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ModalManager' - */ - - class JSI_EXPORT NativeModalManagerSpecJSI : public JavaTurboModule { - public: - NativeModalManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'NetworkingAndroid' - */ - - class JSI_EXPORT NativeNetworkingAndroidSpecJSI : public JavaTurboModule { - public: - NativeNetworkingAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'NetworkingIOS' - */ - - class JSI_EXPORT NativeNetworkingIOSSpecJSI : public JavaTurboModule { - public: - NativeNetworkingIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'PermissionsAndroid' - */ - - class JSI_EXPORT NativePermissionsAndroidSpecJSI : public JavaTurboModule { - public: - NativePermissionsAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'PlatformConstantsAndroid' - */ - - class JSI_EXPORT NativePlatformConstantsAndroidSpecJSI : public JavaTurboModule { - public: - NativePlatformConstantsAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'PlatformConstantsIOS' - */ - - class JSI_EXPORT NativePlatformConstantsIOSSpecJSI : public JavaTurboModule { - public: - NativePlatformConstantsIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'PushNotificationManagerIOS' - */ - - class JSI_EXPORT NativePushNotificationManagerIOSSpecJSI : public JavaTurboModule { - public: - NativePushNotificationManagerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'RedBox' - */ - - class JSI_EXPORT NativeRedBoxSpecJSI : public JavaTurboModule { - public: - NativeRedBoxSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'SegmentFetcher' - */ - - class JSI_EXPORT NativeSegmentFetcherSpecJSI : public JavaTurboModule { - public: - NativeSegmentFetcherSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'SettingsManager' - */ - - class JSI_EXPORT NativeSettingsManagerSpecJSI : public JavaTurboModule { - public: - NativeSettingsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ShareModule' - */ - - class JSI_EXPORT NativeShareModuleSpecJSI : public JavaTurboModule { - public: - NativeShareModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'SoundManager' - */ - - class JSI_EXPORT NativeSoundManagerSpecJSI : public JavaTurboModule { - public: - NativeSoundManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'SourceCode' - */ - - class JSI_EXPORT NativeSourceCodeSpecJSI : public JavaTurboModule { - public: - NativeSourceCodeSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'StatusBarManagerAndroid' - */ - - class JSI_EXPORT NativeStatusBarManagerAndroidSpecJSI : public JavaTurboModule { - public: - NativeStatusBarManagerAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'StatusBarManagerIOS' - */ - - class JSI_EXPORT NativeStatusBarManagerIOSSpecJSI : public JavaTurboModule { - public: - NativeStatusBarManagerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'TVNavigationEventEmitter' - */ - - class JSI_EXPORT NativeTVNavigationEventEmitterSpecJSI : public JavaTurboModule { - public: - NativeTVNavigationEventEmitterSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'Timing' - */ - - class JSI_EXPORT NativeTimingSpecJSI : public JavaTurboModule { - public: - NativeTimingSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'ToastAndroid' - */ - - class JSI_EXPORT NativeToastAndroidSpecJSI : public JavaTurboModule { - public: - NativeToastAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'UIManager' - */ - - class JSI_EXPORT NativeUIManagerSpecJSI : public JavaTurboModule { - public: - NativeUIManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'Vibration' - */ - - class JSI_EXPORT NativeVibrationSpecJSI : public JavaTurboModule { - public: - NativeVibrationSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - -namespace facebook { - namespace react { - /** - * C++ class for module 'WebSocketModule' - */ - - class JSI_EXPORT NativeWebSocketModuleSpecJSI : public JavaTurboModule { - public: - NativeWebSocketModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); - - }; - } // namespace react -} // namespace facebook - - - diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK index 439ae4b4743578..c78901a85f6c1d 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_nat rn_android_library( name = "instrumentation", srcs = ["HermesMemoryDumper.java"], + autoglob = False, visibility = [ "PUBLIC", ], @@ -11,6 +12,7 @@ rn_android_library( rn_android_library( name = "hermes_samplingprofiler", srcs = ["HermesSamplingProfiler.java"], + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = ["PUBLIC"], deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK index 5f42f833dfb309..fca40c1027f765 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/BUCK @@ -6,6 +6,7 @@ rn_android_library( "HermesExecutor.java", "HermesExecutorFactory.java", ], + autoglob = False, visibility = [ "PUBLIC", ], @@ -25,6 +26,7 @@ rn_android_library( srcs = [ "RuntimeConfig.java", ], + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java index bb065be4f42e75..7519f2146faf6d 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java @@ -28,10 +28,7 @@ public class HermesExecutor extends JavaScriptExecutor { } HermesExecutor(@Nullable RuntimeConfig config) { - super( - config == null - ? initHybridDefaultConfig() - : initHybrid(config.heapSizeMB, config.es6Proxy)); + super(config == null ? initHybridDefaultConfig() : initHybrid(config.heapSizeMB)); } @Override @@ -50,5 +47,5 @@ public String getName() { private static native HybridData initHybridDefaultConfig(); - private static native HybridData initHybrid(long heapSizeMB, boolean es6Proxy); + private static native HybridData initHybrid(long heapSizeMB); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp index d6cbef092de08a..56a9f589490f1f 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp @@ -7,7 +7,9 @@ #include <../instrumentation/HermesMemoryDumper.h> #include +#include #include +#include #include #include #include @@ -21,9 +23,14 @@ namespace facebook { namespace react { -static ::hermes::vm::RuntimeConfig makeRuntimeConfig( - jlong heapSizeMB, - bool es6Proxy) { +static void hermesFatalHandler(const std::string &reason) { + LOG(ERROR) << "Hermes Fatal: " << reason << "\n"; + __android_log_assert(nullptr, "Hermes", "%s", reason.c_str()); +} + +static std::once_flag flag; + +static ::hermes::vm::RuntimeConfig makeRuntimeConfig(jlong heapSizeMB) { namespace vm = ::hermes::vm; auto gcConfigBuilder = vm::GCConfig::Builder() @@ -40,7 +47,6 @@ static ::hermes::vm::RuntimeConfig makeRuntimeConfig( return vm::RuntimeConfig::Builder() .withGCConfig(gcConfigBuilder.build()) - .withES6Proxy(es6Proxy) .build(); } @@ -65,14 +71,21 @@ class HermesExecutorHolder jni::alias_ref) { JReactMarker::setLogPerfMarkerIfNeeded(); + std::call_once(flag, []() { + facebook::hermes::HermesRuntime::setFatalHandler(hermesFatalHandler); + }); return makeCxxInstance( std::make_unique(installBindings)); } - static jni::local_ref - initHybrid(jni::alias_ref, jlong heapSizeMB, bool es6Proxy) { + static jni::local_ref initHybrid( + jni::alias_ref, + jlong heapSizeMB) { JReactMarker::setLogPerfMarkerIfNeeded(); - auto runtimeConfig = makeRuntimeConfig(heapSizeMB, es6Proxy); + auto runtimeConfig = makeRuntimeConfig(heapSizeMB); + std::call_once(flag, []() { + facebook::hermes::HermesRuntime::setFatalHandler(hermesFatalHandler); + }); return makeCxxInstance(std::make_unique( installBindings, JSIExecutor::defaultTimeoutInvoker, runtimeConfig)); } diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java index 8300e5e55e0dc0..fec7c457bc8b98 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/RuntimeConfig.java @@ -10,7 +10,6 @@ /** Holds runtime configuration for a Hermes VM instance (master or snapshot). */ public final class RuntimeConfig { public long heapSizeMB; - public boolean es6Proxy; RuntimeConfig() {} diff --git a/ReactAndroid/src/main/java/com/facebook/hermes/unicode/BUCK b/ReactAndroid/src/main/java/com/facebook/hermes/unicode/BUCK index 8f5636e166283b..49f7e87f72be9a 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/unicode/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/hermes/unicode/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "unicode", srcs = glob(["**/*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/perftest/BUCK b/ReactAndroid/src/main/java/com/facebook/perftest/BUCK index 974cfdbcd02591..1809442c8eae59 100644 --- a/ReactAndroid/src/main/java/com/facebook/perftest/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/perftest/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library") rn_android_library( name = "perftest", srcs = glob(["*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/proguard/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/proguard/annotations/BUCK index 31dc81e24005ae..fd767a6dcf14f3 100644 --- a/ReactAndroid/src/main/java/com/facebook/proguard/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/proguard/annotations/BUCK @@ -16,6 +16,7 @@ fb_native.remote_file( rn_android_library( name = "annotations", srcs = glob(["*.java"]), + autoglob = False, proguard_config = "proguard_annotations.pro", visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index e2a345df18109c..0897152fd12c0e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "react", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 7083f86bfc9cbb..c6766d138f59d4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -20,9 +20,9 @@ import com.facebook.react.modules.core.PermissionListener; /** - * Delegate class for {@link ReactActivity} and {@link ReactFragmentActivity}. You can subclass this - * to provide custom implementations for e.g. {@link #getReactNativeHost()}, if your Application - * class doesn't implement {@link ReactApplication}. + * Delegate class for {@link ReactActivity}. You can subclass this to provide custom implementations + * for e.g. {@link #getReactNativeHost()}, if your Application class doesn't implement {@link + * ReactApplication}. */ public class ReactActivityDelegate { diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactFragmentActivity.java b/ReactAndroid/src/main/java/com/facebook/react/ReactFragmentActivity.java deleted file mode 100644 index 9a0e1a1c1fea46..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactFragmentActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react; - -/** - * @deprecated ReactFragmentActivity will be removed in 0.59 release. Use {@link ReactActivity} - * instead. - */ -@Deprecated -public abstract class ReactFragmentActivity extends ReactActivity {} diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 7807b98c9091ee..0f2656027cc1d7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -41,6 +41,7 @@ import android.os.Bundle; import android.os.Process; import android.view.View; +import android.view.ViewGroup; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.common.logging.FLog; @@ -794,9 +795,15 @@ public void showDevOptionsDialog() { mDevSupportManager.showDevOptionsDialog(); } + @ThreadConfined(UI) private void clearReactRoot(ReactRoot reactRoot) { - reactRoot.getRootViewGroup().removeAllViews(); - reactRoot.getRootViewGroup().setId(View.NO_ID); + UiThreadUtil.assertOnUiThread(); + if (ReactFeatureFlags.enableStartSurfaceRaceConditionFix) { + reactRoot.getState().compareAndSet(ReactRoot.STATE_STARTED, ReactRoot.STATE_STOPPED); + } + ViewGroup rootViewGroup = reactRoot.getRootViewGroup(); + rootViewGroup.removeAllViews(); + rootViewGroup.setId(View.NO_ID); } /** @@ -810,17 +817,28 @@ private void clearReactRoot(ReactRoot reactRoot) { @ThreadConfined(UI) public void attachRootView(ReactRoot reactRoot) { UiThreadUtil.assertOnUiThread(); - mAttachedReactRoots.add(reactRoot); - // Reset reactRoot content as it's going to be populated by the application content from JS. - clearReactRoot(reactRoot); + // Calling clearReactRoot is necessary to initialize the Id on reactRoot + // This is necessary independently if the RN Bridge has been initialized or not. + // Ideally reactRoot should be initialized with id == NO_ID + if (ReactFeatureFlags.enableStartSurfaceRaceConditionFix) { + if (mAttachedReactRoots.add(reactRoot)) { + clearReactRoot(reactRoot); + } + } else { + mAttachedReactRoots.add(reactRoot); + clearReactRoot(reactRoot); + } // If react context is being created in the background, JS application will be started // automatically when creation completes, as reactRoot reactRoot is part of the attached // reactRoot reactRoot list. ReactContext currentContext = getCurrentReactContext(); if (mCreateReactContextThread == null && currentContext != null) { - attachRootViewToInstance(reactRoot); + if (!ReactFeatureFlags.enableStartSurfaceRaceConditionFix + || reactRoot.getState().compareAndSet(ReactRoot.STATE_STOPPED, ReactRoot.STATE_STARTED)) { + attachRootViewToInstance(reactRoot); + } } } @@ -1087,7 +1105,12 @@ private void setupReactContext(final ReactApplicationContext reactContext) { ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START); for (ReactRoot reactRoot : mAttachedReactRoots) { - attachRootViewToInstance(reactRoot); + if (!ReactFeatureFlags.enableStartSurfaceRaceConditionFix + || reactRoot + .getState() + .compareAndSet(ReactRoot.STATE_STOPPED, ReactRoot.STATE_STARTED)) { + attachRootViewToInstance(reactRoot); + } } ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END); } @@ -1151,30 +1174,18 @@ private void attachRootViewToInstance(final ReactRoot reactRoot) { final int rootTag; - if (ReactFeatureFlags.enableFabricStartSurfaceWithLayoutMetrics) { - if (reactRoot.getUIManagerType() == FABRIC) { - rootTag = - uiManager.startSurface( - reactRoot.getRootViewGroup(), - reactRoot.getJSModuleName(), - initialProperties == null - ? new WritableNativeMap() - : Arguments.fromBundle(initialProperties), - reactRoot.getWidthMeasureSpec(), - reactRoot.getHeightMeasureSpec()); - reactRoot.setRootViewTag(rootTag); - reactRoot.setShouldLogContentAppeared(true); - } else { - rootTag = - uiManager.addRootView( - reactRoot.getRootViewGroup(), - initialProperties == null - ? new WritableNativeMap() - : Arguments.fromBundle(initialProperties), - reactRoot.getInitialUITemplate()); - reactRoot.setRootViewTag(rootTag); - reactRoot.runApplication(); - } + if (reactRoot.getUIManagerType() == FABRIC) { + rootTag = + uiManager.startSurface( + reactRoot.getRootViewGroup(), + reactRoot.getJSModuleName(), + initialProperties == null + ? new WritableNativeMap() + : Arguments.fromBundle(initialProperties), + reactRoot.getWidthMeasureSpec(), + reactRoot.getHeightMeasureSpec()); + reactRoot.setRootViewTag(rootTag); + reactRoot.setShouldLogContentAppeared(true); } else { rootTag = uiManager.addRootView( @@ -1184,15 +1195,7 @@ private void attachRootViewToInstance(final ReactRoot reactRoot) { : Arguments.fromBundle(initialProperties), reactRoot.getInitialUITemplate()); reactRoot.setRootViewTag(rootTag); - if (reactRoot.getUIManagerType() == FABRIC) { - // Fabric requires to call updateRootLayoutSpecs before starting JS Application, - // this ensures the root will hace the correct pointScaleFactor. - uiManager.updateRootLayoutSpecs( - rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec()); - reactRoot.setShouldLogContentAppeared(true); - } else { - reactRoot.runApplication(); - } + reactRoot.runApplication(); } Systrace.beginAsyncSection( @@ -1223,6 +1226,7 @@ private void detachViewFromInstance(ReactRoot reactRoot, CatalystInstance cataly } } + @ThreadConfined(UI) private void tearDownReactContext(ReactContext reactContext) { FLog.d(ReactConstants.TAG, "ReactInstanceManager.tearDownReactContext()"); UiThreadUtil.assertOnUiThread(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 45049cb5a65366..2ee520cf05f7c6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -14,6 +14,7 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.util.AttributeSet; @@ -26,6 +27,7 @@ import android.view.WindowManager; import android.widget.FrameLayout; import androidx.annotation.Nullable; +import androidx.annotation.UiThread; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; @@ -34,12 +36,12 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactMarker; import com.facebook.react.bridge.ReactMarkerConstants; +import com.facebook.react.bridge.ReactSoftException; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.modules.appregistry.AppRegistry; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.modules.deviceinfo.DeviceInfoModule; @@ -51,10 +53,10 @@ import com.facebook.react.uimanager.ReactRoot; import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.UIManagerHelper; -import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.systrace.Systrace; +import java.util.concurrent.atomic.AtomicInteger; /** * Default root view for catalyst apps. Provides the ability to listen for size changes so that a UI @@ -83,7 +85,8 @@ public interface ReactRootViewEventListener { private @Nullable String mInitialUITemplate; private @Nullable CustomGlobalLayoutListener mCustomGlobalLayoutListener; private @Nullable ReactRootViewEventListener mRootViewEventListener; - private int mRootViewTag; + private int mRootViewTag = + 0; /* This should be View.NO_ID, but for legacy reasons we haven't migrated yet */ private boolean mIsAttachedToInstance; private boolean mShouldLogContentAppeared; private @Nullable JSTouchDispatcher mJSTouchDispatcher; @@ -94,7 +97,10 @@ public interface ReactRootViewEventListener { private int mHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); private int mLastWidth = 0; private int mLastHeight = 0; + private int mLastOffsetX = Integer.MIN_VALUE; + private int mLastOffsetY = Integer.MIN_VALUE; private @UIManagerType int mUIManagerType = DEFAULT; + private final AtomicInteger mState = new AtomicInteger(STATE_STOPPED); public ReactRootView(Context context) { super(context); @@ -118,6 +124,7 @@ private void init() { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.onMeasure"); + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_ON_MEASURE_START); try { boolean measureSpecsUpdated = widthMeasureSpec != mWidthMeasureSpec || heightMeasureSpec != mHeightMeasureSpec; @@ -161,12 +168,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mReactInstanceManager != null && !mIsAttachedToInstance) { attachToReactInstanceManager(); } else if (measureSpecsUpdated || mLastWidth != width || mLastHeight != height) { - updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec); + updateRootLayoutSpecs(true, mWidthMeasureSpec, mHeightMeasureSpec); } mLastWidth = width; mLastHeight = height; } finally { + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_ON_MEASURE_END); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } } @@ -184,7 +192,7 @@ public void onChildStartedNativeGesture(MotionEvent androidEvent) { return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + UIManager uiManager = UIManagerHelper.getUIManager(reactContext, getUIManagerType()); if (uiManager != null) { EventDispatcher eventDispatcher = uiManager.getEventDispatcher(); @@ -272,7 +280,7 @@ private void dispatchJSTouchEvent(MotionEvent event) { return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); + UIManager uiManager = UIManagerHelper.getUIManager(reactContext, getUIManagerType()); if (uiManager != null) { EventDispatcher eventDispatcher = uiManager.getEventDispatcher(); @@ -291,7 +299,12 @@ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - // No-op since UIManagerModule handles actually laying out children. + // No-op in non-Fabric since UIManagerModule handles actually laying out children. + + // In Fabric, update LayoutSpecs just so we update the offsetX and offsetY. + if (mWasMeasured && getUIManagerType() == FABRIC) { + updateRootLayoutSpecs(false, mWidthMeasureSpec, mHeightMeasureSpec); + } } @Override @@ -376,8 +389,6 @@ public void startReactApplication( mReactInstanceManager.createReactContextInBackground(); - attachToReactInstanceManager(); - } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } @@ -405,11 +416,50 @@ public String getSurfaceID() { return appProperties != null ? appProperties.getString("surfaceID") : null; } - private void updateRootLayoutSpecs(final int widthMeasureSpec, final int heightMeasureSpec) { + public AtomicInteger getState() { + return mState; + } + + @UiThread + public static Point getViewportOffset(View v) { + int[] locationInWindow = new int[2]; + v.getLocationInWindow(locationInWindow); + + // we need to subtract visibleWindowCoords - to subtract possible window insets, split + // screen or multi window + Rect visibleWindowFrame = new Rect(); + v.getWindowVisibleDisplayFrame(visibleWindowFrame); + locationInWindow[0] -= visibleWindowFrame.left; + locationInWindow[1] -= visibleWindowFrame.top; + + return new Point(locationInWindow[0], locationInWindow[1]); + } + + /** + * Call whenever measure specs change, or if you want to force an update of offsetX/offsetY. If + * measureSpecsChanged is false and the offsetX/offsetY don't change, updateRootLayoutSpecs will + * not be called on the UIManager as a perf optimization. + * + * @param measureSpecsChanged + * @param widthMeasureSpec + * @param heightMeasureSpec + */ + private void updateRootLayoutSpecs( + boolean measureSpecsChanged, final int widthMeasureSpec, final int heightMeasureSpec) { + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_UPDATE_LAYOUT_SPECS_START); if (mReactInstanceManager == null) { + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_UPDATE_LAYOUT_SPECS_END); FLog.w(TAG, "Unable to update root layout specs for uninitialized ReactInstanceManager"); return; } + // In Fabric we cannot call `updateRootLayoutSpecs` until a SurfaceId has been set. + // Sometimes, + if (getUIManagerType() == FABRIC && !isRootViewTagSet()) { + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_UPDATE_LAYOUT_SPECS_END); + FLog.e(TAG, "Unable to update root layout specs for ReactRootView: no rootViewTag set yet"); + return; + } + final ReactContext reactApplicationContext = mReactInstanceManager.getCurrentReactContext(); if (reactApplicationContext != null) { @@ -418,9 +468,25 @@ private void updateRootLayoutSpecs(final int widthMeasureSpec, final int heightM UIManagerHelper.getUIManager(reactApplicationContext, getUIManagerType()); // Ignore calling updateRootLayoutSpecs if UIManager is not properly initialized. if (uiManager != null) { - uiManager.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec); + // In Fabric only, get position of view within screen + int offsetX = 0; + int offsetY = 0; + if (getUIManagerType() == FABRIC) { + Point viewportOffset = getViewportOffset(this); + offsetX = viewportOffset.x; + offsetY = viewportOffset.y; + } + + if (measureSpecsChanged || offsetX != mLastOffsetX || offsetY != mLastOffsetY) { + uiManager.updateRootLayoutSpecs( + getRootViewTag(), widthMeasureSpec, heightMeasureSpec, offsetX, offsetY); + } + mLastOffsetX = offsetX; + mLastOffsetY = offsetY; } } + + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_UPDATE_LAYOUT_SPECS_END); } /** @@ -438,15 +504,26 @@ public void unmountReactApplication() { // to be committed via the Scheduler, which will cause mounting instructions // to be queued up and synchronously executed to delete and remove // all the views in the hierarchy. - if (mReactInstanceManager != null && ReactFeatureFlags.enableStopSurfaceOnRootViewUnmount) { + if (mReactInstanceManager != null) { final ReactContext reactApplicationContext = mReactInstanceManager.getCurrentReactContext(); if (reactApplicationContext != null && getUIManagerType() == FABRIC) { @Nullable UIManager uiManager = UIManagerHelper.getUIManager(reactApplicationContext, getUIManagerType()); if (uiManager != null) { - FLog.e(TAG, "stopSurface for surfaceId: " + this.getId()); - uiManager.stopSurface(this.getId()); + // TODO T48186892: remove when resolved + FLog.e( + TAG, + "stopSurface for surfaceId: " + this.getId(), + new RuntimeException("unmountReactApplication")); + if (getId() == NO_ID) { + ReactSoftException.logSoftException( + TAG, + new RuntimeException( + "unmountReactApplication called on ReactRootView with invalid id")); + } else { + uiManager.stopSurface(this.getId()); + } } } } @@ -504,7 +581,7 @@ public String getJSModuleName() { public void setAppProperties(@Nullable Bundle appProperties) { UiThreadUtil.assertOnUiThread(); mAppProperties = appProperties; - if (getRootViewTag() != 0) { + if (isRootViewTagSet()) { runApplication(); } } @@ -530,7 +607,7 @@ public void runApplication() { String jsAppModuleName = getJSModuleName(); if (mWasMeasured) { - updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec); + updateRootLayoutSpecs(true, mWidthMeasureSpec, mHeightMeasureSpec); } WritableNativeMap appParams = new WritableNativeMap(); @@ -567,16 +644,28 @@ private CustomGlobalLayoutListener getCustomGlobalLayoutListener() { private void attachToReactInstanceManager() { Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachToReactInstanceManager"); + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_ATTACH_TO_REACT_INSTANCE_MANAGER_START); - if (mIsAttachedToInstance) { - return; + // React Native requires that the RootView id be managed entirely by React Native, and will + // crash in addRootView/startSurface if the native View id isn't set to NO_ID. + if (getId() != View.NO_ID) { + throw new IllegalViewOperationException( + "Trying to attach a ReactRootView with an explicit id already set to [" + + getId() + + "]. React Native uses the id field to track react tags and will overwrite this" + + " field. If that is fine, explicitly overwrite the id field to View.NO_ID."); } try { + if (mIsAttachedToInstance) { + return; + } + mIsAttachedToInstance = true; Assertions.assertNotNull(mReactInstanceManager).attachRootView(this); getViewTreeObserver().addOnGlobalLayoutListener(getCustomGlobalLayoutListener()); } finally { + ReactMarker.logMarker(ReactMarkerConstants.ROOT_VIEW_ATTACH_TO_REACT_INSTANCE_MANAGER_END); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } } @@ -597,6 +686,10 @@ public int getRootViewTag() { return mRootViewTag; } + private boolean isRootViewTagSet() { + return mRootViewTag != 0 && mRootViewTag != NO_ID; + } + public void setRootViewTag(int rootViewTag) { mRootViewTag = rootViewTag; } @@ -700,6 +793,7 @@ private void checkForDeviceOrientationChanges() { return; } mDeviceRotation = rotation; + DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext()); emitOrientationChanged(rotation); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK b/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK index c3f9021b086d2e..da22b9787c38f2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/BUCK @@ -1,10 +1,11 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "animated", srcs = glob([ "*.java", ]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -28,5 +29,5 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index 8a05e0627edbfb..2f2880080e6fc5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactSoftException; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UIManagerListener; @@ -34,6 +35,7 @@ import com.facebook.react.uimanager.common.ViewUtil; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicReference; /** * Module that exposes interface for creating and managing animated nodes on the "native" side. @@ -111,7 +113,7 @@ public long getBatchNumber() { private final ConcurrentLinkedQueue mPreOperations = new ConcurrentLinkedQueue<>(); - private @Nullable NativeAnimatedNodesManager mNodesManager; + private final AtomicReference mNodesManager = new AtomicReference<>(); private boolean mBatchingControlledByJS = false; // TODO T71377544: delete private volatile long mCurrentFrameNumber; // TODO T71377544: delete @@ -223,6 +225,7 @@ public void didDispatchMountItems(UIManager uiManager) { executeAllOperations(mOperations, batchNumber); } + @UiThread private void executeAllOperations(Queue operationQueue, long maxBatchNumber) { NativeAnimatedNodesManager nodesManager = getNodesManager(); while (true) { @@ -315,15 +318,15 @@ public String getName() { */ @Nullable private NativeAnimatedNodesManager getNodesManager() { - if (mNodesManager == null) { + if (mNodesManager.get() == null) { ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); if (reactApplicationContext != null) { - mNodesManager = new NativeAnimatedNodesManager(reactApplicationContext); + mNodesManager.compareAndSet(null, new NativeAnimatedNodesManager(reactApplicationContext)); } } - return mNodesManager; + return mNodesManager.get(); } private void clearFrameCallback() { @@ -340,7 +343,7 @@ private void enqueueFrameCallback() { @VisibleForTesting public void setNodesManager(NativeAnimatedNodesManager nodesManager) { - mNodesManager = nodesManager; + mNodesManager.set(nodesManager); } /** @@ -358,8 +361,14 @@ private void initializeLifecycleEventListenersForViewTag(final int viewTag) { mNumNonFabricAnimations++; } - if (mNodesManager != null) { - mNodesManager.initializeEventListenerForUIManagerType(mUIManagerType); + NativeAnimatedNodesManager nodesManager = getNodesManager(); + if (nodesManager != null) { + nodesManager.initializeEventListenerForUIManagerType(mUIManagerType); + } else { + ReactSoftException.logSoftException( + NAME, + new RuntimeException( + "initializeLifecycleEventListenersForViewTag could not get NativeAnimatedNodesManager")); } // Subscribe to UIManager (Fabric or non-Fabric) lifecycle events if we haven't yet diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java index 9bf6d02fd2a11c..0ff510e5d0d234 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java @@ -121,7 +121,7 @@ public boolean hasActiveAnimations() { public void createAnimatedNode(int tag, ReadableMap config) { if (mAnimatedNodes.get(tag) != null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " already exists"); + "createAnimatedNode: Animated node [" + tag + "] already exists"); } String type = config.getString("type"); final AnimatedNode node; @@ -168,7 +168,9 @@ public void startListeningToAnimatedNodeValue(int tag, AnimatedNodeValueListener AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "startListeningToAnimatedNodeValue: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } ((ValueAnimatedNode) node).setValueListener(listener); } @@ -178,7 +180,9 @@ public void stopListeningToAnimatedNodeValue(int tag) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "startListeningToAnimatedNodeValue: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } ((ValueAnimatedNode) node).setValueListener(null); } @@ -188,7 +192,9 @@ public void setAnimatedNodeValue(int tag, double value) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "setAnimatedNodeValue: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } stopAnimationsForNode(node); ((ValueAnimatedNode) node).mValue = value; @@ -200,7 +206,9 @@ public void setAnimatedNodeOffset(int tag, double offset) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "setAnimatedNodeOffset: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } ((ValueAnimatedNode) node).mOffset = offset; mUpdatedNodes.put(tag, node); @@ -211,7 +219,9 @@ public void flattenAnimatedNodeOffset(int tag) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "flattenAnimatedNodeOffset: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } ((ValueAnimatedNode) node).flattenOffset(); } @@ -221,7 +231,9 @@ public void extractAnimatedNodeOffset(int tag) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exist, or is not a 'value' node"); + "extractAnimatedNodeOffset: Animated node [" + + tag + + "] does not exist, or is not a 'value' node"); } ((ValueAnimatedNode) node).extractOffset(); } @@ -232,11 +244,14 @@ public void startAnimatingNode( AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + animatedNodeTag + " does not exist"); + "startAnimatingNode: Animated node [" + animatedNodeTag + "] does not exist"); } if (!(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node should be of type " + ValueAnimatedNode.class.getName()); + "startAnimatingNode: Animated node [" + + animatedNodeTag + + "] should be of type " + + ValueAnimatedNode.class.getName()); } final AnimationDriver existingDriver = mActiveAnimations.get(animationId); @@ -256,7 +271,8 @@ public void startAnimatingNode( } else if ("decay".equals(type)) { animation = new DecayAnimation(animationConfig); } else { - throw new JSApplicationIllegalArgumentException("Unsupported animation type: " + type); + throw new JSApplicationIllegalArgumentException( + "startAnimatingNode: Unsupported animation type [" + animatedNodeTag + "]: " + type); } animation.mId = animationId; animation.mEndCallback = endCallback; @@ -315,12 +331,16 @@ public void connectAnimatedNodes(int parentNodeTag, int childNodeTag) { AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag); if (parentNode == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + parentNodeTag + " does not exists"); + "connectAnimatedNodes: Animated node with tag (parent) [" + + parentNodeTag + + "] does not exist"); } AnimatedNode childNode = mAnimatedNodes.get(childNodeTag); if (childNode == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + childNodeTag + " does not exists"); + "connectAnimatedNodes: Animated node with tag (child) [" + + childNodeTag + + "] does not exist"); } parentNode.addChild(childNode); mUpdatedNodes.put(childNodeTag, childNode); @@ -330,12 +350,16 @@ public void disconnectAnimatedNodes(int parentNodeTag, int childNodeTag) { AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag); if (parentNode == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + parentNodeTag + " does not exists"); + "disconnectAnimatedNodes: Animated node with tag (parent) [" + + parentNodeTag + + "] does not exist"); } AnimatedNode childNode = mAnimatedNodes.get(childNodeTag); if (childNode == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + childNodeTag + " does not exists"); + "disconnectAnimatedNodes: Animated node with tag (child) [" + + childNodeTag + + "] does not exist"); } parentNode.removeChild(childNode); mUpdatedNodes.put(childNodeTag, childNode); @@ -346,17 +370,21 @@ public void connectAnimatedNodeToView(int animatedNodeTag, int viewTag) { AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + animatedNodeTag + " does not exists"); + "connectAnimatedNodeToView: Animated node with tag [" + + animatedNodeTag + + "] does not exist"); } if (!(node instanceof PropsAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node connected to view should be" - + "of type " + "connectAnimatedNodeToView: Animated node connected to view [" + + viewTag + + "] should be of type " + PropsAnimatedNode.class.getName()); } if (mReactApplicationContext == null) { throw new IllegalStateException( - "Animated node could not be connected, no ReactApplicationContext: " + viewTag); + "connectAnimatedNodeToView: Animated node could not be connected, no ReactApplicationContext: " + + viewTag); } @Nullable @@ -366,7 +394,7 @@ public void connectAnimatedNodeToView(int animatedNodeTag, int viewTag) { ReactSoftException.logSoftException( TAG, new ReactNoCrashSoftException( - "Animated node could not be connected to UIManager - uiManager disappeared for tag: " + "connectAnimatedNodeToView: Animated node could not be connected to UIManager - uiManager disappeared for tag: " + viewTag)); return; } @@ -381,12 +409,15 @@ public void disconnectAnimatedNodeFromView(int animatedNodeTag, int viewTag) { AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + animatedNodeTag + " does not exists"); + "disconnectAnimatedNodeFromView: Animated node with tag [" + + animatedNodeTag + + "] does not exist"); } if (!(node instanceof PropsAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node connected to view should be" - + "of type " + "disconnectAnimatedNodeFromView: Animated node connected to view [" + + viewTag + + "] should be of type " + PropsAnimatedNode.class.getName()); } PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node; @@ -398,7 +429,7 @@ public void getValue(int tag, Callback callback) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + tag + " does not exists or is not a 'value' node"); + "getValue: Animated node with tag [" + tag + "] does not exist or is not a 'value' node"); } callback.invoke(((ValueAnimatedNode) node).getValue()); } @@ -415,8 +446,7 @@ public void restoreDefaultValues(int animatedNodeTag) { } if (!(node instanceof PropsAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node connected to view should be" - + "of type " + "Animated node connected to view [?] should be of type " + PropsAnimatedNode.class.getName()); } PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node; @@ -429,12 +459,15 @@ public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap ev AnimatedNode node = mAnimatedNodes.get(nodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException( - "Animated node with tag " + nodeTag + " does not exists"); + "addAnimatedEventToView: Animated node with tag [" + nodeTag + "] does not exist"); } if (!(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException( - "Animated node connected to event should be" - + "of type " + "addAnimatedEventToView: Animated node on view [" + + viewTag + + "] connected to event (" + + eventName + + ") should be of type " + ValueAnimatedNode.class.getName()); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java index 6302abe043e5f3..c5e8a5ccbcfad0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java @@ -10,12 +10,14 @@ import android.os.Bundle; import android.os.Parcelable; import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; import java.lang.reflect.Array; import java.util.AbstractList; import java.util.ArrayList; import java.util.List; import java.util.Map; +@DoNotStrip public class Arguments { private static Object makeNativeObject(Object object) { if (object == null) { @@ -122,6 +124,7 @@ private static void addEntry(WritableNativeMap nativeMap, String key, Object val * The best way to think of this is a way to generate a Java representation of a json object, from * Java types which have a natural representation in json. */ + @DoNotStrip public static WritableNativeMap makeNativeMap(Map objects) { WritableNativeMap nativeMap = new WritableNativeMap(); if (objects == null) { @@ -134,6 +137,7 @@ public static WritableNativeMap makeNativeMap(Map objects) { } /** Like the above, but takes a Bundle instead of a Map. */ + @DoNotStrip public static WritableNativeMap makeNativeMap(Bundle bundle) { WritableNativeMap nativeMap = new WritableNativeMap(); if (bundle == null) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK index fcf60e30696589..0f54a3c0b0b57f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK @@ -20,6 +20,7 @@ rn_android_library( ["**/*.java"], exclude = INTERFACES, ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], proguard_config = "reactnative.pro", @@ -65,6 +66,7 @@ rn_android_library( rn_android_library( name = "interfaces", srcs = glob(INTERFACES), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], proguard_config = "reactnative.pro", diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 1bbd069bce3749..859d227243f2e8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -470,7 +470,8 @@ public JavaScriptContextHolder getJavaScriptContextHolder() { * @param segmentId * @param path */ - public void registerSegment(int segmentId, String path) { + public void registerSegment(int segmentId, String path, Callback callback) { Assertions.assertNotNull(mCatalystInstance).registerSegment(segmentId, path); + Assertions.assertNotNull(callback).invoke(); } } 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 dd08b9a8eea480..91e13be6f040ee 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java @@ -94,6 +94,12 @@ public enum ReactMarkerConstants { JAVASCRIPT_EXECUTOR_FACTORY_INJECT_END, LOAD_REACT_NATIVE_SO_FILE_START, LOAD_REACT_NATIVE_SO_FILE_END, + ROOT_VIEW_ON_MEASURE_START, + ROOT_VIEW_ON_MEASURE_END, + ROOT_VIEW_ATTACH_TO_REACT_INSTANCE_MANAGER_START, + ROOT_VIEW_ATTACH_TO_REACT_INSTANCE_MANAGER_END, + ROOT_VIEW_UPDATE_LAYOUT_SPECS_START, + ROOT_VIEW_UPDATE_LAYOUT_SPECS_END, // Fabric-specific constants below this line LOAD_REACT_NATIVE_FABRIC_SO_FILE_START, LOAD_REACT_NATIVE_FABRIC_SO_FILE_END, @@ -108,5 +114,8 @@ public enum ReactMarkerConstants { FABRIC_BATCH_EXECUTION_START, FABRIC_BATCH_EXECUTION_END, FABRIC_UPDATE_UI_MAIN_THREAD_START, - FABRIC_UPDATE_UI_MAIN_THREAD_END + FABRIC_UPDATE_UI_MAIN_THREAD_END, + // New markers used by bridgeless RN below this line + REACT_INSTANCE_INIT_START, + REACT_INSTANCE_INIT_END } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java index 5c3ac667e0e828..82ffb0e8ab3ad5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java @@ -8,7 +8,6 @@ package com.facebook.react.bridge; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import java.util.ArrayList; /** @@ -27,13 +26,13 @@ public interface ReadableArray { int getInt(int index); - @Nullable + @NonNull String getString(int index); - @Nullable + @NonNull ReadableArray getArray(int index); - @Nullable + @NonNull ReadableMap getMap(int index); @NonNull diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java index 361457dbadd067..cc80051b4954e4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java @@ -98,17 +98,17 @@ public int getInt(int index) { } @Override - public @Nullable String getString(int index) { + public @NonNull String getString(int index) { return (String) getLocalArray()[index]; } @Override - public @Nullable ReadableNativeArray getArray(int index) { + public @NonNull ReadableNativeArray getArray(int index) { return (ReadableNativeArray) getLocalArray()[index]; } @Override - public @Nullable ReadableNativeMap getMap(int index) { + public @NonNull ReadableNativeMap getMap(int index) { return (ReadableNativeMap) getLocalArray()[index]; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index e8609d8ead5348..a2e4319224abcc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -120,7 +120,7 @@ private T getValue(String name, Class type) { if (hasKey(name)) { return getLocalMap().get(name); } - throw new NoSuchKeyException(name); + return null; } private @Nullable T getNullableValue(String name, Class type) { @@ -187,12 +187,62 @@ public int getInt(@NonNull String name) { @Override public @NonNull Iterator> getEntryIterator() { - return getLocalMap().entrySet().iterator(); + if (mKeys == null) { + mKeys = Assertions.assertNotNull(importKeys()); + } + final String[] iteratorKeys = mKeys; + final Object[] iteratorValues = Assertions.assertNotNull(importValues()); + return new Iterator>() { + int currentIndex = 0; + + @Override + public boolean hasNext() { + return currentIndex < iteratorKeys.length; + } + + @Override + public Map.Entry next() { + final int index = currentIndex++; + return new Map.Entry() { + @Override + public String getKey() { + return iteratorKeys[index]; + } + + @Override + public Object getValue() { + return iteratorValues[index]; + } + + @Override + public Object setValue(Object value) { + throw new UnsupportedOperationException( + "Can't set a value while iterating over a ReadableNativeMap"); + } + }; + } + }; } @Override public @NonNull ReadableMapKeySetIterator keySetIterator() { - return new ReadableNativeMapKeySetIterator(this); + if (mKeys == null) { + mKeys = Assertions.assertNotNull(importKeys()); + } + final String[] iteratorKeys = mKeys; + return new ReadableMapKeySetIterator() { + int currentIndex = 0; + + @Override + public boolean hasNextKey() { + return currentIndex < iteratorKeys.length; + } + + @Override + public String nextKey() { + return iteratorKeys[currentIndex++]; + } + }; } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java index 0bd6a2c649a15e..40776a84e829b3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManager.java @@ -14,12 +14,14 @@ import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.facebook.infer.annotation.ThreadConfined; +import java.util.List; public interface UIManager extends JSIModule, PerformanceCounter { - /** Registers a new root view. */ + /** Registers a new root view. @Deprecated call startSurface instead */ @UiThread @ThreadConfined(UI) + @Deprecated int addRootView( final T rootView, WritableMap initialProps, @Nullable String initialUITemplate); @@ -41,11 +43,12 @@ int startSurface( /** * Updates the layout specs of the RootShadowNode based on the Measure specs received by - * parameters. + * parameters. offsetX and offsetY are the position of the RootView within the screen. */ @UiThread @ThreadConfined(UI) - void updateRootLayoutSpecs(int rootTag, int widthMeasureSpec, int heightMeasureSpec); + void updateRootLayoutSpecs( + int rootTag, int widthMeasureSpec, int heightMeasureSpec, int offsetX, int offsetY); /** * Dispatches the commandId received by parameter to the view associated with the reactTag. The @@ -82,7 +85,7 @@ int startSurface( * layout-related propertied won't be handled properly. Make sure you know what you're doing * before calling this method :) * - * @param tag {@link int} that identifies the view that will be updated + * @param reactTag {@link int} that identifies the view that will be updated * @param props {@link ReadableMap} props that should be immediately updated in view */ @UiThread @@ -122,10 +125,33 @@ int startSurface( * @param eventName name of the event * @param event parameters */ + @Deprecated void receiveEvent(int reactTag, String eventName, @Nullable WritableMap event); + /** + * This method dispatches events from RN Android code to JS. The delivery of this event will not + * be queued in EventDispatcher class. + * + * @param surfaceId + * @param reactTag tag + * @param eventName name of the event + * @param event parameters + */ + void receiveEvent(int surfaceId, int reactTag, String eventName, @Nullable WritableMap event); + /** Resolves Direct Event name exposed to JS from the one known to the Native side. */ @Deprecated @Nullable String resolveCustomDirectEventName(@Nullable String eventName); + + /** + * Helper method to pre-initialize view managers. When using Native ViewConfigs this method will + * also pre-compute the constants for a view manager. The purpose is to ensure that we don't block + * for getting the constants for view managers during initial rendering of a surface. + * + * @deprecated this method will be removed in the future + * @param viewManagerNames {@link List } names of ViewManagers + */ + @Deprecated + void preInitializeViewManagers(List viewManagerNames); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java index dd31f88fd5fa16..ebe2e1404fdbe3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/ReactQueueConfigurationSpec.java @@ -7,7 +7,6 @@ package com.facebook.react.bridge.queue; -import android.os.Build; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Assertions; @@ -19,8 +18,6 @@ */ public class ReactQueueConfigurationSpec { - private static final long LEGACY_STACK_SIZE_BYTES = 2000000; - private final MessageQueueThreadSpec mNativeModulesQueueThreadSpec; private final MessageQueueThreadSpec mJSQueueThreadSpec; @@ -44,11 +41,7 @@ public static Builder builder() { } public static ReactQueueConfigurationSpec createDefault() { - MessageQueueThreadSpec spec = - Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP - ? MessageQueueThreadSpec.newBackgroundThreadSpec( - "native_modules", LEGACY_STACK_SIZE_BYTES) - : MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules"); + MessageQueueThreadSpec spec = MessageQueueThreadSpec.newBackgroundThreadSpec("native_modules"); return builder() .setJSQueueThreadSpec(MessageQueueThreadSpec.newBackgroundThreadSpec("js")) .setNativeModulesQueueThreadSpec(spec) diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK index ef52fb6fb78abf..596d953a230158 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK @@ -10,6 +10,7 @@ rn_android_library( ["**/*.java"], exclude = SUB_PROJECTS, ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -39,6 +40,7 @@ rn_android_build_config( package = "com.facebook.react", values = [ "boolean IS_INTERNAL_BUILD = true", + "int HERMES_BYTECODE_VERSION = 0", ], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.java b/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.java index a90ec674e12edd..093bd88c580a45 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.java +++ b/ReactAndroid/src/main/java/com/facebook/react/common/build/ReactBuildConfig.java @@ -20,4 +20,5 @@ public class ReactBuildConfig { public static final boolean DEBUG = BuildConfig.DEBUG; public static final boolean IS_INTERNAL_BUILD = BuildConfig.IS_INTERNAL_BUILD; public static final int EXOPACKAGE_FLAGS = BuildConfig.EXOPACKAGE_FLAGS; + public static final int HERMES_BYTECODE_VERSION = BuildConfig.HERMES_BYTECODE_VERSION; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK index 25f39b59688c28..2eca2adf3f72ca 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/network/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "network", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/BUCK b/ReactAndroid/src/main/java/com/facebook/react/config/BUCK index 6120fdec936c2d..d2a96d88cfeeea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/config/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library") rn_android_library( name = "config", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 6c2bd52a80fb7a..b1bb234aecd5a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -23,6 +23,9 @@ public class ReactFeatureFlags { */ public static volatile boolean useTurboModules = false; + /** Should we dispatch TurboModule methods with promise returns to the NativeModules thread? */ + public static volatile boolean enableTurboModulePromiseAsyncDispatch = false; + /* * This feature flag enables logs for Fabric */ @@ -42,18 +45,6 @@ public class ReactFeatureFlags { */ public static boolean useViewManagerDelegatesForCommands = false; - /** - * This react flag enables a custom algorithm for the getChildVisibleRect() method in the classes - * ReactViewGroup, ReactHorizontalScrollView and ReactScrollView. - * - *

This new algorithm clip child rects if overflow is set to ViewProps.HIDDEN. More details in - * https://github.com/facebook/react-native/issues/23870 and - * https://github.com/facebook/react-native/pull/26334 - * - *

The react flag is disabled by default because this is increasing ANRs (T57363204) - */ - public static boolean clipChildRectsIfOverflowIsHidden = false; - /** * Temporary feature flat to control a fix in the transition to layoutOnlyViews TODO T61185028: * remove this when bug is fixed @@ -63,15 +54,15 @@ public class ReactFeatureFlags { /** Feature flag to configure eager initialization of Fabric */ public static boolean eagerInitializeFabric = false; - /** Feature flag to configure initialization of Fabric surfaces. */ - public static boolean enableFabricStartSurfaceWithLayoutMetrics = true; + /** Disable UI update operations in non-Fabric renderer after catalyst instance was destroyed */ + public static boolean disableNonFabricViewOperationsOnCatalystDestroy = false; - /** Feature flag to use stopSurface when ReactRootView is unmounted. */ - public static boolean enableStopSurfaceOnRootViewUnmount = false; - - /** Use experimental SetState retry mechanism in view? */ - public static boolean enableExperimentalStateUpdateRetry = false; + /** + * Fixes race-condition in the initialization of RN surface. TODO T78832286: remove this flag once + * we verify the fix is correct in production + */ + public static boolean enableStartSurfaceRaceConditionFix = false; - /** Enable caching of Spannable objects using equality of ReadableNativeMaps */ - public static boolean enableSpannableCacheByReadableNativeMapEquality = true; + /** Enables Static ViewConfig in RN Android native code. */ + public static boolean enableExperimentalStaticViewConfigs = false; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK index 7680650ab6a62f..2c919248ab83d8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "devsupport", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], manifest = "AndroidManifest.xml", @@ -39,13 +40,14 @@ rn_android_library( react_native_target("res:devsupport"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) rn_android_library( name = "interfaces", srcs = glob(["interfaces/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 83e7ca48cb1558..88bb1764b90d13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -14,6 +14,7 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; import com.facebook.react.devsupport.interfaces.StackFrame; @@ -428,9 +429,13 @@ private String createSplitBundleURL(String mainModuleID, String host) { private String createBundleURL( String mainModuleID, BundleType type, String host, boolean modulesOnly, boolean runModule) { + String runtimeBytecodeVersion = + ReactBuildConfig.HERMES_BYTECODE_VERSION != 0 + ? "&runtimeBytecodeVersion=" + ReactBuildConfig.HERMES_BYTECODE_VERSION + : ""; return String.format( Locale.US, - "http://%s/%s.%s?platform=android&dev=%s&minify=%s&app=%s&modulesOnly=%s&runModule=%s", + "http://%s/%s.%s?platform=android&dev=%s&minify=%s&app=%s&modulesOnly=%s&runModule=%s%s", host, mainModuleID, type.typeID(), @@ -438,7 +443,8 @@ private String createBundleURL( getJSMinifyMode(), mPackageName, modulesOnly ? "true" : "false", - runModule ? "true" : "false"); + runModule ? "true" : "false", + runtimeBytecodeVersion); } private String createBundleURL(String mainModuleID, BundleType type) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java index 427c7f37a1ac16..aa84c0091c5686 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -102,7 +102,7 @@ private enum ErrorType { private final Context mApplicationContext; private final ShakeDetector mShakeDetector; private final BroadcastReceiver mReloadAppBroadcastReceiver; - private final DevServerHelper mDevServerHelper; + protected final DevServerHelper mDevServerHelper; private final LinkedHashMap mCustomDevOptions = new LinkedHashMap<>(); private final ReactInstanceManagerDevHelper mReactInstanceManagerHelper; private final @Nullable String mJSAppBundleName; diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK b/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK index 9ebcd431161f44..f3cb842381849b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/BUCK @@ -8,6 +8,7 @@ rn_android_library( "jsi/*.java", "mounting/**/*.java", ]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -39,6 +40,7 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/views/view:view"), + react_native_target("java/com/facebook/react/views/text:text"), react_native_target("java/com/facebook/react/touch:touch"), ], exported_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java index cbe49ce51d2088..ea080bd4e071ed 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java @@ -52,6 +52,8 @@ public native void startSurfaceWithConstraints( float maxWidth, float minHeight, float maxHeight, + float offsetX, + float offsetY, boolean isRTL, boolean doLeftAndRightSwapInRTL); @@ -67,6 +69,8 @@ public native void setConstraints( float maxWidth, float minHeight, float maxHeight, + float offsetX, + float offsetY, boolean isRTL, boolean doLeftAndRightSwapInRTL); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricComponents.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricComponents.java index 9f0f32c169d2a6..ab16eac8e2785f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricComponents.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricComponents.java @@ -43,7 +43,7 @@ public class FabricComponents { } /** @return the name of component in the Fabric environment */ - static String getFabricComponentName(String componentName) { + public static String getFabricComponentName(String componentName) { String component = sComponentNames.get(componentName); return component != null ? component : componentName; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java index c079b48231795a..c4db712c77c973 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -7,6 +7,8 @@ package com.facebook.react.fabric; +import static com.facebook.react.config.ReactFeatureFlags.enableExperimentalStaticViewConfigs; + import androidx.annotation.NonNull; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.JSIModuleProvider; @@ -18,25 +20,19 @@ import com.facebook.react.fabric.events.FabricEventEmitter; import com.facebook.react.fabric.mounting.LayoutMetricsConversions; import com.facebook.react.fabric.mounting.MountingManager; -import com.facebook.react.fabric.mounting.mountitems.BatchMountItem; -import com.facebook.react.fabric.mounting.mountitems.CreateMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem; -import com.facebook.react.fabric.mounting.mountitems.InsertMountItem; +import com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem; import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.fabric.mounting.mountitems.PreAllocateViewMountItem; -import com.facebook.react.fabric.mounting.mountitems.RemoveDeleteMultiMountItem; import com.facebook.react.fabric.mounting.mountitems.SendAccessibilityEvent; -import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdatePaddingMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.react.uimanager.events.BatchEventDispatchedListener; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.uimanager.events.EventDispatcherImpl; import com.facebook.systrace.Systrace; public class FabricJSIModuleProvider implements JSIModuleProvider { @@ -44,18 +40,22 @@ public class FabricJSIModuleProvider implements JSIModuleProvider { @NonNull private final ReactApplicationContext mReactApplicationContext; @NonNull private final ComponentFactory mComponentFactory; @NonNull private final ReactNativeConfig mConfig; + @NonNull private final ViewManagerRegistry mViewManagerRegistry; public FabricJSIModuleProvider( @NonNull ReactApplicationContext reactApplicationContext, @NonNull ComponentFactory componentFactory, - @NonNull ReactNativeConfig config) { + @NonNull ReactNativeConfig config, + @NonNull ViewManagerRegistry viewManagerRegistry) { mReactApplicationContext = reactApplicationContext; mComponentFactory = componentFactory; mConfig = config; + mViewManagerRegistry = viewManagerRegistry; } @Override public UIManager get() { + Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricJSIModuleProvider.get"); final EventBeatManager eventBeatManager = new EventBeatManager(mReactApplicationContext); final FabricUIManager uiManager = createUIManager(eventBeatManager); Systrace.beginSection( @@ -76,48 +76,49 @@ public UIManager get() { jsMessageQueueThread, mComponentFactory, mConfig); + + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + return uiManager; } private FabricUIManager createUIManager(@NonNull EventBeatManager eventBeatManager) { Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricJSIModuleProvider.createUIManager"); - UIManagerModule nativeModule = - Assertions.assertNotNull(mReactApplicationContext.getNativeModule(UIManagerModule.class)); - EventDispatcher eventDispatcher = nativeModule.getEventDispatcher(); + EventDispatcher eventDispatcher = getEventDispatcher(); FabricUIManager fabricUIManager = new FabricUIManager( - mReactApplicationContext, - nativeModule.getViewManagerRegistry_DO_NOT_USE(), - eventDispatcher, - eventBeatManager); + mReactApplicationContext, mViewManagerRegistry, eventDispatcher, eventBeatManager); Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); return fabricUIManager; } + private EventDispatcher getEventDispatcher() { + EventDispatcher eventDispatcher; + if (enableExperimentalStaticViewConfigs) { + eventDispatcher = new EventDispatcherImpl(mReactApplicationContext); + } else { + UIManagerModule nativeModule = + Assertions.assertNotNull(mReactApplicationContext.getNativeModule(UIManagerModule.class)); + eventDispatcher = nativeModule.getEventDispatcher(); + } + return eventDispatcher; + } + // TODO T31905686: eager load Fabric classes, this is temporary and it will be removed // in the near future private static void loadClasses() { EventBeatManager.class.getClass(); EventEmitterWrapper.class.getClass(); FabricEventEmitter.class.getClass(); - BatchMountItem.class.getClass(); - CreateMountItem.class.getClass(); DispatchCommandMountItem.class.getClass(); DispatchIntCommandMountItem.class.getClass(); DispatchStringCommandMountItem.class.getClass(); - InsertMountItem.class.getClass(); MountItem.class.getClass(); PreAllocateViewMountItem.class.getClass(); - RemoveDeleteMultiMountItem.class.getClass(); SendAccessibilityEvent.class.getClass(); - UpdateEventEmitterMountItem.class.getClass(); - UpdateLayoutMountItem.class.getClass(); - UpdatePaddingMountItem.class.getClass(); - UpdatePropsMountItem.class.getClass(); - UpdateStateMountItem.class.getClass(); LayoutMetricsConversions.class.getClass(); MountingManager.class.getClass(); Binding.class.getClass(); @@ -130,5 +131,6 @@ private static void loadClasses() { StateWrapperImpl.class.getClass(); BatchEventDispatchedListener.class.getClass(); ReactNativeConfig.class.getClass(); + IntBufferBatchMountItem.class.getClass(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 740809e39ea0b1..42a5dfa7a86473 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -22,10 +22,11 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Point; import android.os.SystemClock; import android.view.View; +import android.view.accessibility.AccessibilityEvent; import androidx.annotation.AnyThread; -import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; @@ -34,7 +35,9 @@ import com.facebook.debug.tags.ReactDebugOverlayTags; import com.facebook.infer.annotation.ThreadConfined; import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.ReactRootView; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; @@ -50,28 +53,24 @@ import com.facebook.react.bridge.UIManagerListener; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.fabric.events.EventBeatManager; import com.facebook.react.fabric.events.EventEmitterWrapper; import com.facebook.react.fabric.events.FabricEventEmitter; import com.facebook.react.fabric.mounting.MountingManager; -import com.facebook.react.fabric.mounting.mountitems.BatchMountItem; -import com.facebook.react.fabric.mounting.mountitems.CreateMountItem; +import com.facebook.react.fabric.mounting.SurfaceMountingManager; import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchIntCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.DispatchStringCommandMountItem; -import com.facebook.react.fabric.mounting.mountitems.InsertMountItem; +import com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem; import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.fabric.mounting.mountitems.PreAllocateViewMountItem; -import com.facebook.react.fabric.mounting.mountitems.RemoveDeleteMultiMountItem; import com.facebook.react.fabric.mounting.mountitems.SendAccessibilityEvent; -import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdatePaddingMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem; -import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.modules.i18nmanager.I18nUtil; +import com.facebook.react.uimanager.IllegalViewOperationException; +import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactRoot; import com.facebook.react.uimanager.ReactRootViewTagGenerator; import com.facebook.react.uimanager.StateWrapper; @@ -80,22 +79,23 @@ import com.facebook.react.uimanager.ViewManagerPropertyUpdater; import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.text.TextLayoutManager; import com.facebook.systrace.Systrace; -import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArrayList; @SuppressLint("MissingNativeLoadLibrary") public class FabricUIManager implements UIManager, LifecycleEventListener { + public static final String TAG = FabricUIManager.class.getSimpleName(); - public static final String TAG = "FabricUIManager"; // The IS_DEVELOPMENT_ENVIRONMENT variable is used to log extra data when running fabric in a // development environment. DO NOT ENABLE THIS ON PRODUCTION OR YOU WILL BE FIRED! - public static final boolean IS_DEVELOPMENT_ENVIRONMENT = false; + public static final boolean IS_DEVELOPMENT_ENVIRONMENT = false && ReactBuildConfig.DEBUG; public static final boolean ENABLE_FABRIC_LOGS = ReactFeatureFlags.enableFabricLogs || PrinterHolder.getPrinter() @@ -113,44 +113,30 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { @NonNull private final MountingManager mMountingManager; @NonNull private final EventDispatcher mEventDispatcher; - @NonNull - private final ConcurrentHashMap mReactContextForRootTag = - new ConcurrentHashMap<>(); - @NonNull private final EventBeatManager mEventBeatManager; - @NonNull private final Object mViewCommandMountItemsLock = new Object(); - @NonNull private final Object mMountItemsLock = new Object(); - @NonNull private final Object mPreMountItemsLock = new Object(); private boolean mInDispatch = false; private int mReDispatchCounter = 0; - @GuardedBy("mViewCommandMountItemsLock") @NonNull - private List mViewCommandMountItems = new ArrayList<>(); + private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); @NonNull - private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); + private final ConcurrentLinkedQueue mViewCommandMountItemsConcurrent = + new ConcurrentLinkedQueue<>(); - @GuardedBy("mMountItemsLock") @NonNull - private List mMountItems = new ArrayList<>(); + private final ConcurrentLinkedQueue mMountItemsConcurrent = + new ConcurrentLinkedQueue<>(); - @GuardedBy("mPreMountItemsLock") @NonNull - private ArrayDeque mPreMountItems = - new ArrayDeque<>(PRE_MOUNT_ITEMS_INITIAL_SIZE_ARRAY); + private final ConcurrentLinkedQueue mPreMountItemsConcurrent = + new ConcurrentLinkedQueue<>(); @ThreadConfined(UI) @NonNull private final DispatchUIFrameCallback mDispatchUIFrameCallback; - @ThreadConfined(UI) - private int mLastExecutedMountItemSurfaceId = -1; - - @ThreadConfined(UI) - private boolean mLastExecutedMountItemSurfaceIdActive = false; - /** * This is used to keep track of whether or not the FabricUIManager has been destroyed. Once the * Catalyst instance is being destroyed, we should cease all operation here. @@ -190,18 +176,22 @@ public FabricUIManager( @Override @UiThread @ThreadConfined(UI) + @Deprecated public int addRootView( final T rootView, final WritableMap initialProps, final @Nullable String initialUITemplate) { + ReactSoftException.logSoftException( + TAG, + new IllegalViewOperationException( + "Do not call addRootView in Fabric; it is unsupported. Call startSurface instead.")); + final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag(); ReactRoot reactRootView = (ReactRoot) rootView; - // TODO T31905686: Combine with startSurface below ThemedReactContext reactContext = new ThemedReactContext( - mReactApplicationContext, rootView.getContext(), reactRootView.getSurfaceID()); - mMountingManager.addRootView(rootTag, rootView); + mReactApplicationContext, rootView.getContext(), reactRootView.getSurfaceID(), rootTag); + mMountingManager.startSurface(rootTag, rootView, reactContext); String moduleName = reactRootView.getJSModuleName(); - mReactContextForRootTag.put(rootTag, reactContext); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); } @@ -212,6 +202,13 @@ public int addRootView( return rootTag; } + @Override + public void preInitializeViewManagers(List viewManagerNames) { + for (String viewManagerName : viewManagerNames) { + mMountingManager.initializeViewManager(viewManagerName); + } + } + @Override @AnyThread @ThreadConfined(ANY) @@ -224,12 +221,19 @@ public int startSurface( final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag(); Context context = rootView.getContext(); ThemedReactContext reactContext = - new ThemedReactContext(mReactApplicationContext, context, moduleName); + new ThemedReactContext(mReactApplicationContext, context, moduleName, rootTag); if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag); } - mMountingManager.addRootView(rootTag, rootView); - mReactContextForRootTag.put(rootTag, reactContext); + mMountingManager.startSurface(rootTag, rootView, reactContext); + + // If startSurface is executed in the UIThread then, it uses the ViewportOffset from the View, + // Otherwise Fabric relies on calling {@link Binding#setConstraints} method to update the + // ViewportOffset during measurement or onLayout. + @SuppressLint("WrongThread") + Point viewportOffset = + UiThreadUtil.isOnUiThread() ? ReactRootView.getViewportOffset(rootView) : new Point(0, 0); + mBinding.startSurfaceWithConstraints( rootTag, moduleName, @@ -238,6 +242,8 @@ public int startSurface( getMaxSize(widthMeasureSpec), getMinSize(heightMeasureSpec), getMaxSize(heightMeasureSpec), + viewportOffset.x, + viewportOffset.y, I18nUtil.getInstance().isRTL(context), I18nUtil.getInstance().doLeftAndRightSwapInRTL(context)); return rootTag; @@ -254,15 +260,8 @@ public void onRequestEventBeat() { @ThreadConfined(ANY) @Override public void stopSurface(final int surfaceID) { - mReactContextForRootTag.remove(surfaceID); mBinding.stopSurface(surfaceID); - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - mMountingManager.deleteRootView(surfaceID); - } - }); + mMountingManager.stopSurface(surfaceID); } @Override @@ -323,117 +322,35 @@ private void preallocateView( @Nullable Object stateWrapper, boolean isLayoutable) { - // This could be null if teardown/navigation away from a surface on the main thread happens - // while a commit is being processed in a different thread. By contract we expect this to be - // possible at teardown, but this race should *never* happen at startup. - @Nullable ThemedReactContext context = mReactContextForRootTag.get(rootTag); - - String component = getFabricComponentName(componentName); - synchronized (mPreMountItemsLock) { - mPreMountItems.add( - new PreAllocateViewMountItem( - context, - rootTag, - reactTag, - component, - props, - (StateWrapper) stateWrapper, - isLayoutable)); - } - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem createMountItem( - String componentName, - @Nullable ReadableMap props, - @Nullable Object stateWrapper, - int reactRootTag, - int reactTag, - boolean isLayoutable) { - String component = getFabricComponentName(componentName); - - // This could be null if teardown/navigation away from a surface on the main thread happens - // while a commit is being processed in a different thread. By contract we expect this to be - // possible at teardown, but this race should *never* happen at startup. - @Nullable ThemedReactContext reactContext = mReactContextForRootTag.get(reactRootTag); - - return new CreateMountItem( - reactContext, - reactRootTag, - reactTag, - component, - props, - (StateWrapper) stateWrapper, - isLayoutable); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem insertMountItem(int reactTag, int parentReactTag, int index) { - return new InsertMountItem(reactTag, parentReactTag, index); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem removeDeleteMultiMountItem(int[] metadata) { - return new RemoveDeleteMultiMountItem(metadata); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem updateLayoutMountItem( - int reactTag, int x, int y, int width, int height, int layoutDirection) { - return new UpdateLayoutMountItem(reactTag, x, y, width, height, layoutDirection); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem updatePaddingMountItem(int reactTag, int left, int top, int right, int bottom) { - return new UpdatePaddingMountItem(reactTag, left, top, right, bottom); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem updatePropsMountItem(int reactTag, ReadableMap map) { - return new UpdatePropsMountItem(reactTag, map); - } - - @DoNotStrip - @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem updateStateMountItem(int reactTag, @Nullable Object stateWrapper) { - return new UpdateStateMountItem(reactTag, (StateWrapper) stateWrapper); + addPreAllocateMountItem( + new PreAllocateViewMountItem( + rootTag, + reactTag, + getFabricComponentName(componentName), + props, + (StateWrapper) stateWrapper, + isLayoutable)); } @DoNotStrip @SuppressWarnings("unused") @AnyThread @ThreadConfined(ANY) - private MountItem updateEventEmitterMountItem(int reactTag, Object eventEmitter) { - return new UpdateEventEmitterMountItem(reactTag, (EventEmitterWrapper) eventEmitter); + private MountItem createIntBufferBatchMountItem( + int rootTag, int[] intBuffer, Object[] objBuffer, int commitNumber) { + return new IntBufferBatchMountItem(rootTag, intBuffer, objBuffer, commitNumber); } @DoNotStrip @SuppressWarnings("unused") - @AnyThread - @ThreadConfined(ANY) - private MountItem createBatchMountItem( - int rootTag, MountItem[] items, int size, int commitNumber) { - return new BatchMountItem(rootTag, items, size, commitNumber); + private NativeArray measureLines( + ReadableMap attributedString, ReadableMap paragraphAttributes, float width, float height) { + return (NativeArray) + TextLayoutManager.measureLines( + mReactApplicationContext, + attributedString, + paragraphAttributes, + PixelUtil.toPixelFromDIP(width)); } @DoNotStrip @@ -464,7 +381,7 @@ private long measure( @DoNotStrip @SuppressWarnings("unused") private long measure( - int rootTag, + int surfaceId, String componentName, ReadableMap localData, ReadableMap props, @@ -475,16 +392,16 @@ private long measure( float maxHeight, @Nullable float[] attachmentsPositions) { - // This could be null if teardown/navigation away from a surface on the main thread happens - // while a commit is being processed in a different thread. By contract we expect this to be - // possible at teardown, but this race should *never* happen at startup. - @Nullable - ReactContext context = - rootTag < 0 ? mReactApplicationContext : mReactContextForRootTag.get(rootTag); - - // Don't both measuring if we can't get a context. - if (context == null) { - return 0; + ReactContext context; + if (surfaceId > 0) { + SurfaceMountingManager surfaceMountingManager = + mMountingManager.getSurfaceManagerEnforced(surfaceId, "measure"); + if (surfaceMountingManager.isStopped()) { + return 0; + } + context = surfaceMountingManager.getContext(); + } else { + context = mReactApplicationContext; } return mMountingManager.measure( @@ -501,22 +418,16 @@ private long measure( } /** - * @param surfaceID {@link int} surface ID + * @param surfaceId {@link int} surface ID * @param defaultTextInputPadding {@link float[]} output parameter will contain the default theme * padding used by RN Android TextInput. * @return if theme data is available in the output parameters. */ @DoNotStrip - public boolean getThemeData(int surfaceID, float[] defaultTextInputPadding) { - ThemedReactContext themedReactContext = mReactContextForRootTag.get(surfaceID); - if (themedReactContext == null) { - // TODO T68526882: Review if this should cause a crash instead. - ReactSoftException.logSoftException( - TAG, - new ReactNoCrashSoftException( - "Unable to find ThemedReactContext associated to surfaceID: " + surfaceID)); - return false; - } + public boolean getThemeData(int surfaceId, float[] defaultTextInputPadding) { + SurfaceMountingManager surfaceMountingManager = + mMountingManager.getSurfaceManagerEnforced(surfaceId, "getThemeData"); + ThemedReactContext themedReactContext = surfaceMountingManager.getContext(); float[] defaultTextInputPaddingForTheme = UIManagerHelper.getDefaultTextInputPadding(themedReactContext); defaultTextInputPadding[0] = defaultTextInputPaddingForTheme[PADDING_START_INDEX]; @@ -529,37 +440,78 @@ public boolean getThemeData(int surfaceID, float[] defaultTextInputPadding) { @Override @UiThread @ThreadConfined(UI) - public void synchronouslyUpdateViewOnUIThread(int reactTag, @NonNull ReadableMap props) { + public void synchronouslyUpdateViewOnUIThread( + final int reactTag, @NonNull final ReadableMap props) { UiThreadUtil.assertOnUiThread(); int commitNumber = mCurrentSynchronousCommitNumber++; - // We are on the UI thread so this is safe to call. We try to flush any existing - // mount instructions that are queued. - tryDispatchMountItems(); + // We are on the UI thread so it would otherwise be safe to call `tryDispatchMountItems` here to + // flush previously-queued mountitems, *BUT* we don't know where we are on the callstack. + // Why isn't it safe, and why do we have additional safeguards here? + // + // A tangible example where it would cause a crash, and did in the past: + // 1. There are queued "delete" mutations + // 2. We're called by this stack trace: + // FabricUIManager.synchronouslyUpdateViewOnUIThread(FabricUIManager.java:574) + // PropsAnimatedNode.updateView(PropsAnimatedNode.java:114) + // NativeAnimatedNodesManager.updateNodes(NativeAnimatedNodesManager.java:655) + // NativeAnimatedNodesManager.handleEvent(NativeAnimatedNodesManager.java:521) + // NativeAnimatedNodesManager.onEventDispatch(NativeAnimatedNodesManager.java:483) + // EventDispatcherImpl.dispatchEvent(EventDispatcherImpl.java:116) + // ReactScrollViewHelper.emitScrollEvent(ReactScrollViewHelper.java:85) + // ReactScrollViewHelper.emitScrollEvent(ReactScrollViewHelper.java:46) + // ReactScrollView.onScrollChanged(ReactScrollView.java:285) + // ReactScrollView.onOverScrolled(ReactScrollView.java:808) + // android.view.View.overScrollBy(View.java:26052) + // android.widget.ScrollView.overScrollBy(ScrollView.java:2040) + // android.widget.ScrollView.computeScroll(ScrollView.java:1481) + // android.view.View.updateDisplayListIfDirty(View.java:20466) + // 3. A view is deleted while its parent is being drawn, causing a crash. + + MountItem synchronousMountItem = + new MountItem() { + @Override + public void execute(@NonNull MountingManager mountingManager) { + try { + mountingManager.updateProps(reactTag, props); + } catch (Exception ex) { + // TODO T42943890: Fix animations in Fabric and remove this try/catch + ReactSoftException.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Caught exception in synchronouslyUpdateViewOnUIThread", ex)); + } + } - try { - ReactMarker.logFabricMarker( - ReactMarkerConstants.FABRIC_UPDATE_UI_MAIN_THREAD_START, null, commitNumber); - if (ENABLE_FABRIC_LOGS) { - FLog.d( - TAG, - "SynchronouslyUpdateViewOnUIThread for tag %d: %s", - reactTag, - (IS_DEVELOPMENT_ENVIRONMENT ? props.toHashMap().toString() : "")); - } + @Override + public int getSurfaceId() { + return View.NO_ID; + } + }; - updatePropsMountItem(reactTag, props).execute(mMountingManager); - } catch (Exception ex) { - // TODO T42943890: Fix animations in Fabric and remove this try/catch - ReactSoftException.logSoftException( + // If the reactTag exists, we assume that it might at the end of the next + // batch of MountItems. Otherwise, we try to execute immediately. + if (!mMountingManager.getViewExists(reactTag)) { + addMountItem(synchronousMountItem); + return; + } + + ReactMarker.logFabricMarker( + ReactMarkerConstants.FABRIC_UPDATE_UI_MAIN_THREAD_START, null, commitNumber); + + if (ENABLE_FABRIC_LOGS) { + FLog.d( TAG, - new ReactNoCrashSoftException( - "Caught exception in synchronouslyUpdateViewOnUIThread", ex)); - } finally { - ReactMarker.logFabricMarker( - ReactMarkerConstants.FABRIC_UPDATE_UI_MAIN_THREAD_END, null, commitNumber); + "SynchronouslyUpdateViewOnUIThread for tag %d: %s", + reactTag, + (IS_DEVELOPMENT_ENVIRONMENT ? props.toHashMap().toString() : "")); } + + synchronousMountItem.execute(mMountingManager); + + ReactMarker.logFabricMarker( + ReactMarkerConstants.FABRIC_UPDATE_UI_MAIN_THREAD_END, null, commitNumber); } public void addUIManagerEventListener(UIManagerListener listener) { @@ -580,7 +532,7 @@ public void removeUIManagerEventListener(UIManagerListener listener) { @AnyThread @ThreadConfined(ANY) private void scheduleMountItem( - @NonNull final MountItem mountItem, + @Nullable final MountItem mountItem, int commitNumber, long commitStartTime, long diffStartTime, @@ -592,8 +544,10 @@ private void scheduleMountItem( // When Binding.cpp calls scheduleMountItems during a commit phase, it always calls with // a BatchMountItem. No other sites call into this with a BatchMountItem, and Binding.cpp only // calls scheduleMountItems with a BatchMountItem. - boolean isBatchMountItem = mountItem instanceof BatchMountItem; - boolean shouldSchedule = !(isBatchMountItem && ((BatchMountItem) mountItem).getSize() == 0); + boolean isBatchMountItem = mountItem instanceof IntBufferBatchMountItem; + boolean shouldSchedule = + (isBatchMountItem && ((IntBufferBatchMountItem) mountItem).shouldSchedule()) + || (!isBatchMountItem && mountItem != null); // In case of sync rendering, this could be called on the UI thread. Otherwise, // it should ~always be called on the JS thread. @@ -610,10 +564,7 @@ private void scheduleMountItem( } if (shouldSchedule) { - synchronized (mMountItemsLock) { - mMountItems.add(mountItem); - } - + addMountItem(mountItem); if (UiThreadUtil.isOnUiThread()) { // We only read these flags on the UI thread. tryDispatchMountItems(); @@ -646,9 +597,16 @@ private void scheduleMountItem( } } + /** + * Try to dispatch MountItems. Returns true if any items were dispatched, false otherwise. A + * `false` return value doesn't indicate errors, it may just indicate there was no work to be + * done. + * + * @return + */ @UiThread @ThreadConfined(UI) - private void tryDispatchMountItems() { + private boolean tryDispatchMountItems() { // If we're already dispatching, don't reenter. // Reentrance can potentially happen a lot on Android in Fabric because // `updateState` from the @@ -658,7 +616,7 @@ private void tryDispatchMountItems() { // This is a pretty blunt tool, but we might not have better options since we really don't want // to execute anything out-of-order. if (mInDispatch) { - return; + return false; } final boolean didDispatchItems; @@ -666,7 +624,6 @@ private void tryDispatchMountItems() { didDispatchItems = dispatchMountItems(); } catch (Throwable e) { mReDispatchCounter = 0; - mLastExecutedMountItemSurfaceId = -1; throw e; } finally { // Clean up after running dispatchMountItems - even if an exception was thrown @@ -693,76 +650,38 @@ private void tryDispatchMountItems() { tryDispatchMountItems(); } mReDispatchCounter = 0; - mLastExecutedMountItemSurfaceId = -1; + return didDispatchItems; } - @UiThread - @ThreadConfined(UI) - private List getAndResetViewCommandMountItems() { - synchronized (mViewCommandMountItemsLock) { - List result = mViewCommandMountItems; - if (result.isEmpty()) { - return null; + @Nullable + private List drainConcurrentItemQueue(ConcurrentLinkedQueue queue) { + List result = new ArrayList<>(); + while (!queue.isEmpty()) { + E item = queue.poll(); + if (item != null) { + result.add(item); } - mViewCommandMountItems = new ArrayList<>(); - return result; } + if (result.size() == 0) { + return null; + } + return result; } @UiThread @ThreadConfined(UI) - private List getAndResetMountItems() { - synchronized (mMountItemsLock) { - List result = mMountItems; - if (result.isEmpty()) { - return null; - } - mMountItems = new ArrayList<>(); - return result; - } - } - - private ArrayDeque getAndResetPreMountItems() { - synchronized (mPreMountItemsLock) { - ArrayDeque result = mPreMountItems; - if (result.isEmpty()) { - return null; - } - mPreMountItems = new ArrayDeque<>(PRE_MOUNT_ITEMS_INITIAL_SIZE_ARRAY); - return result; - } + private List getAndResetViewCommandMountItems() { + return drainConcurrentItemQueue(mViewCommandMountItemsConcurrent); } - /** - * Check if a surfaceId is active and ready for MountItems to be executed against it. It is safe - * and cheap to call this repeatedly because we expect many operations to be batched with the same - * surfaceId in a row and we memoize the parameters and results. - * - * @param surfaceId - * @param context - * @return - */ @UiThread @ThreadConfined(UI) - private boolean surfaceActiveForExecution(int surfaceId, String context) { - if (mLastExecutedMountItemSurfaceId != surfaceId) { - mLastExecutedMountItemSurfaceId = surfaceId; - mLastExecutedMountItemSurfaceIdActive = mReactContextForRootTag.get(surfaceId) != null; - - // If there are many MountItems with the same SurfaceId, we only - // log a warning for the first one that is skipped. - if (!mLastExecutedMountItemSurfaceIdActive) { - ReactSoftException.logSoftException( - TAG, - new ReactNoCrashSoftException( - "dispatchMountItems: skipping " - + context - + ", because surface not available: " - + surfaceId)); - } - } + private List getAndResetMountItems() { + return drainConcurrentItemQueue(mMountItemsConcurrent); + } - return mLastExecutedMountItemSurfaceIdActive; + private Collection getAndResetPreMountItems() { + return drainConcurrentItemQueue(mPreMountItemsConcurrent); } private static void printMountItem(MountItem mountItem, String prefix) { @@ -845,20 +764,16 @@ private boolean dispatchMountItems() { // If there are MountItems to dispatch, we make sure all the "pre mount items" are executed // first - ArrayDeque mPreMountItemsToDispatch = getAndResetPreMountItems(); + Collection preMountItemsToDispatch = getAndResetPreMountItems(); - if (mPreMountItemsToDispatch != null) { + if (preMountItemsToDispatch != null) { Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricUIManager::mountViews preMountItems to execute: " - + mPreMountItemsToDispatch.size()); + + preMountItemsToDispatch.size()); - while (!mPreMountItemsToDispatch.isEmpty()) { - PreAllocateViewMountItem mountItem = mPreMountItemsToDispatch.pollFirst(); - if (surfaceActiveForExecution( - mountItem.getRootTag(), "dispatchMountItems PreAllocateViewMountItem")) { - mountItem.execute(mMountingManager); - } + for (PreAllocateViewMountItem preMountItem : preMountItemsToDispatch) { + preMountItem.execute(mMountingManager); } Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); @@ -877,16 +792,6 @@ private boolean dispatchMountItems() { } try { - // Make sure surface associated with this MountItem has been started, and not stopped. - // TODO T68118357: clean up this logic and simplify this method overall - if (mountItem instanceof BatchMountItem) { - BatchMountItem batchMountItem = (BatchMountItem) mountItem; - if (!surfaceActiveForExecution( - batchMountItem.getRootTag(), "dispatchMountItems BatchMountItem")) { - continue; - } - } - mountItem.execute(mMountingManager); } catch (Throwable e) { // If there's an exception, we want to log diagnostics in prod and rethrow. @@ -909,6 +814,17 @@ private boolean dispatchMountItems() { return true; } + /** + * Detect if we still have processing time left in this frame. + * + * @param frameTimeNanos + * @return + */ + private boolean haveExceededNonBatchedFrameTime(long frameTimeNanos) { + long timeLeftInFrame = FRAME_TIME_MS - ((System.nanoTime() - frameTimeNanos) / 1000000); + return timeLeftInFrame < MAX_TIME_IN_FRAME_FOR_NON_BATCHED_OPERATIONS_MS; + } + @UiThread @ThreadConfined(UI) private void dispatchPreMountItems(long frameTimeNanos) { @@ -920,27 +836,21 @@ private void dispatchPreMountItems(long frameTimeNanos) { try { while (true) { - long timeLeftInFrame = FRAME_TIME_MS - ((System.nanoTime() - frameTimeNanos) / 1000000); - if (timeLeftInFrame < MAX_TIME_IN_FRAME_FOR_NON_BATCHED_OPERATIONS_MS) { + if (haveExceededNonBatchedFrameTime(frameTimeNanos)) { break; } - PreAllocateViewMountItem preMountItemToDispatch; - synchronized (mPreMountItemsLock) { - if (mPreMountItems.isEmpty()) { - break; - } - preMountItemToDispatch = mPreMountItems.pollFirst(); - } + PreAllocateViewMountItem preMountItemToDispatch = mPreMountItemsConcurrent.poll(); - if (surfaceActiveForExecution( - preMountItemToDispatch.getRootTag(), "dispatchPreMountItems")) { - preMountItemToDispatch.execute(mMountingManager); + // If list is empty, `poll` will return null, or var will never be set + if (preMountItemToDispatch == null) { + break; } + + preMountItemToDispatch.execute(mMountingManager); } } finally { mInDispatch = false; - mLastExecutedMountItemSurfaceId = -1; } Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); @@ -957,13 +867,28 @@ public void setBinding(Binding binding) { @UiThread @ThreadConfined(UI) public void updateRootLayoutSpecs( - final int rootTag, final int widthMeasureSpec, final int heightMeasureSpec) { + final int surfaceId, + final int widthMeasureSpec, + final int heightMeasureSpec, + final int offsetX, + final int offsetY) { if (ENABLE_FABRIC_LOGS) { - FLog.d(TAG, "Updating Root Layout Specs"); + FLog.d(TAG, "Updating Root Layout Specs for [%d]", surfaceId); + } + + SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId); + + // TODO T83615646: make this a hard-crash in the future. + if (surfaceMountingManager == null) { + ReactSoftException.logSoftException( + TAG, + new IllegalViewOperationException( + "Cannot updateRootLayoutSpecs on surfaceId that does not exist: " + surfaceId)); + return; } - ThemedReactContext reactContext = mReactContextForRootTag.get(rootTag); + ThemedReactContext reactContext = surfaceMountingManager.getContext(); boolean isRTL = false; boolean doLeftAndRightSwapInRTL = false; if (reactContext != null) { @@ -972,18 +897,31 @@ public void updateRootLayoutSpecs( } mBinding.setConstraints( - rootTag, + surfaceId, getMinSize(widthMeasureSpec), getMaxSize(widthMeasureSpec), getMinSize(heightMeasureSpec), getMaxSize(heightMeasureSpec), + offsetX, + offsetY, isRTL, doLeftAndRightSwapInRTL); } @Override public void receiveEvent(int reactTag, String eventName, @Nullable WritableMap params) { - EventEmitterWrapper eventEmitter = mMountingManager.getEventEmitter(reactTag); + receiveEvent(View.NO_ID, reactTag, eventName, params); + } + + @Override + public void receiveEvent( + int surfaceId, int reactTag, String eventName, @Nullable WritableMap params) { + if (ReactBuildConfig.DEBUG && surfaceId == View.NO_ID) { + FLog.d(TAG, "Emitted event without surfaceId: [%d] %s", reactTag, eventName); + } + + EventEmitterWrapper eventEmitter = mMountingManager.getEventEmitter(surfaceId, reactTag); + if (eventEmitter == null) { // This can happen if the view has disappeared from the screen (because of async events) FLog.d(TAG, "Unable to invoke event: " + eventName + " for reactTag: " + reactTag); @@ -1015,38 +953,81 @@ public void onHostPause() { @Override public void onHostDestroy() {} - @Deprecated @Override + @Deprecated @AnyThread @ThreadConfined(ANY) public void dispatchCommand( final int reactTag, final int commandId, @Nullable final ReadableArray commandArgs) { - dispatchCommandMountItem(new DispatchIntCommandMountItem(reactTag, commandId, commandArgs)); + throw new UnsupportedOperationException( + "dispatchCommand called without surfaceId - Fabric dispatchCommand must be called through Fabric JSI API"); } @Override + @Deprecated @AnyThread @ThreadConfined(ANY) public void dispatchCommand( final int reactTag, final String commandId, @Nullable final ReadableArray commandArgs) { - dispatchCommandMountItem(new DispatchStringCommandMountItem(reactTag, commandId, commandArgs)); + throw new UnsupportedOperationException( + "dispatchCommand called without surfaceId - Fabric dispatchCommand must be called through Fabric JSI API"); + } + + @Deprecated + @AnyThread + @ThreadConfined(ANY) + public void dispatchCommand( + final int surfaceId, + final int reactTag, + final int commandId, + @Nullable final ReadableArray commandArgs) { + dispatchCommandMountItem( + new DispatchIntCommandMountItem(surfaceId, reactTag, commandId, commandArgs)); + } + + @DoNotStrip + @AnyThread + @ThreadConfined(ANY) + public void dispatchCommand( + final int surfaceId, + final int reactTag, + final String commandId, + @Nullable final ReadableArray commandArgs) { + dispatchCommandMountItem( + new DispatchStringCommandMountItem(surfaceId, reactTag, commandId, commandArgs)); } @AnyThread @ThreadConfined(ANY) private void dispatchCommandMountItem(DispatchCommandMountItem command) { - synchronized (mViewCommandMountItemsLock) { - mViewCommandMountItems.add(command); - } + addViewCommandMountItem(command); } @Override @AnyThread @ThreadConfined(ANY) public void sendAccessibilityEvent(int reactTag, int eventType) { - synchronized (mMountItemsLock) { - mMountItems.add(new SendAccessibilityEvent(reactTag, eventType)); + // Can be called from native, not just JS - we need to migrate the native callsites + // before removing this entirely. + addMountItem(new SendAccessibilityEvent(View.NO_ID, reactTag, eventType)); + } + + @DoNotStrip + @AnyThread + @ThreadConfined(ANY) + public void sendAccessibilityEventFromJS(int surfaceId, int reactTag, String eventTypeJS) { + int eventType; + if ("focus".equals(eventTypeJS)) { + eventType = AccessibilityEvent.TYPE_VIEW_FOCUSED; + } else if ("windowStateChange".equals(eventTypeJS)) { + eventType = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; + } else if ("click".equals(eventTypeJS)) { + eventType = AccessibilityEvent.TYPE_VIEW_CLICKED; + } else { + throw new IllegalArgumentException( + "sendAccessibilityEventFromJS: invalid eventType " + eventTypeJS); } + addMountItem(new SendAccessibilityEvent(surfaceId, reactTag, eventType)); } /** @@ -1058,16 +1039,23 @@ public void sendAccessibilityEvent(int reactTag, int eventType) { */ @DoNotStrip public void setJSResponder( - final int reactTag, final int initialReactTag, final boolean blockNativeResponder) { - synchronized (mMountItemsLock) { - mMountItems.add( - new MountItem() { - @Override - public void execute(MountingManager mountingManager) { - mountingManager.setJSResponder(reactTag, initialReactTag, blockNativeResponder); - } - }); - } + final int surfaceId, + final int reactTag, + final int initialReactTag, + final boolean blockNativeResponder) { + addMountItem( + new MountItem() { + @Override + public void execute(MountingManager mountingManager) { + mountingManager.setJSResponder( + surfaceId, reactTag, initialReactTag, blockNativeResponder); + } + + @Override + public int getSurfaceId() { + return surfaceId; + } + }); } /** @@ -1076,15 +1064,18 @@ public void execute(MountingManager mountingManager) { */ @DoNotStrip public void clearJSResponder() { - synchronized (mMountItemsLock) { - mMountItems.add( - new MountItem() { - @Override - public void execute(MountingManager mountingManager) { - mountingManager.clearJSResponder(); - } - }); - } + addMountItem( + new MountItem() { + @Override + public void execute(MountingManager mountingManager) { + mountingManager.clearJSResponder(); + } + + @Override + public int getSurfaceId() { + return View.NO_ID; + } + }); } @Override @@ -1132,6 +1123,29 @@ public Map getPerformanceCounters() { return performanceCounters; } + private void addMountItem(MountItem mountItem) { + mMountItemsConcurrent.add(mountItem); + } + + private void addPreAllocateMountItem(PreAllocateViewMountItem mountItem) { + // We do this check only for PreAllocateViewMountItem - and not DispatchMountItem or regular + // MountItem - because PreAllocateViewMountItem is not batched, and is relatively more expensive + // both to queue, to drain, and to execute. + if (!mMountingManager.surfaceIsStopped(mountItem.getSurfaceId())) { + mPreMountItemsConcurrent.add(mountItem); + } else if (IS_DEVELOPMENT_ENVIRONMENT) { + FLog.e( + TAG, + "Not queueing PreAllocateMountItem: surfaceId stopped: [%d] - %s", + mountItem.getSurfaceId(), + mountItem.toString()); + } + } + + private void addViewCommandMountItem(DispatchCommandMountItem mountItem) { + mViewCommandMountItemsConcurrent.add(mountItem); + } + private class DispatchUIFrameCallback extends GuardedFrameCallback { private volatile boolean mIsMountingEnabled = true; @@ -1164,7 +1178,6 @@ public void doFrameGuarded(long frameTimeNanos) { try { dispatchPreMountItems(frameTimeNanos); - tryDispatchMountItems(); } catch (Exception ex) { FLog.e(TAG, "Exception thrown when executing UIFrameGuarded", ex); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/StateWrapperImpl.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/StateWrapperImpl.java index 6a461623e99aca..2d96776f882ea0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/StateWrapperImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/StateWrapperImpl.java @@ -8,13 +8,11 @@ package com.facebook.react.fabric; import android.annotation.SuppressLint; -import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.ReadableNativeMap; -import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.StateWrapper; @@ -30,9 +28,6 @@ public class StateWrapperImpl implements StateWrapper { @DoNotStrip private final HybridData mHybridData; - private Runnable mFailureCallback = null; - private int mUpdateStateId = 0; - private static native HybridData initHybrid(); private StateWrapperImpl() { @@ -44,29 +39,8 @@ private StateWrapperImpl() { public native void updateStateImpl(@NonNull NativeMap map); - public native void updateStateWithFailureCallbackImpl( - @NonNull NativeMap map, Object self, int updateStateId); - @Override - public void updateState(@NonNull WritableMap map, Runnable failureCallback) { - mUpdateStateId++; - mFailureCallback = failureCallback; - updateStateWithFailureCallbackImpl((NativeMap) map, this, mUpdateStateId); - } - - @DoNotStrip - @AnyThread - public void updateStateFailed(int callbackRefId) { - // If the callback ref ID doesn't match the ID of the most-recent updateState call, - // then it's an outdated failure callback and we ignore it. - if (callbackRefId != mUpdateStateId) { - return; - } - - final Runnable failureCallback = mFailureCallback; - mFailureCallback = null; - if (failureCallback != null) { - UiThreadUtil.runOnUiThread(failureCallback); - } + public void updateState(@NonNull WritableMap map) { + updateStateImpl((NativeMap) map); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java index 6b9578b442c1d3..f0856af612e9a8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java @@ -9,6 +9,7 @@ import static com.facebook.react.uimanager.events.TouchesHelper.CHANGED_TOUCHES_KEY; import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_KEY; +import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_SURFACE_KEY; import static com.facebook.react.uimanager.events.TouchesHelper.TOP_TOUCH_CANCEL_KEY; import static com.facebook.react.uimanager.events.TouchesHelper.TOP_TOUCH_END_KEY; import static com.facebook.react.uimanager.events.TouchesHelper.TOUCHES_KEY; @@ -23,12 +24,12 @@ import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.fabric.FabricUIManager; -import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.facebook.react.uimanager.events.RCTModernEventEmitter; import com.facebook.systrace.Systrace; import java.util.HashSet; import java.util.Set; -public class FabricEventEmitter implements RCTEventEmitter { +public class FabricEventEmitter implements RCTModernEventEmitter { private static final String TAG = "FabricEventEmitter"; @@ -40,10 +41,16 @@ public FabricEventEmitter(@NonNull FabricUIManager uiManager) { @Override public void receiveEvent(int reactTag, @NonNull String eventName, @Nullable WritableMap params) { + receiveEvent(-1, reactTag, eventName, params); + } + + @Override + public void receiveEvent( + int surfaceId, int reactTag, String eventName, @Nullable WritableMap params) { Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "FabricEventEmitter.receiveEvent('" + eventName + "')"); - mUIManager.receiveEvent(reactTag, eventName, params); + mUIManager.receiveEvent(surfaceId, reactTag, eventName, params); Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } @@ -70,14 +77,15 @@ public void receiveTouches( touch.putArray(TOUCHES_KEY, copyWritableArray(touches)); WritableMap nativeEvent = touch; int rootNodeID = 0; - int target = nativeEvent.getInt(TARGET_KEY); - if (target < 1) { + int targetSurfaceId = nativeEvent.getInt(TARGET_SURFACE_KEY); + int targetReactTag = nativeEvent.getInt(TARGET_KEY); + if (targetReactTag < 1) { FLog.e(TAG, "A view is reporting that a touch occurred on tag zero."); } else { - rootNodeID = target; + rootNodeID = targetReactTag; } - receiveEvent(rootNodeID, eventTopLevelType, touch); + receiveEvent(targetSurfaceId, rootNodeID, eventTopLevelType, touch); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk index 593a8cf30815b3..793daed7427978 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk @@ -11,7 +11,7 @@ LOCAL_MODULE := fabricjni LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) -LOCAL_SHARED_LIBRARIES := libreactconfig libreact_render_components_slider libreact_render_components_progressbar libreact_render_components_switch libreact_render_components_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core libreact_render_mapbuffer react_render_componentregistry libreact_render_components_view libreact_render_components_unimplementedview libreact_render_components_root libreact_render_components_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_render_viewmanagers react_render_components_text libreact_render_components_image react_render_components_textinput react_render_components_picker +LOCAL_SHARED_LIBRARIES := libreactconfig libreact_render_components_slider libreact_render_components_progressbar libreact_render_components_switch libreact_render_components_modal libyoga libglog libfb libfbjni libglog_init libfolly_json libfolly_futures libreact_render_mounting libreactnativeutilsjni libreact_utils libreact_render_debug libreact_render_graphics libreact_render_core libreact_render_mapbuffer react_render_componentregistry libreact_render_components_view libreact_render_components_unimplementedview libreact_render_components_root libreact_render_components_scrollview libbetter libreact_render_attributedstring libreact_render_uimanager libreact_render_templateprocessor libreact_render_scheduler libreact_render_animations libreact_render_imagemanager libreact_render_textlayoutmanager libreact_codegen_rncore react_render_components_text libreact_render_components_image react_render_components_textinput react_render_components_picker LOCAL_STATIC_LIBRARIES := @@ -60,5 +60,3 @@ $(call import-module,react/renderer/scheduler) $(call import-module,react/renderer/templateprocessor) $(call import-module,react/renderer/textlayoutmanager) $(call import-module,react/renderer/uimanager) - -# $(call import-module,react/fabric/viewmanagers/jni) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK index 0d6dd21aaaaef3..8f9d8e9e4793b3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK @@ -27,7 +27,6 @@ rn_xplat_cxx_library( soname = "libfabricjni.$(ext)", visibility = ["PUBLIC"], deps = [ - react_native_xplat_target("better:better"), react_native_xplat_target("react/config:config"), react_native_xplat_target("react/renderer/animations:animations"), react_native_xplat_target("react/renderer/uimanager:uimanager"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index 0764559764f5cd..181250e0cd9f53 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -11,7 +11,6 @@ #include "ReactNativeConfigHolder.h" #include "StateWrapperImpl.h" -#include #include #include #include @@ -53,6 +52,173 @@ struct RemoveDeleteMetadata { } // namespace +CppMountItem CppMountItem::CreateMountItem(ShadowView shadowView) { + return {CppMountItem::Type::Create, {}, {}, shadowView, -1}; +} +CppMountItem CppMountItem::DeleteMountItem(ShadowView shadowView) { + return {CppMountItem::Type::Delete, {}, shadowView, {}, -1}; +} +CppMountItem CppMountItem::InsertMountItem( + ShadowView parentView, + ShadowView shadowView, + int index) { + return {CppMountItem::Type::Insert, parentView, {}, shadowView, index}; +} +CppMountItem CppMountItem::RemoveMountItem( + ShadowView parentView, + ShadowView shadowView, + int index) { + return {CppMountItem::Type::Remove, parentView, shadowView, {}, index}; +} +CppMountItem CppMountItem::UpdatePropsMountItem(ShadowView shadowView) { + return {CppMountItem::Type::UpdateProps, {}, {}, shadowView, -1}; +} +CppMountItem CppMountItem::UpdateStateMountItem(ShadowView shadowView) { + return {CppMountItem::Type::UpdateState, {}, {}, shadowView, -1}; +} +CppMountItem CppMountItem::UpdateLayoutMountItem(ShadowView shadowView) { + return {CppMountItem::Type::UpdateLayout, {}, {}, shadowView, -1}; +} +CppMountItem CppMountItem::UpdateEventEmitterMountItem(ShadowView shadowView) { + return {CppMountItem::Type::UpdateEventEmitter, {}, {}, shadowView, -1}; +} +CppMountItem CppMountItem::UpdatePaddingMountItem(ShadowView shadowView) { + return {CppMountItem::Type::UpdatePadding, {}, {}, shadowView, -1}; +} + +static inline int getIntBufferSizeForType(CppMountItem::Type mountItemType) { + if (mountItemType == CppMountItem::Type::Create) { + return 2; // tag, isLayoutable + } else if (mountItemType == CppMountItem::Type::Insert) { + return 3; // tag, parentTag, index + } else if (mountItemType == CppMountItem::Type::Remove) { + return 3; // tag, parentTag, index + } else if (mountItemType == CppMountItem::Type::Delete) { + return 1; // tag + } else if (mountItemType == CppMountItem::Type::UpdateProps) { + return 1; // tag + } else if (mountItemType == CppMountItem::Type::UpdateState) { + return 1; // tag + } else if (mountItemType == CppMountItem::Type::UpdatePadding) { + return 5; // tag, top, left, bottom, right + } else if (mountItemType == CppMountItem::Type::UpdateLayout) { + return 7; // tag, x, y, w, h, layoutDirection, DisplayType + } else if (mountItemType == CppMountItem::Type::UpdateEventEmitter) { + return 1; // tag + } else { + return -1; + } +} + +static inline void updateBufferSizes( + CppMountItem::Type mountItemType, + int numInstructions, + int &batchMountItemIntsSize, + int &batchMountItemObjectsSize) { + if (numInstructions == 0) { + return; + } + + batchMountItemIntsSize += + numInstructions == 1 ? 1 : 2; // instructionType[, numInstructions] + batchMountItemIntsSize += + numInstructions * getIntBufferSizeForType(mountItemType); + + if (mountItemType == CppMountItem::Type::UpdateProps) { + batchMountItemObjectsSize += + numInstructions; // props object * numInstructions + } else if (mountItemType == CppMountItem::Type::UpdateState) { + batchMountItemObjectsSize += + numInstructions; // state object * numInstructions + } else if (mountItemType == CppMountItem::Type::UpdateEventEmitter) { + batchMountItemObjectsSize += + numInstructions; // EventEmitter object * numInstructions + } +} + +static inline void computeBufferSizes( + int &batchMountItemIntsSize, + int &batchMountItemObjectsSize, + std::vector &cppCommonMountItems, + std::vector &cppDeleteMountItems, + std::vector &cppUpdatePropsMountItems, + std::vector &cppUpdateStateMountItems, + std::vector &cppUpdatePaddingMountItems, + std::vector &cppUpdateLayoutMountItems, + std::vector &cppUpdateEventEmitterMountItems) { + CppMountItem::Type lastType = CppMountItem::Type::Undefined; + int numSameType = 0; + for (const auto &mountItem : cppCommonMountItems) { + const auto &mountItemType = mountItem.type; + + if (lastType == mountItemType) { + numSameType++; + if (numSameType == 2) { + batchMountItemIntsSize += 1; // numInstructions + } + } else { + numSameType = 1; + lastType = mountItemType; + batchMountItemIntsSize += 1; // instructionType + } + + batchMountItemIntsSize += getIntBufferSizeForType(mountItemType); + if (mountItemType == CppMountItem::Type::Create) { + batchMountItemObjectsSize += 3; // component name, props, state + } + } + + updateBufferSizes( + CppMountItem::Type::UpdateProps, + cppUpdatePropsMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); + updateBufferSizes( + CppMountItem::Type::UpdateState, + cppUpdateStateMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); + updateBufferSizes( + CppMountItem::Type::UpdatePadding, + cppUpdatePaddingMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); + updateBufferSizes( + CppMountItem::Type::UpdateLayout, + cppUpdateLayoutMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); + updateBufferSizes( + CppMountItem::Type::UpdateEventEmitter, + cppUpdateEventEmitterMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); + updateBufferSizes( + CppMountItem::Type::Delete, + cppDeleteMountItems.size(), + batchMountItemIntsSize, + batchMountItemObjectsSize); +} + +static inline void writeIntBufferTypePreamble( + int mountItemType, + int numItems, + _JNIEnv *env, + jintArray &intBufferArray, + int &intBufferPosition) { + jint temp[2]; + if (numItems == 1) { + temp[0] = mountItemType; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp); + intBufferPosition += 1; + } else { + temp[0] = mountItemType | CppMountItem::Type::Multiple; + temp[1] = numItems; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp); + intBufferPosition += 2; + } +} + jni::local_ref Binding::initHybrid( jni::alias_ref) { return makeCxxInstance(); @@ -89,7 +255,9 @@ void Binding::startSurface( moduleName->toStdString(), initialProps->consume(), {}, - context, + context); + + scheduler->findMountingCoordinator(surfaceId)->setMountingOverrideDelegate( animationDriver_); } @@ -101,6 +269,8 @@ void Binding::startSurfaceWithConstraints( jfloat maxWidth, jfloat minHeight, jfloat maxHeight, + jfloat offsetX, + jfloat offsetY, jboolean isRTL, jboolean doLeftAndRightSwapInRTL) { SystraceSection s("FabricUIManagerBinding::startSurfaceWithConstraints"); @@ -123,6 +293,8 @@ void Binding::startSurfaceWithConstraints( Size{maxWidth / pointScaleFactor_, maxHeight / pointScaleFactor_}; LayoutContext context; + context.viewportOffset = + Point{offsetX / pointScaleFactor_, offsetY / pointScaleFactor_}; context.pointScaleFactor = {pointScaleFactor_}; context.swapLeftAndRightInRTL = doLeftAndRightSwapInRTL; LayoutConstraints constraints = {}; @@ -136,7 +308,9 @@ void Binding::startSurfaceWithConstraints( moduleName->toStdString(), initialProps->consume(), constraints, - context, + context); + + scheduler->findMountingCoordinator(surfaceId)->setMountingOverrideDelegate( animationDriver_); } @@ -178,6 +352,8 @@ void Binding::setConstraints( jfloat maxWidth, jfloat minHeight, jfloat maxHeight, + jfloat offsetX, + jfloat offsetY, jboolean isRTL, jboolean doLeftAndRightSwapInRTL) { SystraceSection s("FabricUIManagerBinding::setConstraints"); @@ -194,6 +370,8 @@ void Binding::setConstraints( Size{maxWidth / pointScaleFactor_, maxHeight / pointScaleFactor_}; LayoutContext context; + context.viewportOffset = + Point{offsetX / pointScaleFactor_, offsetY / pointScaleFactor_}; context.pointScaleFactor = {pointScaleFactor_}; context.swapLeftAndRightInRTL = doLeftAndRightSwapInRTL; LayoutConstraints constraints = {}; @@ -262,20 +440,10 @@ void Binding::installFabricUIManager( // Keep reference to config object and cache some feature flags here reactNativeConfig_ = config; - collapseDeleteCreateMountingInstructions_ = - reactNativeConfig_->getBool( - "react_fabric:enabled_collapse_delete_create_mounting_instructions") && - !reactNativeConfig_->getBool( - "react_fabric:enable_reparenting_detection_android") && - !reactNativeConfig_->getBool( - "react_fabric:enabled_layout_animations_android"); disablePreallocateViews_ = reactNativeConfig_->getBool( "react_fabric:disabled_view_preallocation_android"); - bool enableLayoutAnimations = reactNativeConfig_->getBool( - "react_fabric:enabled_layout_animations_android"); - auto toolbox = SchedulerToolbox{}; toolbox.contextContainer = contextContainer; toolbox.componentRegistryFactory = componentsRegistry->buildRegistryFunction; @@ -289,10 +457,8 @@ void Binding::installFabricUIManager( toolbox.backgroundExecutor = backgroundExecutor_->get(); } - if (enableLayoutAnimations) { - animationDriver_ = - std::make_shared(runtimeExecutor, this); - } + animationDriver_ = + std::make_shared(runtimeExecutor, this); scheduler_ = std::make_shared( toolbox, (animationDriver_ ? animationDriver_.get() : nullptr), this); } @@ -341,231 +507,12 @@ local_ref getPlatformComponentName(const ShadowView &shadowView) { return componentName; } -local_ref createUpdateEventEmitterMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - if (!mutation.newChildShadowView.eventEmitter) { - return nullptr; - } - SharedEventEmitter eventEmitter = mutation.newChildShadowView.eventEmitter; - - // Do not hold a reference to javaEventEmitter from the C++ side. - auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs(); - EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter); - cEventEmitter->eventEmitter = eventEmitter; - - static auto updateEventEmitterInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jint, jobject)>( - "updateEventEmitterMountItem"); - - return updateEventEmitterInstruction( - javaUIManager, mutation.newChildShadowView.tag, javaEventEmitter.get()); -} - -local_ref createUpdatePropsMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - auto shadowView = mutation.newChildShadowView; - auto newViewProps = - *std::dynamic_pointer_cast(shadowView.props); - - // TODO: move props from map to a typed object. - auto newProps = shadowView.props->rawProps; - - local_ref readableMap = - castReadableMap(ReadableNativeMap::newObjectCxxArgs(newProps)); - static auto updatePropsInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jint, ReadableMap::javaobject)>( - "updatePropsMountItem"); - - return updatePropsInstruction( - javaUIManager, mutation.newChildShadowView.tag, readableMap.get()); -} - -local_ref createUpdateLayoutMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - auto oldChildShadowView = mutation.oldChildShadowView; - auto newChildShadowView = mutation.newChildShadowView; - - if (newChildShadowView.layoutMetrics != EmptyLayoutMetrics && - oldChildShadowView.layoutMetrics != newChildShadowView.layoutMetrics) { - static auto updateLayoutInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod( - jint, jint, jint, jint, jint, jint)>("updateLayoutMountItem"); - auto layoutMetrics = newChildShadowView.layoutMetrics; - auto pointScaleFactor = layoutMetrics.pointScaleFactor; - auto frame = layoutMetrics.frame; - - int x = round(frame.origin.x * pointScaleFactor); - int y = round(frame.origin.y * pointScaleFactor); - int w = round(frame.size.width * pointScaleFactor); - int h = round(frame.size.height * pointScaleFactor); - auto layoutDirection = - toInt(newChildShadowView.layoutMetrics.layoutDirection); - return updateLayoutInstruction( - javaUIManager, newChildShadowView.tag, x, y, w, h, layoutDirection); - } - - return nullptr; -} - -local_ref createUpdatePaddingMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - auto oldChildShadowView = mutation.oldChildShadowView; - auto newChildShadowView = mutation.newChildShadowView; - - if (oldChildShadowView.layoutMetrics.contentInsets == - newChildShadowView.layoutMetrics.contentInsets) { - return nullptr; - } - - static auto updateLayoutInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jint, jint, jint, jint, jint)>( - "updatePaddingMountItem"); - - auto layoutMetrics = newChildShadowView.layoutMetrics; - auto pointScaleFactor = layoutMetrics.pointScaleFactor; - auto contentInsets = layoutMetrics.contentInsets; - - int left = round(contentInsets.left * pointScaleFactor); - int top = round(contentInsets.top * pointScaleFactor); - int right = round(contentInsets.right * pointScaleFactor); - int bottom = round(contentInsets.bottom * pointScaleFactor); - - return updateLayoutInstruction( - javaUIManager, newChildShadowView.tag, left, top, right, bottom); -} - -local_ref createInsertMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - static auto insertInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jint, jint, jint)>( - "insertMountItem"); - - return insertInstruction( - javaUIManager, - mutation.newChildShadowView.tag, - mutation.parentShadowView.tag, - mutation.index); -} - -local_ref createUpdateStateMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation) { - static auto updateStateInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jint, jobject)>( - "updateStateMountItem"); - - auto state = mutation.newChildShadowView.state; - - // Do not hold onto Java object from C - // We DO want to hold onto C object from Java, since we don't know the - // lifetime of the Java object - local_ref javaStateWrapper = nullptr; - if (state != nullptr) { - javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); - StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = state; - } - - return updateStateInstruction( - javaUIManager, - mutation.newChildShadowView.tag, - (javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr)); -} - -local_ref createRemoveAndDeleteMultiMountItem( - const jni::global_ref &javaUIManager, - const std::vector &metadata) { - auto env = Environment::current(); - auto removeAndDeleteArray = env->NewIntArray(metadata.size() * 4); - int position = 0; - jint temp[4]; - for (const auto &x : metadata) { - temp[0] = x.tag; - temp[1] = x.parentTag; - temp[2] = x.index; - temp[3] = (x.shouldRemove ? 1 : 0) | (x.shouldDelete ? 2 : 0); - env->SetIntArrayRegion(removeAndDeleteArray, position, 4, temp); - position += 4; - } - - static auto removeDeleteMultiInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod(jintArray)>( - "removeDeleteMultiMountItem"); - - auto ret = removeDeleteMultiInstruction(javaUIManager, removeAndDeleteArray); - - // It is not strictly necessary to manually delete the ref here, in this - // particular case. If JNI memory is being allocated in a loop, it's easy to - // overload the localref table and crash; this is not possible in this case - // since the JNI would automatically clear this ref when it goes out of scope, - // anyway. However, this is being left here as a reminder of good hygiene and - // to be careful with JNI-allocated memory in general. - env->DeleteLocalRef(removeAndDeleteArray); - - return ret; -} - -// TODO T48019320: because we pass initial props and state to the Create (and -// preallocate) mount instruction, we technically don't need to pass the first -// Update to any components. Dedupe? -local_ref createCreateMountItem( - const jni::global_ref &javaUIManager, - const ShadowViewMutation &mutation, - const Tag surfaceId) { - static auto createJavaInstruction = - jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod( - jstring, ReadableMap::javaobject, jobject, jint, jint, jboolean)>( - "createMountItem"); - - auto newChildShadowView = mutation.newChildShadowView; - - local_ref componentName = - getPlatformComponentName(newChildShadowView); - - jboolean isLayoutable = - newChildShadowView.layoutMetrics != EmptyLayoutMetrics; - - local_ref props = castReadableMap( - ReadableNativeMap::newObjectCxxArgs(newChildShadowView.props->rawProps)); - - // Do not hold onto Java object from C - // We DO want to hold onto C object from Java, since we don't know the - // lifetime of the Java object - local_ref javaStateWrapper = nullptr; - if (newChildShadowView.state != nullptr) { - javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); - StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = newChildShadowView.state; - } - - return createJavaInstruction( - javaUIManager, - componentName.get(), - props.get(), - (javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr), - surfaceId, - newChildShadowView.tag, - isLayoutable); -} - void Binding::schedulerDidFinishTransaction( MountingCoordinator::Shared const &mountingCoordinator) { std::lock_guard lock(commitMutex_); - SystraceSection s("FabricUIManagerBinding::schedulerDidFinishTransaction"); + SystraceSection s( + "FabricUIManagerBinding::schedulerDidFinishTransactionIntBuffer"); auto finishTransactionStartTime = telemetryTimePointNow(); jni::global_ref localJavaUIManager = getJavaUIManager(); @@ -581,212 +528,125 @@ void Binding::schedulerDidFinishTransaction( return; } + auto env = Environment::current(); + auto telemetry = mountingTransaction->getTelemetry(); auto surfaceId = mountingTransaction->getSurfaceId(); auto &mutations = mountingTransaction->getMutations(); - facebook::better::set createAndDeleteTagsToProcess; - // When collapseDeleteCreateMountingInstructions_ is enabled, the - // createAndDeleteTagsToProcess set will contain all the tags belonging to - // CREATE and DELETE mutation instructions that needs to be processed. If a - // CREATE or DELETE mutation instruction does not belong in the set, it means - // that the we received a pair of mutation instructions: DELETE - CREATE and - // it is not necessary to create or delete on the screen. - if (collapseDeleteCreateMountingInstructions_) { - for (const auto &mutation : mutations) { - if (mutation.type == ShadowViewMutation::Delete) { - // TAG on 'Delete' mutation instructions are part of the - // oldChildShadowView - createAndDeleteTagsToProcess.insert(mutation.oldChildShadowView.tag); - } else if (mutation.type == ShadowViewMutation::Create) { - // TAG on 'Create' mutation instructions are part of the - // newChildShadowView - Tag tag = mutation.newChildShadowView.tag; - if (createAndDeleteTagsToProcess.find(tag) == - createAndDeleteTagsToProcess.end()) { - createAndDeleteTagsToProcess.insert(tag); - } else { - createAndDeleteTagsToProcess.erase(tag); - } - } - } - } - auto revisionNumber = telemetry.getRevisionNumber(); - std::vector> queue; - // Upper bound estimation of mount items to be delivered to Java side. - int size = mutations.size() * 3 + 42; - - local_ref> mountItemsArray = - JArrayClass::newArray(size); - - auto mountItems = *(mountItemsArray); - std::unordered_set deletedViewTags; - - // Find the set of tags that are removed and deleted in one block - std::vector toRemove; + std::vector cppCommonMountItems; + std::vector cppDeleteMountItems; + std::vector cppUpdatePropsMountItems; + std::vector cppUpdateStateMountItems; + std::vector cppUpdatePaddingMountItems; + std::vector cppUpdateLayoutMountItems; + std::vector cppUpdateEventEmitterMountItems; - int position = 0; for (const auto &mutation : mutations) { - auto oldChildShadowView = mutation.oldChildShadowView; - auto newChildShadowView = mutation.newChildShadowView; - auto mutationType = mutation.type; - - if (collapseDeleteCreateMountingInstructions_ && - (mutationType == ShadowViewMutation::Create || - mutationType == ShadowViewMutation::Delete) && - createAndDeleteTagsToProcess.size() > 0) { - // The TAG on 'Delete' mutation instructions are part of the - // oldChildShadowView. On the other side, the TAG on 'Create' mutation - // instructions are part of the newChildShadowView - Tag tag = mutationType == ShadowViewMutation::Create - ? mutation.newChildShadowView.tag - : mutation.oldChildShadowView.tag; - if (createAndDeleteTagsToProcess.find(tag) == - createAndDeleteTagsToProcess.end()) { - continue; - } - } + const auto &parentShadowView = mutation.parentShadowView; + const auto &oldChildShadowView = mutation.oldChildShadowView; + const auto &newChildShadowView = mutation.newChildShadowView; + auto &mutationType = mutation.type; + auto &index = mutation.index; bool isVirtual = newChildShadowView.layoutMetrics == EmptyLayoutMetrics && oldChildShadowView.layoutMetrics == EmptyLayoutMetrics; - // Handle accumulated removals/deletions - if (mutation.type != ShadowViewMutation::Remove && - mutation.type != ShadowViewMutation::Delete) { - if (toRemove.size() > 0) { - mountItems[position++] = - createRemoveAndDeleteMultiMountItem(localJavaUIManager, toRemove); - toRemove.clear(); - } - } - - switch (mutation.type) { + switch (mutationType) { case ShadowViewMutation::Create: { if (disablePreallocateViews_ || - mutation.newChildShadowView.props->revision > 1 || - deletedViewTags.find(mutation.newChildShadowView.tag) != - deletedViewTags.end()) { - mountItems[position++] = - createCreateMountItem(localJavaUIManager, mutation, surfaceId); + newChildShadowView.props->revision > 1) { + cppCommonMountItems.push_back( + CppMountItem::CreateMountItem(newChildShadowView)); } break; } case ShadowViewMutation::Remove: { if (!isVirtual) { - toRemove.push_back( - RemoveDeleteMetadata{mutation.oldChildShadowView.tag, - mutation.parentShadowView.tag, - mutation.index, - true, - false}); + cppCommonMountItems.push_back(CppMountItem::RemoveMountItem( + parentShadowView, oldChildShadowView, index)); } break; } case ShadowViewMutation::Delete: { - // It is impossible to delete without removing node first - const auto &it = std::find_if( - std::begin(toRemove), - std::end(toRemove), - [&mutation](const auto &x) { - return x.tag == mutation.oldChildShadowView.tag; - }); - - if (it != std::end(toRemove)) { - it->shouldDelete = true; - } else { - toRemove.push_back(RemoveDeleteMetadata{ - mutation.oldChildShadowView.tag, -1, -1, false, true}); - } - - deletedViewTags.insert(mutation.oldChildShadowView.tag); + cppDeleteMountItems.push_back( + CppMountItem::DeleteMountItem(oldChildShadowView)); break; } case ShadowViewMutation::Update: { if (!isVirtual) { - if (mutation.oldChildShadowView.props != - mutation.newChildShadowView.props) { - mountItems[position++] = - createUpdatePropsMountItem(localJavaUIManager, mutation); + if (oldChildShadowView.props != newChildShadowView.props) { + cppUpdatePropsMountItems.push_back( + CppMountItem::UpdatePropsMountItem(newChildShadowView)); } - if (mutation.oldChildShadowView.state != - mutation.newChildShadowView.state) { - mountItems[position++] = - createUpdateStateMountItem(localJavaUIManager, mutation); + if (oldChildShadowView.state != newChildShadowView.state) { + cppUpdateStateMountItems.push_back( + CppMountItem::UpdateStateMountItem(newChildShadowView)); } // Padding: padding mountItems must be executed before layout props // are updated in the view. This is necessary to ensure that events // (resulting from layout changes) are dispatched with the correct // padding information. - auto updatePaddingMountItem = - createUpdatePaddingMountItem(localJavaUIManager, mutation); - if (updatePaddingMountItem) { - mountItems[position++] = updatePaddingMountItem; + if (oldChildShadowView.layoutMetrics.contentInsets != + newChildShadowView.layoutMetrics.contentInsets) { + cppUpdatePaddingMountItems.push_back( + CppMountItem::UpdatePaddingMountItem(newChildShadowView)); } - auto updateLayoutMountItem = - createUpdateLayoutMountItem(localJavaUIManager, mutation); - if (updateLayoutMountItem) { - mountItems[position++] = updateLayoutMountItem; + if (oldChildShadowView.layoutMetrics != + newChildShadowView.layoutMetrics) { + cppUpdateLayoutMountItems.push_back( + CppMountItem::UpdateLayoutMountItem( + mutation.newChildShadowView)); } } - if (mutation.oldChildShadowView.eventEmitter != - mutation.newChildShadowView.eventEmitter) { - auto updateEventEmitterMountItem = - createUpdateEventEmitterMountItem(localJavaUIManager, mutation); - if (updateEventEmitterMountItem) { - mountItems[position++] = updateEventEmitterMountItem; - } + if (oldChildShadowView.eventEmitter != + newChildShadowView.eventEmitter) { + cppUpdateEventEmitterMountItems.push_back( + CppMountItem::UpdateEventEmitterMountItem( + mutation.newChildShadowView)); } break; } case ShadowViewMutation::Insert: { if (!isVirtual) { // Insert item - mountItems[position++] = - createInsertMountItem(localJavaUIManager, mutation); + cppCommonMountItems.push_back(CppMountItem::InsertMountItem( + parentShadowView, newChildShadowView, index)); if (disablePreallocateViews_ || - mutation.newChildShadowView.props->revision > 1 || - deletedViewTags.find(mutation.newChildShadowView.tag) != - deletedViewTags.end()) { - mountItems[position++] = - createUpdatePropsMountItem(localJavaUIManager, mutation); + newChildShadowView.props->revision > 1) { + cppUpdatePropsMountItems.push_back( + CppMountItem::UpdatePropsMountItem(newChildShadowView)); } // State - if (mutation.newChildShadowView.state) { - mountItems[position++] = - createUpdateStateMountItem(localJavaUIManager, mutation); + if (newChildShadowView.state) { + cppUpdateStateMountItems.push_back( + CppMountItem::UpdateStateMountItem(newChildShadowView)); } // Padding: padding mountItems must be executed before layout props // are updated in the view. This is necessary to ensure that events // (resulting from layout changes) are dispatched with the correct // padding information. - auto updatePaddingMountItem = - createUpdatePaddingMountItem(localJavaUIManager, mutation); - if (updatePaddingMountItem) { - mountItems[position++] = updatePaddingMountItem; - } + cppUpdatePaddingMountItems.push_back( + CppMountItem::UpdatePaddingMountItem( + mutation.newChildShadowView)); // Layout - auto updateLayoutMountItem = - createUpdateLayoutMountItem(localJavaUIManager, mutation); - if (updateLayoutMountItem) { - mountItems[position++] = updateLayoutMountItem; - } + cppUpdateLayoutMountItems.push_back( + CppMountItem::UpdateLayoutMountItem(mutation.newChildShadowView)); } // EventEmitter - auto updateEventEmitterMountItem = - createUpdateEventEmitterMountItem(localJavaUIManager, mutation); - if (updateEventEmitterMountItem) { - mountItems[position++] = updateEventEmitterMountItem; - } + cppUpdateEventEmitterMountItems.push_back( + CppMountItem::UpdateEventEmitterMountItem( + mutation.newChildShadowView)); break; } @@ -796,27 +656,26 @@ void Binding::schedulerDidFinishTransaction( } } - // Handle remaining removals and deletions - if (toRemove.size() > 0) { - mountItems[position++] = - createRemoveAndDeleteMultiMountItem(localJavaUIManager, toRemove); - toRemove.clear(); - } - - static auto createMountItemsBatchContainer = + // We now have all the information we need, including ordering of mount items, + // to know exactly how much space must be allocated + int batchMountItemIntsSize = 0; + int batchMountItemObjectsSize = 0; + computeBufferSizes( + batchMountItemIntsSize, + batchMountItemObjectsSize, + cppCommonMountItems, + cppDeleteMountItems, + cppUpdatePropsMountItems, + cppUpdateStateMountItems, + cppUpdatePaddingMountItems, + cppUpdateLayoutMountItems, + cppUpdateEventEmitterMountItems); + + static auto createMountItemsIntBufferBatchContainer = jni::findClassStatic(Binding::UIManagerJavaDescriptor) ->getMethod( - jint, jtypeArray, jint, jint)>( - "createBatchMountItem"); - - // If there are no items, we pass a nullptr instead of passing the object - // through the JNI - auto batch = createMountItemsBatchContainer( - localJavaUIManager, - surfaceId, - position == 0 ? nullptr : mountItemsArray.get(), - position, - revisionNumber); + jint, jintArray, jtypeArray, jint)>( + "createIntBufferBatchMountItem"); static auto scheduleMountItem = jni::findClassStatic(Binding::UIManagerJavaDescriptor) @@ -831,6 +690,267 @@ void Binding::schedulerDidFinishTransaction( jlong, jlong)>("scheduleMountItem"); + if (batchMountItemIntsSize == 0) { + auto finishTransactionEndTime = telemetryTimePointNow(); + + scheduleMountItem( + localJavaUIManager, + nullptr, + telemetry.getRevisionNumber(), + telemetryTimePointToMilliseconds(telemetry.getCommitStartTime()), + telemetryTimePointToMilliseconds(telemetry.getDiffStartTime()), + telemetryTimePointToMilliseconds(telemetry.getDiffEndTime()), + telemetryTimePointToMilliseconds(telemetry.getLayoutStartTime()), + telemetryTimePointToMilliseconds(telemetry.getLayoutEndTime()), + telemetryTimePointToMilliseconds(finishTransactionStartTime), + telemetryTimePointToMilliseconds(finishTransactionEndTime)); + return; + } + + // Allocate the intBuffer and object array, now that we know exact sizes + // necessary + // TODO: don't allocate at all if size is zero + jintArray intBufferArray = env->NewIntArray(batchMountItemIntsSize); + local_ref> objBufferArray = + JArrayClass::newArray(batchMountItemObjectsSize); + + // Fill in arrays + int intBufferPosition = 0; + int objBufferPosition = 0; + int prevMountItemType = -1; + jint temp[7]; + for (int i = 0; i < cppCommonMountItems.size(); i++) { + const auto &mountItem = cppCommonMountItems[i]; + const auto &mountItemType = mountItem.type; + + // Get type here, and count forward how many items of this type are in a + // row. Write preamble to any common type here. + if (prevMountItemType != mountItemType) { + int numSameItemTypes = 1; + for (int j = i + 1; j < cppCommonMountItems.size() && + cppCommonMountItems[j].type == mountItemType; + j++) { + numSameItemTypes++; + } + + writeIntBufferTypePreamble( + mountItemType, + numSameItemTypes, + env, + intBufferArray, + intBufferPosition); + } + prevMountItemType = mountItemType; + + // TODO: multi-create, multi-insert, etc + if (mountItemType == CppMountItem::Type::Create) { + local_ref componentName = + getPlatformComponentName(mountItem.newChildShadowView); + + int isLayoutable = + mountItem.newChildShadowView.layoutMetrics != EmptyLayoutMetrics ? 1 + : 0; + + local_ref props = + castReadableMap(ReadableNativeMap::newObjectCxxArgs( + mountItem.newChildShadowView.props->rawProps)); + + // Do not hold onto Java object from C + // We DO want to hold onto C object from Java, since we don't know the + // lifetime of the Java object + local_ref javaStateWrapper = nullptr; + if (mountItem.newChildShadowView.state != nullptr) { + javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); + StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper); + cStateWrapper->state_ = mountItem.newChildShadowView.state; + } + + temp[0] = mountItem.newChildShadowView.tag; + temp[1] = isLayoutable; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp); + intBufferPosition += 2; + + (*objBufferArray)[objBufferPosition++] = componentName.get(); + (*objBufferArray)[objBufferPosition++] = props.get(); + (*objBufferArray)[objBufferPosition++] = + javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr; + } else if (mountItemType == CppMountItem::Type::Insert) { + temp[0] = mountItem.newChildShadowView.tag; + temp[1] = mountItem.parentShadowView.tag; + temp[2] = mountItem.index; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 3, temp); + intBufferPosition += 3; + } else if (mountItemType == CppMountItem::Remove) { + temp[0] = mountItem.oldChildShadowView.tag; + temp[1] = mountItem.parentShadowView.tag; + temp[2] = mountItem.index; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 3, temp); + intBufferPosition += 3; + } else { + LOG(ERROR) << "Unexpected CppMountItem type"; + } + } + if (cppUpdatePropsMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::UpdateProps, + cppUpdatePropsMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppUpdatePropsMountItems) { + temp[0] = mountItem.newChildShadowView.tag; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp); + intBufferPosition += 1; + + auto newProps = mountItem.newChildShadowView.props->rawProps; + local_ref newPropsReadableMap = + castReadableMap(ReadableNativeMap::newObjectCxxArgs(newProps)); + (*objBufferArray)[objBufferPosition++] = newPropsReadableMap.get(); + } + } + if (cppUpdateStateMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::UpdateState, + cppUpdateStateMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppUpdateStateMountItems) { + temp[0] = mountItem.newChildShadowView.tag; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp); + intBufferPosition += 1; + + auto state = mountItem.newChildShadowView.state; + // Do not hold onto Java object from C + // We DO want to hold onto C object from Java, since we don't know the + // lifetime of the Java object + local_ref javaStateWrapper = nullptr; + if (state != nullptr) { + javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); + StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper); + cStateWrapper->state_ = state; + } + + (*objBufferArray)[objBufferPosition++] = + (javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr); + } + } + if (cppUpdatePaddingMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::UpdatePadding, + cppUpdatePaddingMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppUpdatePaddingMountItems) { + auto layoutMetrics = mountItem.newChildShadowView.layoutMetrics; + auto pointScaleFactor = layoutMetrics.pointScaleFactor; + auto contentInsets = layoutMetrics.contentInsets; + + int left = floor(contentInsets.left * pointScaleFactor); + int top = floor(contentInsets.top * pointScaleFactor); + int right = floor(contentInsets.right * pointScaleFactor); + int bottom = floor(contentInsets.bottom * pointScaleFactor); + + temp[0] = mountItem.newChildShadowView.tag; + temp[1] = left; + temp[2] = top; + temp[3] = right; + temp[4] = bottom; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 5, temp); + intBufferPosition += 5; + } + } + if (cppUpdateLayoutMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::UpdateLayout, + cppUpdateLayoutMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppUpdateLayoutMountItems) { + auto layoutMetrics = mountItem.newChildShadowView.layoutMetrics; + auto pointScaleFactor = layoutMetrics.pointScaleFactor; + auto frame = layoutMetrics.frame; + + int x = round(frame.origin.x * pointScaleFactor); + int y = round(frame.origin.y * pointScaleFactor); + int w = round(frame.size.width * pointScaleFactor); + int h = round(frame.size.height * pointScaleFactor); + int layoutDirection = + toInt(mountItem.newChildShadowView.layoutMetrics.layoutDirection); + int displayType = + toInt(mountItem.newChildShadowView.layoutMetrics.displayType); + + temp[0] = mountItem.newChildShadowView.tag; + temp[1] = x; + temp[2] = y; + temp[3] = w; + temp[4] = h; + temp[5] = layoutDirection; + temp[6] = displayType; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 7, temp); + intBufferPosition += 7; + } + } + if (cppUpdateEventEmitterMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::UpdateEventEmitter, + cppUpdateEventEmitterMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppUpdateEventEmitterMountItems) { + temp[0] = mountItem.newChildShadowView.tag; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp); + intBufferPosition += 1; + + SharedEventEmitter eventEmitter = + mountItem.newChildShadowView.eventEmitter; + + // Do not hold a reference to javaEventEmitter from the C++ side. + auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs(); + EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter); + cEventEmitter->eventEmitter = eventEmitter; + + (*objBufferArray)[objBufferPosition++] = javaEventEmitter.get(); + } + } + + // Write deletes last - so that all prop updates, etc, for the tag in the same + // batch don't fail. Without additional machinery, moving deletes here + // requires that the differ never produces "DELETE...CREATE" in that order for + // the same tag. It's nice to be able to batch all similar operations together + // for space efficiency. + if (cppDeleteMountItems.size() > 0) { + writeIntBufferTypePreamble( + CppMountItem::Type::Delete, + cppDeleteMountItems.size(), + env, + intBufferArray, + intBufferPosition); + + for (const auto &mountItem : cppDeleteMountItems) { + temp[0] = mountItem.oldChildShadowView.tag; + env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp); + intBufferPosition += 1; + } + } + + // If there are no items, we pass a nullptr instead of passing the object + // through the JNI + auto batch = createMountItemsIntBufferBatchContainer( + localJavaUIManager, + surfaceId, + batchMountItemIntsSize == 0 ? nullptr : intBufferArray, + batchMountItemObjectsSize == 0 ? nullptr : objBufferArray.get(), + revisionNumber); + auto finishTransactionEndTime = telemetryTimePointNow(); scheduleMountItem( @@ -844,6 +964,8 @@ void Binding::schedulerDidFinishTransaction( telemetryTimePointToMilliseconds(telemetry.getLayoutEndTime()), telemetryTimePointToMilliseconds(finishTransactionStartTime), telemetryTimePointToMilliseconds(finishTransactionEndTime)); + + env->DeleteLocalRef(intBufferArray); } void Binding::setPixelDensity(float pointScaleFactor) { @@ -944,7 +1066,7 @@ void Binding::schedulerDidDispatchCommand( static auto dispatchCommand = jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod( + ->getMethod( "dispatchCommand"); local_ref command = make_jstring(commandName); @@ -953,7 +1075,35 @@ void Binding::schedulerDidDispatchCommand( castReadableArray(ReadableNativeArray::newObjectCxxArgs(args)); dispatchCommand( - localJavaUIManager, shadowView.tag, command.get(), argsArray.get()); + localJavaUIManager, + shadowView.surfaceId, + shadowView.tag, + command.get(), + argsArray.get()); +} + +void Binding::schedulerDidSendAccessibilityEvent( + const ShadowView &shadowView, + std::string const &eventType) { + jni::global_ref localJavaUIManager = getJavaUIManager(); + if (!localJavaUIManager) { + LOG(ERROR) + << "Binding::schedulerDidDispatchCommand: JavaUIManager disappeared"; + return; + } + + local_ref eventTypeStr = make_jstring(eventType); + + static auto sendAccessibilityEventFromJS = + jni::findClassStatic(Binding::UIManagerJavaDescriptor) + ->getMethod( + "sendAccessibilityEventFromJS"); + + sendAccessibilityEventFromJS( + localJavaUIManager, + shadowView.surfaceId, + shadowView.tag, + eventTypeStr.get()); } void Binding::schedulerDidSetJSResponder( @@ -969,10 +1119,11 @@ void Binding::schedulerDidSetJSResponder( static auto setJSResponder = jni::findClassStatic(Binding::UIManagerJavaDescriptor) - ->getMethod("setJSResponder"); + ->getMethod("setJSResponder"); setJSResponder( localJavaUIManager, + shadowView.surfaceId, shadowView.tag, initialShadowView.tag, (jboolean)blockNativeResponder); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h index fe27981709892b..f2ac6cd479ada7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h @@ -26,6 +26,45 @@ namespace react { class Instance; +struct CppMountItem final { +#pragma mark - Designated Initializers + static CppMountItem CreateMountItem(ShadowView shadowView); + static CppMountItem DeleteMountItem(ShadowView shadowView); + static CppMountItem + InsertMountItem(ShadowView parentView, ShadowView shadowView, int index); + static CppMountItem + RemoveMountItem(ShadowView parentView, ShadowView shadowView, int index); + static CppMountItem UpdatePropsMountItem(ShadowView shadowView); + static CppMountItem UpdateStateMountItem(ShadowView shadowView); + static CppMountItem UpdateLayoutMountItem(ShadowView shadowView); + static CppMountItem UpdateEventEmitterMountItem(ShadowView shadowView); + static CppMountItem UpdatePaddingMountItem(ShadowView shadowView); + +#pragma mark - Type + + enum Type { + Undefined = -1, + Multiple = 1, + Create = 2, + Delete = 4, + Insert = 8, + Remove = 16, + UpdateProps = 32, + UpdateState = 64, + UpdateLayout = 128, + UpdateEventEmitter = 256, + UpdatePadding = 512 + }; + +#pragma mark - Fields + + Type type = {Create}; + ShadowView parentShadowView = {}; + ShadowView oldChildShadowView = {}; + ShadowView newChildShadowView = {}; + int index = {}; +}; + class Binding : public jni::HybridClass, public SchedulerDelegate, public LayoutAnimationStatusDelegate { @@ -48,6 +87,8 @@ class Binding : public jni::HybridClass, jfloat maxWidth, jfloat minHeight, jfloat maxHeight, + jfloat offsetX, + jfloat offsetY, jboolean isRTL, jboolean doLeftAndRightSwapInRTL); @@ -74,6 +115,8 @@ class Binding : public jni::HybridClass, jfloat maxWidth, jfloat minHeight, jfloat maxHeight, + jfloat offsetX, + jfloat offsetY, jboolean isRTL, jboolean doLeftAndRightSwapInRTL); @@ -93,6 +136,10 @@ class Binding : public jni::HybridClass, std::string const &commandName, folly::dynamic const args) override; + void schedulerDidSendAccessibilityEvent( + const ShadowView &shadowView, + std::string const &eventType) override; + void schedulerDidSetJSResponder( SurfaceId surfaceId, const ShadowView &shadowView, @@ -126,7 +173,6 @@ class Binding : public jni::HybridClass, float pointScaleFactor_ = 1; std::shared_ptr reactNativeConfig_{nullptr}; - bool collapseDeleteCreateMountingInstructions_{false}; bool disablePreallocateViews_{false}; bool disableVirtualNodePreallocation_{false}; bool enableFabricLogs_{false}; diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/StateWrapperImpl.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/StateWrapperImpl.cpp index afbe9c7155232e..9a5b929e9af10f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/StateWrapperImpl.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/StateWrapperImpl.cpp @@ -33,31 +33,7 @@ void StateWrapperImpl::updateStateImpl(NativeMap *map) { // Get folly::dynamic from map auto dynamicMap = map->consume(); // Set state - state_->updateState(dynamicMap, nullptr); -} - -void StateWrapperImpl::updateStateWithFailureCallbackImpl( - NativeMap *map, - jni::alias_ref self, - int callbackRefId) { - // Get folly::dynamic from map - auto dynamicMap = map->consume(); - // Turn the alias into a global_ref - // Note: this whole thing feels really janky, making StateWrapperImpl.java - // pass "this" into a function it's calling on "this". But after struggling - // for a while I couldn't figure out how to get a reference to the Java side - // of "this" in C++ in a way that's reasonably safe, and it maybe is even - // discouraged. Anyway, it might be weird, but this seems to work and be safe. - jni::global_ref globalSelf = make_global(self); - // Set state - state_->updateState( - dynamicMap, [globalSelf = std::move(globalSelf), callbackRefId]() { - static auto method = - jni::findClassStatic( - StateWrapperImpl::StateWrapperImplJavaDescriptor) - ->getMethod("updateStateFailed"); - method(globalSelf, callbackRefId); - }); + state_->updateState(dynamicMap); } void StateWrapperImpl::registerNatives() { @@ -65,9 +41,6 @@ void StateWrapperImpl::registerNatives() { makeNativeMethod("initHybrid", StateWrapperImpl::initHybrid), makeNativeMethod("getState", StateWrapperImpl::getState), makeNativeMethod("updateStateImpl", StateWrapperImpl::updateStateImpl), - makeNativeMethod( - "updateStateWithFailureCallbackImpl", - StateWrapperImpl::updateStateWithFailureCallbackImpl), }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index 4629668d4944b4..b916ff6ffd3bc6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -8,42 +8,32 @@ package com.facebook.react.fabric.mounting; import static com.facebook.infer.annotation.ThreadConfined.ANY; -import static com.facebook.infer.annotation.ThreadConfined.UI; -import android.content.Context; import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.facebook.common.logging.FLog; -import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; +import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactSoftException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableNativeMap; import com.facebook.react.bridge.RetryableMountingLayerException; -import com.facebook.react.bridge.SoftAssertions; import com.facebook.react.bridge.UiThreadUtil; -import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.fabric.FabricUIManager; import com.facebook.react.fabric.events.EventEmitterWrapper; import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.touch.JSResponderHandler; import com.facebook.react.uimanager.IllegalViewOperationException; -import com.facebook.react.uimanager.ReactStylesDiffMap; -import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.RootViewManager; -import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.yoga.YogaMeasureMode; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * Class responsible for actually dispatching view updates enqueued via {@link @@ -51,589 +41,233 @@ */ public class MountingManager { public static final String TAG = MountingManager.class.getSimpleName(); - private static final boolean SHOW_CHANGED_VIEW_HIERARCHIES = ReactBuildConfig.DEBUG && false; + private static final int MAX_STOPPED_SURFACE_IDS_LENGTH = 15; + + @NonNull + private final ConcurrentHashMap mSurfaceIdToManager = + new ConcurrentHashMap<>(); // any thread + + private final CopyOnWriteArrayList mStoppedSurfaceIds = new CopyOnWriteArrayList<>(); + + @Nullable private SurfaceMountingManager mMostRecentSurfaceMountingManager; - @NonNull private final ConcurrentHashMap mTagToViewState; @NonNull private final JSResponderHandler mJSResponderHandler = new JSResponderHandler(); @NonNull private final ViewManagerRegistry mViewManagerRegistry; @NonNull private final RootViewManager mRootViewManager = new RootViewManager(); + private volatile int mStoppedSurfaceCacheLastId = View.NO_ID; + private volatile boolean mStoppedSurfaceCacheLastResult = false; + public MountingManager(@NonNull ViewManagerRegistry viewManagerRegistry) { - mTagToViewState = new ConcurrentHashMap<>(); mViewManagerRegistry = viewManagerRegistry; } - private static void logViewHierarchy(ViewGroup parent) { - int parentTag = parent.getId(); - FLog.e(TAG, " "); - for (int i = 0; i < parent.getChildCount(); i++) { - FLog.e( - TAG, - " "); - } - FLog.e(TAG, " "); - } - /** * This mutates the rootView, which is an Android View, so this should only be called on the UI * thread. * - * @param reactRootTag + * @param surfaceId * @param rootView */ - @ThreadConfined(UI) - public void addRootView(int reactRootTag, @NonNull View rootView) { - if (rootView.getId() != View.NO_ID) { - throw new IllegalViewOperationException( - "Trying to add a root view with an explicit id already set. React Native uses " - + "the id field to track react tags and will overwrite this field. If that is fine, " - + "explicitly overwrite the id field to View.NO_ID before calling addRootView."); + @AnyThread + public void startSurface( + final int surfaceId, @NonNull final View rootView, ThemedReactContext themedReactContext) { + SurfaceMountingManager surfaceMountingManager = + new SurfaceMountingManager( + surfaceId, + rootView, + mJSResponderHandler, + mViewManagerRegistry, + mRootViewManager, + themedReactContext); + + // There could technically be a race condition here if addRootView is called twice from + // different threads, though this is (probably) extremely unlikely, and likely an error. + // This logic to protect against race conditions is a holdover from older code, and we don't + // know if it actually happens in practice - so, we're logging soft exceptions for now. + // This *will* crash in Debug mode, but not in production. + mSurfaceIdToManager.putIfAbsent(surfaceId, surfaceMountingManager); + if (mSurfaceIdToManager.get(surfaceId) != surfaceMountingManager) { + ReactSoftException.logSoftException( + TAG, + new IllegalViewOperationException( + "Called addRootView more than once for the SurfaceId [" + surfaceId + "]")); } - mTagToViewState.put( - reactRootTag, new ViewState(reactRootTag, rootView, mRootViewManager, true)); - rootView.setId(reactRootTag); + mMostRecentSurfaceMountingManager = mSurfaceIdToManager.get(surfaceId); } - /** Delete rootView and all children/ */ - @UiThread - public void deleteRootView(int reactRootTag) { - if (mTagToViewState.containsKey(reactRootTag)) { - dropView(mTagToViewState.get(reactRootTag).mView, true); - } - } - - /** Releases all references to given native View. */ - @UiThread - private void dropView(@NonNull View view, boolean deleteImmediately) { - UiThreadUtil.assertOnUiThread(); - - final int reactTag = view.getId(); - ViewState state = getViewState(reactTag); - ViewManager viewManager = state.mViewManager; - - if (!state.mIsRoot && viewManager != null) { - // For non-root views we notify viewmanager with {@link ViewManager#onDropInstance} - viewManager.onDropViewInstance(view); - } - if (view instanceof ViewGroup && viewManager instanceof ViewGroupManager) { - final ViewGroup viewGroup = (ViewGroup) view; - final ViewGroupManager viewGroupManager = getViewGroupManager(state); - - // As documented elsewhere, sometimes when a child is removed from a parent, that change - // is not immediately available in the hierarchy until a future UI tick. This can cause - // inconsistent child counts, etc, but it can _also_ cause us to drop views that shouldn't, - // because they're removed from the parent but that change isn't immediately visible. So, - // we do two things: 1) delay this logic until the next UI thread tick, 2) ignore children - // who don't report the expected parent. - // For most cases, we _do not_ want this logic to run, anyway, since it either means that we - // don't have a correct set of MountingInstructions; or it means that we're tearing down an - // entire screen, in which case we can safely delete everything immediately, not having - // executed any remove instructions immediately before this. - if (deleteImmediately) { - dropChildren(reactTag, viewGroup, viewGroupManager); - } else { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - dropChildren(reactTag, viewGroup, viewGroupManager); - } - }); + @AnyThread + public void stopSurface(final int surfaceId) { + mStoppedSurfaceCacheLastId = View.NO_ID; + + SurfaceMountingManager surfaceMountingManager = mSurfaceIdToManager.get(surfaceId); + if (surfaceMountingManager != null) { + // Maximum number of stopped surfaces to keep track of + while (mStoppedSurfaceIds.size() >= MAX_STOPPED_SURFACE_IDS_LENGTH) { + Integer staleStoppedId = mStoppedSurfaceIds.get(0); + mSurfaceIdToManager.remove(staleStoppedId.intValue()); + mStoppedSurfaceIds.remove(staleStoppedId); + FLog.d(TAG, "Removing stale SurfaceMountingManager: [%d]", staleStoppedId.intValue()); } - } + mStoppedSurfaceIds.add(surfaceId); - mTagToViewState.remove(reactTag); - } + surfaceMountingManager.stopSurface(); - @UiThread - private void dropChildren( - int reactTag, - @NonNull ViewGroup viewGroup, - @NonNull ViewGroupManager viewGroupManager) { - for (int i = viewGroupManager.getChildCount(viewGroup) - 1; i >= 0; i--) { - View child = viewGroupManager.getChildAt(viewGroup, i); - if (getNullableViewState(child.getId()) != null) { - if (SHOW_CHANGED_VIEW_HIERARCHIES) { - FLog.e( - TAG, - "Automatically dropping view that is still attached to a parent being dropped. Parent: [" - + reactTag - + "] child: [" - + child.getId() - + "]"); - } - ViewParent childParent = child.getParent(); - if (childParent == null || !childParent.equals(viewGroup)) { - int childParentId = - (childParent == null - ? -1 - : (childParent instanceof ViewGroup ? ((ViewGroup) childParent).getId() : -1)); - FLog.e( - TAG, - "Recursively deleting children of [" - + reactTag - + "] but parent of child [" - + child.getId() - + "] is [" - + childParentId - + "]"); - } else { - dropView(child, true); - } + if (surfaceMountingManager == mMostRecentSurfaceMountingManager) { + mMostRecentSurfaceMountingManager = null; } - viewGroupManager.removeViewAt(viewGroup, i); - } - } - - @UiThread - public void addViewAt(final int parentTag, final int tag, final int index) { - UiThreadUtil.assertOnUiThread(); - ViewState parentViewState = getViewState(parentTag); - if (!(parentViewState.mView instanceof ViewGroup)) { - String message = - "Unable to add a view into a view that is not a ViewGroup. ParentTag: " - + parentTag - + " - Tag: " - + tag - + " - Index: " - + index; - FLog.e(TAG, message); - throw new IllegalStateException(message); - } - final ViewGroup parentView = (ViewGroup) parentViewState.mView; - ViewState viewState = getViewState(tag); - final View view = viewState.mView; - if (view == null) { - throw new IllegalStateException( - "Unable to find view for viewState " + viewState + " and tag " + tag); - } - - // Display children before inserting - if (SHOW_CHANGED_VIEW_HIERARCHIES) { - FLog.e(TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); - logViewHierarchy(parentView); - } - - try { - getViewGroupManager(parentViewState).addView(parentView, view, index); - } catch (IllegalStateException e) { - // Wrap error with more context for debugging - throw new IllegalStateException( - "addViewAt: failed to insert view [" - + tag - + "] into parent [" - + parentTag - + "] at index " - + index, - e); - } - - // Display children after inserting - if (SHOW_CHANGED_VIEW_HIERARCHIES) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - FLog.e( - TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); - logViewHierarchy(parentView); - } - }); - } - } - - private @NonNull ViewState getViewState(int tag) { - ViewState viewState = mTagToViewState.get(tag); - if (viewState == null) { - throw new RetryableMountingLayerException("Unable to find viewState view for tag " + tag); + } else { + ReactSoftException.logSoftException( + TAG, + new IllegalViewOperationException( + "Cannot call StopSurface on non-existent surface: [" + surfaceId + "]")); } - return viewState; } - private @Nullable ViewState getNullableViewState(int tag) { - return mTagToViewState.get(tag); + @Nullable + public SurfaceMountingManager getSurfaceManager(int surfaceId) { + return mSurfaceIdToManager.get(surfaceId); } - @Deprecated - public void receiveCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) { - ViewState viewState = getNullableViewState(reactTag); - - // It's not uncommon for JS to send events as/after a component is being removed from the - // view hierarchy. For example, TextInput may send a "blur" command in response to the view - // disappearing. Throw `ReactNoCrashSoftException` so they're logged but don't crash in dev - // for now. - if (viewState == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState for tag: " + reactTag + " for commandId: " + commandId); - } - - if (viewState.mViewManager == null) { - throw new RetryableMountingLayerException("Unable to find viewManager for tag " + reactTag); - } + @NonNull + public SurfaceMountingManager getSurfaceManagerEnforced(int surfaceId, String context) { + SurfaceMountingManager surfaceMountingManager = getSurfaceManager(surfaceId); - if (viewState.mView == null) { + if (surfaceMountingManager == null) { throw new RetryableMountingLayerException( - "Unable to find viewState view for tag " + reactTag); + "Unable to find SurfaceMountingManager for surfaceId: [" + + surfaceId + + "]. Context: " + + context); } - viewState.mViewManager.receiveCommand(viewState.mView, commandId, commandArgs); + return surfaceMountingManager; } - public void receiveCommand( - int reactTag, @NonNull String commandId, @Nullable ReadableArray commandArgs) { - ViewState viewState = getNullableViewState(reactTag); - - // It's not uncommon for JS to send events as/after a component is being removed from the - // view hierarchy. For example, TextInput may send a "blur" command in response to the view - // disappearing. Throw `ReactNoCrashSoftException` so they're logged but don't crash in dev - // for now. - if (viewState == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState for tag: " + reactTag + " for commandId: " + commandId); - } - - if (viewState.mViewManager == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState manager for tag " + reactTag); + public boolean surfaceIsStopped(int surfaceId) { + if (surfaceId == View.NO_ID) { + return false; } - - if (viewState.mView == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState view for tag " + reactTag); + if (surfaceId == mStoppedSurfaceCacheLastId) { + return mStoppedSurfaceCacheLastResult; } - viewState.mViewManager.receiveCommand(viewState.mView, commandId, commandArgs); + boolean res = surfaceIsStoppedImpl(surfaceId); + mStoppedSurfaceCacheLastResult = res; + mStoppedSurfaceCacheLastId = surfaceId; + return res; } - public void sendAccessibilityEvent(int reactTag, int eventType) { - ViewState viewState = getViewState(reactTag); - - if (viewState.mViewManager == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState manager for tag " + reactTag); + private boolean surfaceIsStoppedImpl(int surfaceId) { + if (mStoppedSurfaceIds.contains(surfaceId)) { + return true; } - if (viewState.mView == null) { - throw new RetryableMountingLayerException( - "Unable to find viewState view for tag " + reactTag); + SurfaceMountingManager surfaceMountingManager = mSurfaceIdToManager.get(surfaceId); + if (surfaceMountingManager != null && surfaceMountingManager.isStopped()) { + return true; } - viewState.mView.sendAccessibilityEvent(eventType); - } - - @SuppressWarnings("unchecked") // prevents unchecked conversion warn of the type - private static @NonNull ViewGroupManager getViewGroupManager( - @NonNull ViewState viewState) { - if (viewState.mViewManager == null) { - throw new IllegalStateException("Unable to find ViewManager for view: " + viewState); - } - return (ViewGroupManager) viewState.mViewManager; + return false; } - @UiThread - public void removeViewAt(final int tag, final int parentTag, final int index) { - UiThreadUtil.assertOnUiThread(); - ViewState viewState = getNullableViewState(parentTag); - - if (viewState == null) { - ReactSoftException.logSoftException( - MountingManager.TAG, - new IllegalStateException( - "Unable to find viewState for tag: " + parentTag + " for removeViewAt")); - return; - } - - final ViewGroup parentView = (ViewGroup) viewState.mView; - - if (parentView == null) { - throw new IllegalStateException("Unable to find view for tag " + parentTag); - } - - if (SHOW_CHANGED_VIEW_HIERARCHIES) { - // Display children before deleting any - FLog.e(TAG, "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); - logViewHierarchy(parentView); - } - - ViewGroupManager viewGroupManager = getViewGroupManager(viewState); - - // Verify that the view we're about to remove has the same tag we expect - View view = viewGroupManager.getChildAt(parentView, index); - int actualTag = (view != null ? view.getId() : -1); - if (actualTag != tag) { - int tagActualIndex = -1; - int parentChildrenCount = parentView.getChildCount(); - for (int i = 0; i < parentChildrenCount; i++) { - if (parentView.getChildAt(i).getId() == tag) { - tagActualIndex = i; - break; + /** + * Get SurfaceMountingManager associated with a ReactTag. Unfortunately, this requires lookups + * over N maps, where N is the number of active or recently-stopped Surfaces. Each lookup will + * cost `log(M)` operations where M is the number of reactTags in the surface, so the total cost + * per lookup is `O(N * log(M))`. + * + *

To mitigate this cost, we attempt to keep track of the "most recent" SurfaceMountingManager + * and do lookups in it first. For the vast majority of use-cases, except for events or operations + * sent to off-screen surfaces, or use-cases where multiple surfaces are visible and interactable, + * this will reduce the lookup time to `O(log(M))`. Someone smarter than me could probably figure + * out an amortized time. + * + * @param reactTag + * @return + */ + @Nullable + public SurfaceMountingManager getSurfaceManagerForView(int reactTag) { + if (mMostRecentSurfaceMountingManager != null + && mMostRecentSurfaceMountingManager.getViewExists(reactTag)) { + return mMostRecentSurfaceMountingManager; + } + + for (Map.Entry entry : mSurfaceIdToManager.entrySet()) { + SurfaceMountingManager smm = entry.getValue(); + if (smm != mMostRecentSurfaceMountingManager && smm.getViewExists(reactTag)) { + if (mMostRecentSurfaceMountingManager == null) { + mMostRecentSurfaceMountingManager = smm; } + return smm; } - - // TODO T74425739: previously, we did not do this check and `removeViewAt` would be executed - // below, sometimes crashing there. *However*, interestingly enough, `removeViewAt` would not - // complain if you removed views from an already-empty parent. This seems necessary currently - // for certain ViewManagers that remove their own children - like BottomSheet? - // This workaround seems not-great, but for now, we just return here for - // backwards-compatibility. Essentially, if a view has already been removed from the - // hierarchy, we treat it as a noop. - if (tagActualIndex == -1) { - FLog.e( - TAG, - "removeViewAt: [" - + tag - + "] -> [" - + parentTag - + "] @" - + index - + ": view already removed from parent! Children in parent: " - + parentChildrenCount); - return; - } - - throw new IllegalStateException( - "Tried to delete view [" - + tag - + "] of parent [" - + parentTag - + "] at index " - + index - + ", but got view tag " - + actualTag - + " - actual index of view: " - + tagActualIndex); - } - - try { - viewGroupManager.removeViewAt(parentView, index); - } catch (RuntimeException e) { - // Note: `getChildCount` may not always be accurate! - // We don't currently have a good explanation other than, in situations where you - // would empirically expect to see childCount > 0, the childCount is reported as 0. - // This is likely due to a ViewManager overriding getChildCount or some other methods - // in a way that is strictly incorrect, but potentially only visible here. - // The failure mode is actually that in `removeViewAt`, a NullPointerException is - // thrown when we try to perform an operation on a View that doesn't exist, and - // is therefore null. - // We try to add some extra diagnostics here, but we always try to remove the View - // from the hierarchy first because detecting by looking at childCount will not work. - // - // Note that the lesson here is that `getChildCount` is not /required/ to adhere to - // any invariants. If you add 9 children to a parent, the `getChildCount` of the parent - // may not be equal to 9. This apparently causes no issues with Android and is common - // enough that we shouldn't try to change this invariant, without a lot of thought. - int childCount = viewGroupManager.getChildCount(parentView); - - throw new IllegalStateException( - "Cannot remove child at index " - + index - + " from parent ViewGroup [" - + parentView.getId() - + "], only " - + childCount - + " children in parent. Warning: childCount may be incorrect!", - e); - } - - // Display children after deleting any - if (SHOW_CHANGED_VIEW_HIERARCHIES) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - FLog.e( - TAG, - "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); - logViewHierarchy(parentView); - } - }); } + return null; } - @UiThread - public void createView( - @NonNull ThemedReactContext themedReactContext, - @NonNull String componentName, - int reactTag, - @Nullable ReadableMap props, - @Nullable StateWrapper stateWrapper, - boolean isLayoutable) { - if (getNullableViewState(reactTag) != null) { - return; - } - - View view = null; - ViewManager viewManager = null; - - ReactStylesDiffMap propsDiffMap = null; - if (props != null) { - propsDiffMap = new ReactStylesDiffMap(props); - } + @NonNull + @AnyThread + public SurfaceMountingManager getSurfaceManagerForViewEnforced(int reactTag) { + SurfaceMountingManager surfaceMountingManager = getSurfaceManagerForView(reactTag); - if (isLayoutable) { - viewManager = mViewManagerRegistry.get(componentName); - // View Managers are responsible for dealing with initial state and props. - view = - viewManager.createView( - themedReactContext, propsDiffMap, stateWrapper, mJSResponderHandler); - view.setId(reactTag); + if (surfaceMountingManager == null) { + throw new RetryableMountingLayerException( + "Unable to find SurfaceMountingManager for tag: [" + reactTag + "]"); } - ViewState viewState = new ViewState(reactTag, view, viewManager); - viewState.mCurrentProps = propsDiffMap; - viewState.mCurrentState = (stateWrapper != null ? stateWrapper.getState() : null); - - mTagToViewState.put(reactTag, viewState); + return surfaceMountingManager; } - @UiThread - public void updateProps(int reactTag, @Nullable ReadableMap props) { - if (props == null) { - return; - } - UiThreadUtil.assertOnUiThread(); - ViewState viewState = getViewState(reactTag); - viewState.mCurrentProps = new ReactStylesDiffMap(props); - View view = viewState.mView; - - if (view == null) { - throw new IllegalStateException("Unable to find view for tag " + reactTag); - } - - Assertions.assertNotNull(viewState.mViewManager) - .updateProperties(view, viewState.mCurrentProps); + public boolean getViewExists(int reactTag) { + return getSurfaceManagerForView(reactTag) != null; } - @UiThread - public void updateLayout(int reactTag, int x, int y, int width, int height) { + @Deprecated + public void receiveCommand( + int surfaceId, int reactTag, int commandId, @Nullable ReadableArray commandArgs) { UiThreadUtil.assertOnUiThread(); - - ViewState viewState = getViewState(reactTag); - // Do not layout Root Views - if (viewState.mIsRoot) { - return; - } - - View viewToUpdate = viewState.mView; - if (viewToUpdate == null) { - throw new IllegalStateException("Unable to find View for tag: " + reactTag); - } - - viewToUpdate.measure( - View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); - - ViewParent parent = viewToUpdate.getParent(); - if (parent instanceof RootView) { - parent.requestLayout(); - } - - // TODO: T31905686 Check if the parent of the view has to layout the view, or the child has - // to lay itself out. see NativeViewHierarchyManager.updateLayout - viewToUpdate.layout(x, y, x + width, y + height); + getSurfaceManagerEnforced(surfaceId, "receiveCommand:int") + .receiveCommand(reactTag, commandId, commandArgs); } - @UiThread - public void updatePadding(int reactTag, int left, int top, int right, int bottom) { + public void receiveCommand( + int surfaceId, int reactTag, @NonNull String commandId, @Nullable ReadableArray commandArgs) { UiThreadUtil.assertOnUiThread(); - - ViewState viewState = getViewState(reactTag); - // Do not layout Root Views - if (viewState.mIsRoot) { - return; - } - - View viewToUpdate = viewState.mView; - if (viewToUpdate == null) { - throw new IllegalStateException("Unable to find View for tag: " + reactTag); - } - - ViewManager viewManager = viewState.mViewManager; - if (viewManager == null) { - throw new IllegalStateException("Unable to find ViewManager for view: " + viewState); - } - - //noinspection unchecked - viewManager.setPadding(viewToUpdate, left, top, right, bottom); + getSurfaceManagerEnforced(surfaceId, "receiveCommand:string") + .receiveCommand(reactTag, commandId, commandArgs); } - @UiThread - public void deleteView(int reactTag) { + /** + * Send an accessibility eventType to a Native View. eventType is any valid `AccessibilityEvent.X` + * value. + * + *

Why accept `-1` SurfaceId? Currently there are calls to + * UIManagerModule.sendAccessibilityEvent which is a legacy API and accepts only reactTag. We will + * have to investigate and migrate away from those calls over time. + * + * @param surfaceId + * @param reactTag + * @param eventType + */ + public void sendAccessibilityEvent(int surfaceId, int reactTag, int eventType) { UiThreadUtil.assertOnUiThread(); - ViewState viewState = getNullableViewState(reactTag); - - if (viewState == null) { - ReactSoftException.logSoftException( - MountingManager.TAG, - new IllegalStateException( - "Unable to find viewState for tag: " + reactTag + " for deleteView")); - return; - } - - View view = viewState.mView; - - if (view != null) { - dropView(view, false); + if (surfaceId == View.NO_ID) { + getSurfaceManagerForViewEnforced(reactTag).sendAccessibilityEvent(reactTag, eventType); } else { - mTagToViewState.remove(reactTag); + getSurfaceManagerEnforced(surfaceId, "sendAccessibilityEvent") + .sendAccessibilityEvent(reactTag, eventType); } } @UiThread - public void updateState(final int reactTag, @Nullable StateWrapper stateWrapper) { + public void updateProps(int reactTag, @Nullable ReadableMap props) { UiThreadUtil.assertOnUiThread(); - ViewState viewState = getViewState(reactTag); - @Nullable ReadableNativeMap newState = stateWrapper == null ? null : stateWrapper.getState(); - - viewState.mCurrentState = newState; - - ViewManager viewManager = viewState.mViewManager; - - if (viewManager == null) { - throw new IllegalStateException("Unable to find ViewManager for tag: " + reactTag); - } - Object extraData = - viewManager.updateState(viewState.mView, viewState.mCurrentProps, stateWrapper); - if (extraData != null) { - viewManager.updateExtraData(viewState.mView, extraData); - } - } - - @UiThread - public void preallocateView( - @NonNull ThemedReactContext reactContext, - String componentName, - int reactTag, - @Nullable ReadableMap props, - @Nullable StateWrapper stateWrapper, - boolean isLayoutable) { - - if (getNullableViewState(reactTag) != null) { - throw new IllegalStateException( - "View for component " + componentName + " with tag " + reactTag + " already exists."); + if (props == null) { + return; } - createView(reactContext, componentName, reactTag, props, stateWrapper, isLayoutable); - } - - @UiThread - public void updateEventEmitter(int reactTag, @NonNull EventEmitterWrapper eventEmitter) { - UiThreadUtil.assertOnUiThread(); - ViewState viewState = mTagToViewState.get(reactTag); - if (viewState == null) { - // TODO T62717437 - Use a flag to determine that these event emitters belong to virtual nodes - // only. - viewState = new ViewState(reactTag, null, null); - mTagToViewState.put(reactTag, viewState); - } - viewState.mEventEmitter = eventEmitter; + getSurfaceManagerForViewEnforced(reactTag).updateProps(reactTag, props); } /** @@ -655,43 +289,53 @@ public void updateEventEmitter(int reactTag, @NonNull EventEmitterWrapper eventE */ @UiThread public synchronized void setJSResponder( - int reactTag, int initialReactTag, boolean blockNativeResponder) { - if (!blockNativeResponder) { - mJSResponderHandler.setJSResponder(initialReactTag, null); - return; - } - - ViewState viewState = getViewState(reactTag); - View view = viewState.mView; - if (initialReactTag != reactTag && view instanceof ViewParent) { - // In this case, initialReactTag corresponds to a virtual/layout-only View, and we already - // have a parent of that View in reactTag, so we can use it. - mJSResponderHandler.setJSResponder(initialReactTag, (ViewParent) view); - return; - } else if (view == null) { - SoftAssertions.assertUnreachable("Cannot find view for tag " + reactTag + "."); - return; - } + int surfaceId, int reactTag, int initialReactTag, boolean blockNativeResponder) { + UiThreadUtil.assertOnUiThread(); - if (viewState.mIsRoot) { - SoftAssertions.assertUnreachable( - "Cannot block native responder on " + reactTag + " that is a root view"); - } - mJSResponderHandler.setJSResponder(initialReactTag, view.getParent()); + getSurfaceManagerEnforced(surfaceId, "setJSResponder") + .setJSResponder(reactTag, initialReactTag, blockNativeResponder); } /** - * Clears the JS Responder specified by {@link #setJSResponder(int, int, boolean)}. After this - * method is called, all the touch events are going to be handled by JS. + * Clears the JS Responder specified by {@link #setJSResponder(int, int, int, boolean)}. After + * this method is called, all the touch events are going to be handled by JS. */ @UiThread public void clearJSResponder() { mJSResponderHandler.clearJSResponder(); } + @AnyThread + @ThreadConfined(ANY) + public @Nullable EventEmitterWrapper getEventEmitter(int surfaceId, int reactTag) { + SurfaceMountingManager surfaceMountingManager = + (surfaceId == -1 ? getSurfaceManagerForView(reactTag) : getSurfaceManager(surfaceId)); + if (surfaceMountingManager == null) { + return null; + } + return surfaceMountingManager.getEventEmitter(reactTag); + } + + /** + * Measure a component, given localData, props, state, and measurement information. This needs to + * remain here for now - and not in SurfaceMountingManager - because sometimes measures are made + * outside of the context of a Surface; especially from C++ before StartSurface is called. + * + * @param context + * @param componentName + * @param localData + * @param props + * @param state + * @param width + * @param widthMode + * @param height + * @param heightMode + * @param attachmentsPositions + * @return + */ @AnyThread public long measure( - @NonNull Context context, + @NonNull ReactContext context, @NonNull String componentName, @NonNull ReadableMap localData, @NonNull ReadableMap props, @@ -716,53 +360,7 @@ public long measure( attachmentsPositions); } - @AnyThread - @ThreadConfined(ANY) - public @Nullable EventEmitterWrapper getEventEmitter(int reactTag) { - ViewState viewState = getNullableViewState(reactTag); - return viewState == null ? null : viewState.mEventEmitter; - } - - /** - * This class holds view state for react tags. Objects of this class are stored into the {@link - * #mTagToViewState}, and they should be updated in the same thread. - */ - private static class ViewState { - @Nullable final View mView; - final int mReactTag; - final boolean mIsRoot; - @Nullable final ViewManager mViewManager; - @Nullable public ReactStylesDiffMap mCurrentProps = null; - @Nullable public ReadableMap mCurrentLocalData = null; - @Nullable public ReadableMap mCurrentState = null; - @Nullable public EventEmitterWrapper mEventEmitter = null; - - private ViewState(int reactTag, @Nullable View view, @Nullable ViewManager viewManager) { - this(reactTag, view, viewManager, false); - } - - private ViewState(int reactTag, @Nullable View view, ViewManager viewManager, boolean isRoot) { - mReactTag = reactTag; - mView = view; - mIsRoot = isRoot; - mViewManager = viewManager; - } - - @Override - public String toString() { - boolean isLayoutOnly = mViewManager == null; - return "ViewState [" - + mReactTag - + "] - isRoot: " - + mIsRoot - + " - props: " - + mCurrentProps - + " - localData: " - + mCurrentLocalData - + " - viewManager: " - + mViewManager - + " - isLayoutOnly: " - + isLayoutOnly; - } + public void initializeViewManager(String componentName) { + mViewManagerRegistry.get(componentName); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java new file mode 100644 index 00000000000000..d5d937f8eda26c --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -0,0 +1,838 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.fabric.mounting; + +import static com.facebook.infer.annotation.ThreadConfined.ANY; + +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import androidx.annotation.AnyThread; +import androidx.annotation.NonNull; +import androidx.annotation.UiThread; +import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Assertions; +import com.facebook.infer.annotation.ThreadConfined; +import com.facebook.react.bridge.ReactSoftException; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableNativeMap; +import com.facebook.react.bridge.RetryableMountingLayerException; +import com.facebook.react.bridge.SoftAssertions; +import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.common.build.ReactBuildConfig; +import com.facebook.react.fabric.events.EventEmitterWrapper; +import com.facebook.react.touch.JSResponderHandler; +import com.facebook.react.uimanager.IllegalViewOperationException; +import com.facebook.react.uimanager.ReactRoot; +import com.facebook.react.uimanager.ReactStylesDiffMap; +import com.facebook.react.uimanager.RootView; +import com.facebook.react.uimanager.RootViewManager; +import com.facebook.react.uimanager.StateWrapper; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.ViewManager; +import com.facebook.react.uimanager.ViewManagerRegistry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; + +public class SurfaceMountingManager { + public static final String TAG = SurfaceMountingManager.class.getSimpleName(); + + private static final boolean SHOW_CHANGED_VIEW_HIERARCHIES = ReactBuildConfig.DEBUG && false; + + private volatile boolean mIsStopped = false; + + @NonNull private final ThemedReactContext mThemedReactContext; + + // These are all non-null, until StopSurface is called + private ConcurrentHashMap mTagToViewState = + new ConcurrentHashMap<>(); // any thread + private JSResponderHandler mJSResponderHandler; + private ViewManagerRegistry mViewManagerRegistry; + private RootViewManager mRootViewManager; + + // This is null *until* StopSurface is called. + private Set mTagSetForStoppedSurface; + private long mLastSuccessfulQueryTime = -1; + + private final int mSurfaceId; + + public SurfaceMountingManager( + int surfaceId, + @NonNull final View rootView, + @NonNull JSResponderHandler jsResponderHandler, + @NonNull ViewManagerRegistry viewManagerRegistry, + @NonNull RootViewManager rootViewManager, + @NonNull ThemedReactContext context) { + mSurfaceId = surfaceId; + mJSResponderHandler = jsResponderHandler; + mViewManagerRegistry = viewManagerRegistry; + mRootViewManager = rootViewManager; + mThemedReactContext = context; + + addRootView(rootView); + } + + public boolean isStopped() { + return mIsStopped; + } + + public ThemedReactContext getContext() { + return mThemedReactContext; + } + + private static void logViewHierarchy(ViewGroup parent, boolean recurse) { + int parentTag = parent.getId(); + FLog.e(TAG, " "); + for (int i = 0; i < parent.getChildCount(); i++) { + FLog.e( + TAG, + " "); + } + FLog.e(TAG, " "); + + if (recurse) { + FLog.e(TAG, "Displaying Ancestors:"); + ViewParent ancestor = parent.getParent(); + while (ancestor != null) { + ViewGroup ancestorViewGroup = (ancestor instanceof ViewGroup ? (ViewGroup) ancestor : null); + int ancestorId = ancestorViewGroup == null ? View.NO_ID : ancestorViewGroup.getId(); + FLog.e( + TAG, + ""); + ancestor = ancestor.getParent(); + } + } + } + + public boolean getViewExists(int tag) { + // If Surface stopped, check if tag *was* associated with this Surface, even though it's been + // deleted. This helps distinguish between scenarios where an invalid tag is referenced, vs + // race conditions where an imperative method is called on a tag during/just after StopSurface. + if (mTagSetForStoppedSurface != null && mTagSetForStoppedSurface.contains(tag)) { + mLastSuccessfulQueryTime = System.currentTimeMillis(); + return true; + } + if (mTagToViewState == null) { + return false; + } + return mTagToViewState.containsKey(tag); + } + + @AnyThread + private void addRootView(@NonNull final View rootView) { + // Since this is called from the constructor, we know the surface cannot have stopped yet. + mTagToViewState.put(mSurfaceId, new ViewState(mSurfaceId, rootView, mRootViewManager, true)); + + Runnable runnable = + new Runnable() { + @Override + public void run() { + // The CPU has ticked since `addRootView` was called, so the surface could technically + // have already stopped here. + if (isStopped()) { + return; + } + + if (rootView.getId() == mSurfaceId) { + ReactSoftException.logSoftException( + TAG, + new IllegalViewOperationException( + "Race condition in addRootView detected. Trying to set an id of [" + + mSurfaceId + + "] on the RootView, but that id has already been set. ")); + } else if (rootView.getId() != View.NO_ID) { + FLog.e( + TAG, + "Trying to add RootTag to RootView that already has a tag: existing tag: [%d] new tag: [%d]", + rootView.getId(), + mSurfaceId); + throw new IllegalViewOperationException( + "Trying to add a root view with an explicit id already set. React Native uses " + + "the id field to track react tags and will overwrite this field. If that is fine, " + + "explicitly overwrite the id field to View.NO_ID before calling addRootView."); + } + rootView.setId(mSurfaceId); + + if (rootView instanceof ReactRoot) { + ((ReactRoot) rootView).setRootViewTag(mSurfaceId); + } + } + }; + + if (UiThreadUtil.isOnUiThread()) { + runnable.run(); + } else { + UiThreadUtil.runOnUiThread(runnable); + } + } + + /** + * Stop surface and all operations within it. Garbage-collect Views (caller is responsible for + * removing RootView from View layer). + * + *

Delete rootView from cache. Since RN does not control the RootView, in a sense, the fragment + * is responsible for actually removing the RootView from the hierarchy / tearing down the + * fragment. + * + *

In the original version(s) of this function, we recursively went through all children of the + * View and dropped those Views as well; ad infinitum. This was before we had a + * SurfaceMountingManager, and all tags were in one global map. Doing this was particularly + * important in the case of StopSurface, where race conditions between threads meant you couldn't + * rely on DELETE instructions actually deleting all Views in the Surface. + * + *

Now that we have SurfaceMountingManager, we can simply drop our local reference to the View. + * Since it will be removed from the View hierarchy entirely (outside of the scope of this class), + * garbage collection will take care of destroying it and all descendents. + */ + @AnyThread + public void stopSurface() { + if (isStopped()) { + return; + } + + // Prevent more views from being created, or the hierarchy from being manipulated at all + mIsStopped = true; + + Runnable runnable = + new Runnable() { + @Override + public void run() { + // Evict all views from cache and memory + mLastSuccessfulQueryTime = System.currentTimeMillis(); + mTagSetForStoppedSurface = mTagToViewState.keySet(); + mTagToViewState = null; + mJSResponderHandler = null; + mRootViewManager = null; + } + }; + + if (UiThreadUtil.isOnUiThread()) { + runnable.run(); + } else { + UiThreadUtil.runOnUiThread(runnable); + } + } + + @UiThread + public void addViewAt(final int parentTag, final int tag, final int index) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + ViewState parentViewState = getViewState(parentTag); + if (!(parentViewState.mView instanceof ViewGroup)) { + String message = + "Unable to add a view into a view that is not a ViewGroup. ParentTag: " + + parentTag + + " - Tag: " + + tag + + " - Index: " + + index; + FLog.e(TAG, message); + throw new IllegalStateException(message); + } + final ViewGroup parentView = (ViewGroup) parentViewState.mView; + ViewState viewState = getViewState(tag); + final View view = viewState.mView; + if (view == null) { + throw new IllegalStateException( + "Unable to find view for viewState " + viewState + " and tag " + tag); + } + + // Display children before inserting + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + FLog.e(TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); + logViewHierarchy(parentView, false); + } + + try { + getViewGroupManager(parentViewState).addView(parentView, view, index); + } catch (IllegalStateException e) { + // Wrap error with more context for debugging + throw new IllegalStateException( + "addViewAt: failed to insert view [" + + tag + + "] into parent [" + + parentTag + + "] at index " + + index, + e); + } + + // Display children after inserting + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + // Why are we calling `runOnUiThread`? We're already on the UI thread, right?! + // Yes - but if you get the children of the View here and display them, *it might show you + // the previous children*. Without getting too much into Android internals, basically if we + // wait a tick, everything is what we expect. + // tldr is that `parent.children == []; parent.addView(x); parent.children == []` + // and you need to wait a tick for `parent.children == [x]`. + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + FLog.e( + TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); + logViewHierarchy(parentView, false); + } + }); + } + } + + @UiThread + public void removeViewAt(final int tag, final int parentTag, int index) { + if (isStopped()) { + return; + } + + UiThreadUtil.assertOnUiThread(); + ViewState viewState = getNullableViewState(parentTag); + + // TODO: throw exception here? + if (viewState == null) { + ReactSoftException.logSoftException( + MountingManager.TAG, + new IllegalStateException( + "Unable to find viewState for tag: [" + parentTag + "] for removeViewAt")); + return; + } + + final ViewGroup parentView = (ViewGroup) viewState.mView; + + if (parentView == null) { + throw new IllegalStateException("Unable to find view for tag [" + parentTag + "]"); + } + + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + // Display children before deleting any + FLog.e(TAG, "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); + logViewHierarchy(parentView, false); + } + + ViewGroupManager viewGroupManager = getViewGroupManager(viewState); + + // Verify that the view we're about to remove has the same tag we expect + View view = viewGroupManager.getChildAt(parentView, index); + int actualTag = (view != null ? view.getId() : -1); + if (actualTag != tag) { + int tagActualIndex = -1; + int parentChildrenCount = parentView.getChildCount(); + for (int i = 0; i < parentChildrenCount; i++) { + if (parentView.getChildAt(i).getId() == tag) { + tagActualIndex = i; + break; + } + } + + // TODO T74425739: previously, we did not do this check and `removeViewAt` would be executed + // below, sometimes crashing there. *However*, interestingly enough, `removeViewAt` would not + // complain if you removed views from an already-empty parent. This seems necessary currently + // for certain ViewManagers that remove their own children - like BottomSheet? + // This workaround seems not-great, but for now, we just return here for + // backwards-compatibility. Essentially, if a view has already been removed from the + // hierarchy, we treat it as a noop. + if (tagActualIndex == -1) { + FLog.e( + TAG, + "removeViewAt: [" + + tag + + "] -> [" + + parentTag + + "] @" + + index + + ": view already removed from parent! Children in parent: " + + parentChildrenCount); + return; + } + + // Here we are guaranteed that the view is still in the View hierarchy, just + // at a different index. In debug mode we'll crash here; in production, we'll remove + // the child from the parent and move on. + // This is an issue that is safely recoverable 95% of the time. If this allows corruption + // of the view hierarchy and causes bugs or a crash after this point, there will be logs + // indicating that this happened. + // This is likely *only* necessary because of Fabric's LayoutAnimations implementation. + // If we can fix the bug there, or remove the need for LayoutAnimation index adjustment + // entirely, we can just throw this exception without regression user experience. + logViewHierarchy(parentView, true); + ReactSoftException.logSoftException( + TAG, + new IllegalStateException( + "Tried to remove view [" + + tag + + "] of parent [" + + parentTag + + "] at index " + + index + + ", but got view tag " + + actualTag + + " - actual index of view: " + + tagActualIndex)); + index = tagActualIndex; + } + + try { + viewGroupManager.removeViewAt(parentView, index); + } catch (RuntimeException e) { + // Note: `getChildCount` may not always be accurate! + // We don't currently have a good explanation other than, in situations where you + // would empirically expect to see childCount > 0, the childCount is reported as 0. + // This is likely due to a ViewManager overriding getChildCount or some other methods + // in a way that is strictly incorrect, but potentially only visible here. + // The failure mode is actually that in `removeViewAt`, a NullPointerException is + // thrown when we try to perform an operation on a View that doesn't exist, and + // is therefore null. + // We try to add some extra diagnostics here, but we always try to remove the View + // from the hierarchy first because detecting by looking at childCount will not work. + // + // Note that the lesson here is that `getChildCount` is not /required/ to adhere to + // any invariants. If you add 9 children to a parent, the `getChildCount` of the parent + // may not be equal to 9. This apparently causes no issues with Android and is common + // enough that we shouldn't try to change this invariant, without a lot of thought. + int childCount = viewGroupManager.getChildCount(parentView); + + logViewHierarchy(parentView, true); + + throw new IllegalStateException( + "Cannot remove child at index " + + index + + " from parent ViewGroup [" + + parentView.getId() + + "], only " + + childCount + + " children in parent. Warning: childCount may be incorrect!", + e); + } + + // Display children after deleting any + if (SHOW_CHANGED_VIEW_HIERARCHIES) { + final int finalIndex = index; + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + FLog.e( + TAG, + "removeViewAt: [" + + tag + + "] -> [" + + parentTag + + "] idx: " + + finalIndex + + " AFTER"); + logViewHierarchy(parentView, false); + } + }); + } + } + + @UiThread + public void createView( + @NonNull String componentName, + int reactTag, + @Nullable ReadableMap props, + @Nullable StateWrapper stateWrapper, + boolean isLayoutable) { + if (isStopped()) { + return; + } + if (getNullableViewState(reactTag) != null) { + return; + } + + View view = null; + ViewManager viewManager = null; + + ReactStylesDiffMap propsDiffMap = null; + if (props != null) { + propsDiffMap = new ReactStylesDiffMap(props); + } + + if (isLayoutable) { + viewManager = mViewManagerRegistry.get(componentName); + // View Managers are responsible for dealing with initial state and props. + view = + viewManager.createView( + reactTag, mThemedReactContext, propsDiffMap, stateWrapper, mJSResponderHandler); + view.setId(reactTag); + } + + ViewState viewState = new ViewState(reactTag, view, viewManager); + viewState.mCurrentProps = propsDiffMap; + viewState.mCurrentState = (stateWrapper != null ? stateWrapper.getState() : null); + + mTagToViewState.put(reactTag, viewState); + } + + public void updateProps(int reactTag, ReadableMap props) { + if (isStopped()) { + return; + } + + ViewState viewState = getViewState(reactTag); + viewState.mCurrentProps = new ReactStylesDiffMap(props); + View view = viewState.mView; + + if (view == null) { + throw new IllegalStateException("Unable to find view for tag [" + reactTag + "]"); + } + + Assertions.assertNotNull(viewState.mViewManager) + .updateProperties(view, viewState.mCurrentProps); + } + + @Deprecated + public void receiveCommand(int reactTag, int commandId, @Nullable ReadableArray commandArgs) { + if (isStopped()) { + return; + } + + ViewState viewState = getNullableViewState(reactTag); + + // It's not uncommon for JS to send events as/after a component is being removed from the + // view hierarchy. For example, TextInput may send a "blur" command in response to the view + // disappearing. Throw `ReactNoCrashSoftException` so they're logged but don't crash in dev + // for now. + if (viewState == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState for tag: [" + reactTag + "] for commandId: " + commandId); + } + + if (viewState.mViewManager == null) { + throw new RetryableMountingLayerException("Unable to find viewManager for tag " + reactTag); + } + + if (viewState.mView == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState view for tag " + reactTag); + } + + viewState.mViewManager.receiveCommand(viewState.mView, commandId, commandArgs); + } + + public void receiveCommand( + int reactTag, @NonNull String commandId, @Nullable ReadableArray commandArgs) { + if (isStopped()) { + return; + } + + ViewState viewState = getNullableViewState(reactTag); + + // It's not uncommon for JS to send events as/after a component is being removed from the + // view hierarchy. For example, TextInput may send a "blur" command in response to the view + // disappearing. Throw `ReactNoCrashSoftException` so they're logged but don't crash in dev + // for now. + if (viewState == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState for tag: " + reactTag + " for commandId: " + commandId); + } + + if (viewState.mViewManager == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState manager for tag " + reactTag); + } + + if (viewState.mView == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState view for tag " + reactTag); + } + + viewState.mViewManager.receiveCommand(viewState.mView, commandId, commandArgs); + } + + public void sendAccessibilityEvent(int reactTag, int eventType) { + if (isStopped()) { + return; + } + + ViewState viewState = getViewState(reactTag); + + if (viewState.mViewManager == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState manager for tag " + reactTag); + } + + if (viewState.mView == null) { + throw new RetryableMountingLayerException( + "Unable to find viewState view for tag " + reactTag); + } + + viewState.mView.sendAccessibilityEvent(eventType); + } + + @UiThread + public void updateLayout(int reactTag, int x, int y, int width, int height, int displayType) { + if (isStopped()) { + return; + } + + ViewState viewState = getViewState(reactTag); + // Do not layout Root Views + if (viewState.mIsRoot) { + return; + } + + View viewToUpdate = viewState.mView; + if (viewToUpdate == null) { + throw new IllegalStateException("Unable to find View for tag: " + reactTag); + } + + viewToUpdate.measure( + View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); + + ViewParent parent = viewToUpdate.getParent(); + if (parent instanceof RootView) { + parent.requestLayout(); + } + + // TODO: T31905686 Check if the parent of the view has to layout the view, or the child has + // to lay itself out. see NativeViewHierarchyManager.updateLayout + viewToUpdate.layout(x, y, x + width, y + height); + + // displayType: 0 represents display: 'none' + int visibility = displayType == 0 ? View.INVISIBLE : View.VISIBLE; + if (viewToUpdate.getVisibility() != visibility) { + viewToUpdate.setVisibility(visibility); + } + } + + @UiThread + public void updatePadding(int reactTag, int left, int top, int right, int bottom) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + ViewState viewState = getViewState(reactTag); + // Do not layout Root Views + if (viewState.mIsRoot) { + return; + } + + View viewToUpdate = viewState.mView; + if (viewToUpdate == null) { + throw new IllegalStateException("Unable to find View for tag: " + reactTag); + } + + ViewManager viewManager = viewState.mViewManager; + if (viewManager == null) { + throw new IllegalStateException("Unable to find ViewManager for view: " + viewState); + } + + //noinspection unchecked + viewManager.setPadding(viewToUpdate, left, top, right, bottom); + } + + @UiThread + public void updateState(final int reactTag, @Nullable StateWrapper stateWrapper) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + ViewState viewState = getViewState(reactTag); + @Nullable ReadableNativeMap newState = stateWrapper == null ? null : stateWrapper.getState(); + + viewState.mCurrentState = newState; + + ViewManager viewManager = viewState.mViewManager; + + if (viewManager == null) { + throw new IllegalStateException("Unable to find ViewManager for tag: " + reactTag); + } + Object extraData = + viewManager.updateState(viewState.mView, viewState.mCurrentProps, stateWrapper); + if (extraData != null) { + viewManager.updateExtraData(viewState.mView, extraData); + } + } + + @UiThread + public void updateEventEmitter(int reactTag, @NonNull EventEmitterWrapper eventEmitter) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + ViewState viewState = mTagToViewState.get(reactTag); + if (viewState == null) { + // TODO T62717437 - Use a flag to determine that these event emitters belong to virtual nodes + // only. + viewState = new ViewState(reactTag, null, null); + mTagToViewState.put(reactTag, viewState); + } + viewState.mEventEmitter = eventEmitter; + } + + @UiThread + public synchronized void setJSResponder( + int reactTag, int initialReactTag, boolean blockNativeResponder) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + if (!blockNativeResponder) { + mJSResponderHandler.setJSResponder(initialReactTag, null); + return; + } + + ViewState viewState = getViewState(reactTag); + View view = viewState.mView; + if (initialReactTag != reactTag && view instanceof ViewParent) { + // In this case, initialReactTag corresponds to a virtual/layout-only View, and we already + // have a parent of that View in reactTag, so we can use it. + mJSResponderHandler.setJSResponder(initialReactTag, (ViewParent) view); + return; + } else if (view == null) { + SoftAssertions.assertUnreachable("Cannot find view for tag [" + reactTag + "]."); + return; + } + + if (viewState.mIsRoot) { + SoftAssertions.assertUnreachable( + "Cannot block native responder on [" + reactTag + "] that is a root view"); + } + mJSResponderHandler.setJSResponder(initialReactTag, view.getParent()); + } + + @UiThread + public void deleteView(int reactTag) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + ViewState viewState = getNullableViewState(reactTag); + + if (viewState == null) { + ReactSoftException.logSoftException( + MountingManager.TAG, + new IllegalStateException( + "Unable to find viewState for tag: " + reactTag + " for deleteView")); + return; + } + + // To delete we simply remove the tag from the registry. + // We want to rely on the correct set of MountInstructions being sent to the platform, + // or StopSurface being called, so we do not handle deleting descendents of the View. + mTagToViewState.remove(reactTag); + + // For non-root views we notify viewmanager with {@link ViewManager#onDropInstance} + ViewManager viewManager = viewState.mViewManager; + if (!viewState.mIsRoot && viewManager != null) { + viewManager.onDropViewInstance(viewState.mView); + } + } + + @UiThread + public void preallocateView( + String componentName, + int reactTag, + @Nullable ReadableMap props, + @Nullable StateWrapper stateWrapper, + boolean isLayoutable) { + UiThreadUtil.assertOnUiThread(); + if (isStopped()) { + return; + } + + if (getNullableViewState(reactTag) != null) { + throw new IllegalStateException( + "View for component " + componentName + " with tag " + reactTag + " already exists."); + } + + createView(componentName, reactTag, props, stateWrapper, isLayoutable); + } + + @AnyThread + @ThreadConfined(ANY) + public @Nullable EventEmitterWrapper getEventEmitter(int reactTag) { + ViewState viewState = getNullableViewState(reactTag); + return viewState == null ? null : viewState.mEventEmitter; + } + + @NonNull + private ViewState getViewState(int tag) { + ViewState viewState = mTagToViewState.get(tag); + if (viewState == null) { + throw new RetryableMountingLayerException("Unable to find viewState view for tag " + tag); + } + return viewState; + } + + private @Nullable ViewState getNullableViewState(int tag) { + if (mTagToViewState == null) { + return null; + } + return mTagToViewState.get(tag); + } + + @SuppressWarnings("unchecked") // prevents unchecked conversion warn of the type + private static @NonNull ViewGroupManager getViewGroupManager( + @NonNull ViewState viewState) { + if (viewState.mViewManager == null) { + throw new IllegalStateException("Unable to find ViewManager for view: " + viewState); + } + return (ViewGroupManager) viewState.mViewManager; + } + + /** + * This class holds view state for react tags. Objects of this class are stored into the {@link + * #mTagToViewState}, and they should be updated in the same thread. + */ + private static class ViewState { + @Nullable final View mView; + final int mReactTag; + final boolean mIsRoot; + @Nullable final ViewManager mViewManager; + @Nullable public ReactStylesDiffMap mCurrentProps = null; + @Nullable public ReadableMap mCurrentLocalData = null; + @Nullable public ReadableMap mCurrentState = null; + @Nullable public EventEmitterWrapper mEventEmitter = null; + + private ViewState(int reactTag, @Nullable View view, @Nullable ViewManager viewManager) { + this(reactTag, view, viewManager, false); + } + + private ViewState(int reactTag, @Nullable View view, ViewManager viewManager, boolean isRoot) { + mReactTag = reactTag; + mView = view; + mIsRoot = isRoot; + mViewManager = viewManager; + } + + @Override + public String toString() { + boolean isLayoutOnly = mViewManager == null; + return "ViewState [" + + mReactTag + + "] - isRoot: " + + mIsRoot + + " - props: " + + mCurrentProps + + " - localData: " + + mCurrentLocalData + + " - viewManager: " + + mViewManager + + " - isLayoutOnly: " + + isLayoutOnly; + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java deleted file mode 100644 index d685be1ae02868..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.react.bridge.ReactMarker; -import com.facebook.react.bridge.ReactMarkerConstants; -import com.facebook.react.fabric.mounting.MountingManager; -import com.facebook.systrace.Systrace; - -/** - * This class represents a batch of {@link MountItem}s - * - *

A MountItem batch contains an array of {@link MountItem} and a size. The size determines the - * amount of items that needs to be processed in the array. - * - *

The purpose of encapsulating the array of MountItems this way, is to reduce the amount of - * allocations in C++ - */ -@DoNotStrip -public class BatchMountItem implements MountItem { - static final String TAG = "FabricBatchMountItem"; - - private final int mRootTag; - @NonNull private final MountItem[] mMountItems; - - private final int mSize; - - private final int mCommitNumber; - - public BatchMountItem(int rootTag, MountItem[] items, int size, int commitNumber) { - int itemsLength = (items == null ? 0 : items.length); - if (size < 0 || size > itemsLength) { - throw new IllegalArgumentException( - "Invalid size received by parameter size: " + size + " items.size = " + itemsLength); - } - mRootTag = rootTag; - mMountItems = items; - mSize = size; - mCommitNumber = commitNumber; - } - - private void beginMarkers(String reason) { - Systrace.beginSection( - Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, - "FabricUIManager::" + reason + " - " + mSize + " items"); - - if (mCommitNumber > 0) { - ReactMarker.logFabricMarker( - ReactMarkerConstants.FABRIC_BATCH_EXECUTION_START, null, mCommitNumber); - } - } - - private void endMarkers() { - if (mCommitNumber > 0) { - ReactMarker.logFabricMarker( - ReactMarkerConstants.FABRIC_BATCH_EXECUTION_END, null, mCommitNumber); - } - - Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - beginMarkers("mountViews"); - - for (int mountItemIndex = 0; mountItemIndex < mSize; mountItemIndex++) { - mMountItems[mountItemIndex].execute(mountingManager); - } - - endMarkers(); - } - - public int getRootTag() { - return mRootTag; - } - - public int getSize() { - return mSize; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - for (int i = 0; i < mSize; i++) { - if (s.length() > 0) { - s.append("\n"); - } - s.append("BatchMountItem [S:" + mRootTag + "] (") - .append(i + 1) - .append("/") - .append(mSize) - .append("): ") - .append(mMountItems[i]); - } - return s.toString(); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/CreateMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/CreateMountItem.java deleted file mode 100644 index d96bab3326e086..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/CreateMountItem.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.fabric.mounting.MountingManager; -import com.facebook.react.uimanager.StateWrapper; -import com.facebook.react.uimanager.ThemedReactContext; - -public class CreateMountItem implements MountItem { - - @NonNull private final String mComponent; - private final int mRootTag; - private final int mReactTag; - @NonNull private final ThemedReactContext mContext; - private final @Nullable ReadableMap mProps; - private final @Nullable StateWrapper mStateWrapper; - private final boolean mIsLayoutable; - - public CreateMountItem( - @Nullable ThemedReactContext context, - int rootTag, - int reactTag, - @NonNull String component, - @Nullable ReadableMap props, - @NonNull StateWrapper stateWrapper, - boolean isLayoutable) { - mContext = context; - mComponent = component; - mRootTag = rootTag; - mReactTag = reactTag; - mProps = props; - mStateWrapper = stateWrapper; - mIsLayoutable = isLayoutable; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - if (mContext == null) { - throw new IllegalStateException( - "Cannot execute PreAllocateViewMountItem without Context for ReactTag: " - + mReactTag - + " and rootTag: " - + mRootTag); - } - mountingManager.createView( - mContext, mComponent, mReactTag, mProps, mStateWrapper, mIsLayoutable); - } - - @Override - public String toString() { - return "CreateMountItem [" - + mReactTag - + "] - component: " - + mComponent - + " - rootTag: " - + mRootTag - + " - isLayoutable: " - + mIsLayoutable; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchIntCommandMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchIntCommandMountItem.java index 9d525755bfa38e..6f23f9b8779985 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchIntCommandMountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchIntCommandMountItem.java @@ -14,20 +14,27 @@ public class DispatchIntCommandMountItem extends DispatchCommandMountItem { + private final int mSurfaceId; private final int mReactTag; private final int mCommandId; private final @Nullable ReadableArray mCommandArgs; public DispatchIntCommandMountItem( - int reactTag, int commandId, @Nullable ReadableArray commandArgs) { + int surfaceId, int reactTag, int commandId, @Nullable ReadableArray commandArgs) { + mSurfaceId = surfaceId; mReactTag = reactTag; mCommandId = commandId; mCommandArgs = commandArgs; } + @Override + public int getSurfaceId() { + return mSurfaceId; + } + @Override public void execute(@NonNull MountingManager mountingManager) { - mountingManager.receiveCommand(mReactTag, mCommandId, mCommandArgs); + mountingManager.receiveCommand(mSurfaceId, mReactTag, mCommandId, mCommandArgs); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchStringCommandMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchStringCommandMountItem.java index 0b04e25f161d0e..1d76091b6ae031 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchStringCommandMountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/DispatchStringCommandMountItem.java @@ -14,20 +14,27 @@ public class DispatchStringCommandMountItem extends DispatchCommandMountItem { + private final int mSurfaceId; private final int mReactTag; @NonNull private final String mCommandId; private final @Nullable ReadableArray mCommandArgs; public DispatchStringCommandMountItem( - int reactTag, @NonNull String commandId, @Nullable ReadableArray commandArgs) { + int surfaceId, int reactTag, @NonNull String commandId, @Nullable ReadableArray commandArgs) { + mSurfaceId = surfaceId; mReactTag = reactTag; mCommandId = commandId; mCommandArgs = commandArgs; } + @Override + public int getSurfaceId() { + return mSurfaceId; + } + @Override public void execute(@NonNull MountingManager mountingManager) { - mountingManager.receiveCommand(mReactTag, mCommandId, mCommandArgs); + mountingManager.receiveCommand(mSurfaceId, mReactTag, mCommandId, mCommandArgs); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/InsertMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/InsertMountItem.java deleted file mode 100644 index edfc46ac7109cf..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/InsertMountItem.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import com.facebook.react.fabric.mounting.MountingManager; - -public class InsertMountItem implements MountItem { - - private int mReactTag; - private int mParentReactTag; - private int mIndex; - - public InsertMountItem(int reactTag, int parentReactTag, int index) { - mReactTag = reactTag; - mParentReactTag = parentReactTag; - mIndex = index; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.addViewAt(mParentReactTag, mReactTag, mIndex); - } - - public int getParentReactTag() { - return mParentReactTag; - } - - public int getIndex() { - return mIndex; - } - - @Override - public String toString() { - return "InsertMountItem [" - + mReactTag - + "] - parentTag: [" - + mParentReactTag - + "] - index: " - + mIndex; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java new file mode 100644 index 00000000000000..311a08143ea3be --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.fabric.mounting.mountitems; + +import static com.facebook.react.fabric.FabricComponents.getFabricComponentName; +import static com.facebook.react.fabric.FabricUIManager.ENABLE_FABRIC_LOGS; +import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT; + +import androidx.annotation.NonNull; +import com.facebook.common.logging.FLog; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactMarker; +import com.facebook.react.bridge.ReactMarkerConstants; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.fabric.events.EventEmitterWrapper; +import com.facebook.react.fabric.mounting.MountingManager; +import com.facebook.react.fabric.mounting.SurfaceMountingManager; +import com.facebook.react.uimanager.StateWrapper; +import com.facebook.systrace.Systrace; + +/** + * This class represents a batch of {@link MountItem}s, represented directly as int buffers to + * remove the need for actual MountItem instances. + * + *

An IntBufferBatchMountItem batch contains an array of ints, indicating the mount actions that + * should be taken, and a size; as well as an array of Objects, and a corresponding array size, for + * any data that cannot be passed as a raw int. + * + *

The purpose of encapsulating the array of MountItems this way, is to reduce the amount of + * allocations in C++ and JNI round-trips. + */ +@DoNotStrip +public class IntBufferBatchMountItem implements MountItem { + static final String TAG = IntBufferBatchMountItem.class.getSimpleName(); + + static final int INSTRUCTION_FLAG_MULTIPLE = 1; + + static final int INSTRUCTION_CREATE = 2; + static final int INSTRUCTION_DELETE = 4; + static final int INSTRUCTION_INSERT = 8; + static final int INSTRUCTION_REMOVE = 16; + static final int INSTRUCTION_UPDATE_PROPS = 32; + static final int INSTRUCTION_UPDATE_STATE = 64; + static final int INSTRUCTION_UPDATE_LAYOUT = 128; + static final int INSTRUCTION_UPDATE_EVENT_EMITTER = 256; + static final int INSTRUCTION_UPDATE_PADDING = 512; + + private final int mSurfaceId; + private final int mCommitNumber; + + @NonNull private final int[] mIntBuffer; + @NonNull private final Object[] mObjBuffer; + + private final int mIntBufferLen; + private final int mObjBufferLen; + + public IntBufferBatchMountItem(int surfaceId, int[] intBuf, Object[] objBuf, int commitNumber) { + mSurfaceId = surfaceId; + mCommitNumber = commitNumber; + + mIntBuffer = intBuf; + mObjBuffer = objBuf; + + mIntBufferLen = mIntBuffer != null ? mIntBuffer.length : 0; + mObjBufferLen = mObjBuffer != null ? mObjBuffer.length : 0; + } + + private void beginMarkers(String reason) { + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, + "FabricUIManager::" + + reason + + " - " + + mIntBufferLen + + " intBufSize " + + " - " + + mObjBufferLen + + " objBufSize"); + + if (mCommitNumber > 0) { + ReactMarker.logFabricMarker( + ReactMarkerConstants.FABRIC_BATCH_EXECUTION_START, null, mCommitNumber); + } + } + + private void endMarkers() { + if (mCommitNumber > 0) { + ReactMarker.logFabricMarker( + ReactMarkerConstants.FABRIC_BATCH_EXECUTION_END, null, mCommitNumber); + } + + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } + + private static StateWrapper castToState(Object obj) { + return obj != null ? (StateWrapper) obj : null; + } + + private static ReadableMap castToProps(Object obj) { + return obj != null ? (ReadableMap) obj : null; + } + + private static EventEmitterWrapper castToEventEmitter(Object obj) { + return obj != null ? (EventEmitterWrapper) obj : null; + } + + @Override + public void execute(@NonNull MountingManager mountingManager) { + SurfaceMountingManager surfaceMountingManager = mountingManager.getSurfaceManager(mSurfaceId); + if (surfaceMountingManager == null) { + FLog.e( + TAG, + "Skipping batch of MountItems; no SurfaceMountingManager found for [%d].", + mSurfaceId); + return; + } + if (surfaceMountingManager.isStopped()) { + FLog.e(TAG, "Skipping batch of MountItems; was stopped [%d].", mSurfaceId); + return; + } + if (ENABLE_FABRIC_LOGS) { + FLog.d(TAG, "Executing IntBufferBatchMountItem on surface [%d]", mSurfaceId); + } + + beginMarkers("mountViews"); + + int i = 0, j = 0; + while (i < mIntBufferLen) { + int rawType = mIntBuffer[i++]; + int type = rawType & ~INSTRUCTION_FLAG_MULTIPLE; + int numInstructions = ((rawType & INSTRUCTION_FLAG_MULTIPLE) != 0 ? mIntBuffer[i++] : 1); + for (int k = 0; k < numInstructions; k++) { + if (type == INSTRUCTION_CREATE) { + String componentName = getFabricComponentName((String) mObjBuffer[j++]); + surfaceMountingManager.createView( + componentName, + mIntBuffer[i++], + castToProps(mObjBuffer[j++]), + castToState(mObjBuffer[j++]), + mIntBuffer[i++] == 1); + } else if (type == INSTRUCTION_DELETE) { + surfaceMountingManager.deleteView(mIntBuffer[i++]); + } else if (type == INSTRUCTION_INSERT) { + int tag = mIntBuffer[i++]; + int parentTag = mIntBuffer[i++]; + surfaceMountingManager.addViewAt(parentTag, tag, mIntBuffer[i++]); + } else if (type == INSTRUCTION_REMOVE) { + surfaceMountingManager.removeViewAt(mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++]); + } else if (type == INSTRUCTION_UPDATE_PROPS) { + surfaceMountingManager.updateProps(mIntBuffer[i++], castToProps(mObjBuffer[j++])); + } else if (type == INSTRUCTION_UPDATE_STATE) { + surfaceMountingManager.updateState(mIntBuffer[i++], castToState(mObjBuffer[j++])); + } else if (type == INSTRUCTION_UPDATE_LAYOUT) { + int reactTag = mIntBuffer[i++]; + int x = mIntBuffer[i++]; + int y = mIntBuffer[i++]; + int width = mIntBuffer[i++]; + int height = mIntBuffer[i++]; + // The final buffer, layoutDirection, seems unused? + i++; + int displayType = mIntBuffer[i++]; + surfaceMountingManager.updateLayout(reactTag, x, y, width, height, displayType); + + } else if (type == INSTRUCTION_UPDATE_PADDING) { + surfaceMountingManager.updatePadding( + mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++]); + } else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) { + surfaceMountingManager.updateEventEmitter( + mIntBuffer[i++], castToEventEmitter(mObjBuffer[j++])); + } else { + throw new IllegalArgumentException( + "Invalid type argument to IntBufferBatchMountItem: " + type + " at index: " + i); + } + } + } + + endMarkers(); + } + + @Override + public int getSurfaceId() { + return mSurfaceId; + } + + public boolean shouldSchedule() { + return mIntBufferLen != 0; + } + + @Override + public String toString() { + try { + StringBuilder s = new StringBuilder(); + s.append("IntBufferBatchMountItem:"); + int i = 0, j = 0; + while (i < mIntBufferLen) { + int rawType = mIntBuffer[i++]; + int type = rawType & ~INSTRUCTION_FLAG_MULTIPLE; + int numInstructions = ((rawType & INSTRUCTION_FLAG_MULTIPLE) != 0 ? mIntBuffer[i++] : 1); + for (int k = 0; k < numInstructions; k++) { + if (type == INSTRUCTION_CREATE) { + String componentName = getFabricComponentName((String) mObjBuffer[j++]); + j += 2; + s.append( + String.format( + "CREATE [%d] - layoutable:%d - %s\n", + mIntBuffer[i++], mIntBuffer[i++], componentName)); + } else if (type == INSTRUCTION_DELETE) { + s.append(String.format("DELETE [%d]\n", mIntBuffer[i++])); + } else if (type == INSTRUCTION_INSERT) { + s.append( + String.format( + "INSERT [%d]->[%d] @%d\n", mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++])); + } else if (type == INSTRUCTION_REMOVE) { + s.append( + String.format( + "REMOVE [%d]->[%d] @%d\n", mIntBuffer[i++], mIntBuffer[i++], mIntBuffer[i++])); + } else if (type == INSTRUCTION_UPDATE_PROPS) { + ReadableMap props = castToProps(mObjBuffer[j++]); + String propsString = + IS_DEVELOPMENT_ENVIRONMENT + ? (props != null ? props.toHashMap().toString() : "") + : ""; + s.append(String.format("UPDATE PROPS [%d]: %s\n", mIntBuffer[i++], propsString)); + } else if (type == INSTRUCTION_UPDATE_STATE) { + j += 1; + s.append(String.format("UPDATE STATE [%d]\n", mIntBuffer[i++])); + } else if (type == INSTRUCTION_UPDATE_LAYOUT) { + s.append( + String.format( + "UPDATE LAYOUT [%d]: x:%d y:%d w:%d h:%d layoutDirection:%d displayType:%d\n", + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++])); + } else if (type == INSTRUCTION_UPDATE_PADDING) { + s.append( + String.format( + "UPDATE PADDING [%d]: top:%d right:%d bottom:%d left:%d\n", + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++], + mIntBuffer[i++])); + } else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) { + j += 1; + s.append(String.format("UPDATE EVENTEMITTER [%d]\n", mIntBuffer[i++])); + } else { + FLog.e(TAG, "String so far: " + s.toString()); + throw new IllegalArgumentException( + "Invalid type argument to IntBufferBatchMountItem: " + type + " at index: " + i); + } + } + } + return s.toString(); + } catch (Exception e) { + // Generally, this only happens during development when a malformed buffer is sent through. + // In these cases, we print the buffers to assist in debugging. + // This should never happen in production, but if it does... it'd still be helpful to know. + FLog.e(TAG, "Caught exception trying to print", e); + + StringBuilder ss = new StringBuilder(); + for (int ii = 0; ii < mIntBufferLen; ii++) { + ss.append(mIntBuffer[ii]); + ss.append(", "); + } + FLog.e(TAG, ss.toString()); + + for (int jj = 0; jj < mObjBufferLen; jj++) { + FLog.e(TAG, mObjBuffer[jj] != null ? mObjBuffer[jj].toString() : "null"); + } + + return ""; + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/MountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/MountItem.java index dc053625c2a6de..5ec3aeea571a4d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/MountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/MountItem.java @@ -7,6 +7,7 @@ package com.facebook.react.fabric.mounting.mountitems; +import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.facebook.react.fabric.mounting.MountingManager; @@ -16,4 +17,7 @@ public interface MountItem { /** Execute this {@link MountItem} into the operation queue received by parameter. */ @UiThread void execute(@NonNull MountingManager mountingManager); + + @AnyThread + int getSurfaceId(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/PreAllocateViewMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/PreAllocateViewMountItem.java index 0e3c7140eafbf2..7764bd58a3c452 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/PreAllocateViewMountItem.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/PreAllocateViewMountItem.java @@ -17,38 +17,35 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.fabric.mounting.MountingManager; import com.facebook.react.uimanager.StateWrapper; -import com.facebook.react.uimanager.ThemedReactContext; /** {@link MountItem} that is used to pre-allocate views for JS components. */ public class PreAllocateViewMountItem implements MountItem { @NonNull private final String mComponent; - private final int mRootTag; + private final int mSurfaceId; private final int mReactTag; private final @Nullable ReadableMap mProps; private final @Nullable StateWrapper mStateWrapper; - private final @NonNull ThemedReactContext mContext; private final boolean mIsLayoutable; public PreAllocateViewMountItem( - @Nullable ThemedReactContext context, - int rootTag, + int surfaceId, int reactTag, @NonNull String component, @Nullable ReadableMap props, @NonNull StateWrapper stateWrapper, boolean isLayoutable) { - mContext = context; mComponent = component; - mRootTag = rootTag; + mSurfaceId = surfaceId; mProps = props; mStateWrapper = stateWrapper; mReactTag = reactTag; mIsLayoutable = isLayoutable; } - public int getRootTag() { - return mRootTag; + @Override + public int getSurfaceId() { + return mSurfaceId; } @Override @@ -56,15 +53,9 @@ public void execute(@NonNull MountingManager mountingManager) { if (ENABLE_FABRIC_LOGS) { FLog.d(TAG, "Executing pre-allocation of: " + toString()); } - if (mContext == null) { - throw new IllegalStateException( - "Cannot execute PreAllocateViewMountItem without Context for ReactTag: " - + mReactTag - + " and rootTag: " - + mRootTag); - } - mountingManager.preallocateView( - mContext, mComponent, mReactTag, mProps, mStateWrapper, mIsLayoutable); + mountingManager + .getSurfaceManagerEnforced(mSurfaceId, "PreAllocateViewMountItem") + .preallocateView(mComponent, mReactTag, mProps, mStateWrapper, mIsLayoutable); } @Override @@ -74,8 +65,8 @@ public String toString() { .append(mReactTag) .append("] - component: ") .append(mComponent) - .append(" rootTag: ") - .append(mRootTag) + .append(" surfaceId: ") + .append(mSurfaceId) .append(" isLayoutable: ") .append(mIsLayoutable); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/RemoveDeleteMultiMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/RemoveDeleteMultiMountItem.java deleted file mode 100644 index daf3ed5ca75d5e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/RemoveDeleteMultiMountItem.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import com.facebook.react.fabric.mounting.MountingManager; - -public class RemoveDeleteMultiMountItem implements MountItem { - - // Metadata is an array of ints, grouped into 4 ints per instruction (so the length of metadata - // is always divisible by 4): - // - // `instruction*4 + 0`: react tag of view instruction - // `instruction*4 + 1`: react tag of view's parent - // `instruction*4 + 2`: index of view in parents' children instruction - // `instruction*4 + 3`: flags indicating if the view should be removed, and/or deleted - @NonNull private int[] mMetadata; - - // Bitfields of "flag", indicating if a view should be removed and/or deleted - private static final int REMOVE_FLAG = 1; - private static final int DELETE_FLAG = 2; - - // Indices for each parameter within an "instruction" - private static final int INSTRUCTION_FIELDS_LEN = 4; - private static final int TAG_INDEX = 0; - private static final int PARENT_TAG_INDEX = 1; - private static final int VIEW_INDEX_INDEX = 2; - private static final int FLAGS_INDEX = 3; - - public RemoveDeleteMultiMountItem(@NonNull int[] metadata) { - mMetadata = metadata; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - // First, go through instructions and remove all views that are marked - // for removal. - // Not all views that are removed are deleted, and not all deleted views - // are removed first. - // *All* views must be removed here before we can delete any views. - // Removal of a view from a parent is based on indices within the parents' children, - // and deletion causes reordering; so we must perform all removals first. - for (int i = 0; i < mMetadata.length; i += INSTRUCTION_FIELDS_LEN) { - int flags = mMetadata[i + FLAGS_INDEX]; - if ((flags & REMOVE_FLAG) != 0) { - int parentTag = mMetadata[i + PARENT_TAG_INDEX]; - int tag = mMetadata[i + TAG_INDEX]; - int index = mMetadata[i + VIEW_INDEX_INDEX]; - mountingManager.removeViewAt(tag, parentTag, index); - } - } - - // After removing all views, delete all views marked for deletion. - for (int i = 0; i < mMetadata.length; i += 4) { - int flags = mMetadata[i + FLAGS_INDEX]; - if ((flags & DELETE_FLAG) != 0) { - int tag = mMetadata[i + TAG_INDEX]; - mountingManager.deleteView(tag); - } - } - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - for (int i = 0; i < mMetadata.length; i += 4) { - if (s.length() > 0) { - s.append("\n"); - } - s.append("RemoveDeleteMultiMountItem (") - .append(i / INSTRUCTION_FIELDS_LEN + 1) - .append("/") - .append(mMetadata.length / INSTRUCTION_FIELDS_LEN) - .append("): [") - .append(mMetadata[i + TAG_INDEX]) - .append("] parent [") - .append(mMetadata[i + PARENT_TAG_INDEX]) - .append("] idx ") - .append(mMetadata[i + VIEW_INDEX_INDEX]) - .append(" ") - .append(mMetadata[i + FLAGS_INDEX]); - } - return s.toString(); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/SendAccessibilityEvent.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/SendAccessibilityEvent.java index 5852ff1a78c643..a52ed29042da4f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/SendAccessibilityEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/SendAccessibilityEvent.java @@ -16,10 +16,12 @@ public class SendAccessibilityEvent implements MountItem { private final String TAG = "Fabric.SendAccessibilityEvent"; + private final int mSurfaceId; private final int mReactTag; private final int mEventType; - public SendAccessibilityEvent(int reactTag, int eventType) { + public SendAccessibilityEvent(int surfaceId, int reactTag, int eventType) { + mSurfaceId = surfaceId; mReactTag = reactTag; mEventType = eventType; } @@ -27,7 +29,7 @@ public SendAccessibilityEvent(int reactTag, int eventType) { @Override public void execute(@NonNull MountingManager mountingManager) { try { - mountingManager.sendAccessibilityEvent(mReactTag, mEventType); + mountingManager.sendAccessibilityEvent(mSurfaceId, mReactTag, mEventType); } catch (RetryableMountingLayerException e) { // Accessibility events are similar to commands in that they're imperative // calls from JS, disconnected from the commit lifecycle, and therefore @@ -40,6 +42,11 @@ public void execute(@NonNull MountingManager mountingManager) { } } + @Override + public int getSurfaceId() { + return mSurfaceId; + } + @Override public String toString() { return "SendAccessibilityEvent [" + mReactTag + "] " + mEventType; diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateEventEmitterMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateEventEmitterMountItem.java deleted file mode 100644 index 72331c6b963484..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateEventEmitterMountItem.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import com.facebook.react.fabric.events.EventEmitterWrapper; -import com.facebook.react.fabric.mounting.MountingManager; - -public class UpdateEventEmitterMountItem implements MountItem { - - @NonNull private final EventEmitterWrapper mEventHandler; - private final int mReactTag; - - public UpdateEventEmitterMountItem(int reactTag, @NonNull EventEmitterWrapper EventHandler) { - mReactTag = reactTag; - mEventHandler = EventHandler; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.updateEventEmitter(mReactTag, mEventHandler); - } - - @Override - public String toString() { - return "UpdateEventEmitterMountItem [" + mReactTag + "]"; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateLayoutMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateLayoutMountItem.java deleted file mode 100644 index 3db91ed740c26e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateLayoutMountItem.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import android.annotation.TargetApi; -import android.os.Build; -import android.util.LayoutDirection; -import androidx.annotation.NonNull; -import com.facebook.react.fabric.mounting.MountingManager; - -public class UpdateLayoutMountItem implements MountItem { - - private final int mReactTag; - private final int mX; - private final int mY; - private final int mWidth; - private final int mHeight; - private final int mLayoutDirection; - - public UpdateLayoutMountItem( - int reactTag, int x, int y, int width, int height, int layoutDirection) { - mReactTag = reactTag; - mX = x; - mY = y; - mWidth = width; - mHeight = height; - mLayoutDirection = convertLayoutDirection(layoutDirection); - } - - // TODO move this from here - @TargetApi(Build.VERSION_CODES.KITKAT) - private static int convertLayoutDirection(int layoutDirection) { - switch (layoutDirection) { - case 0: - return LayoutDirection.INHERIT; - case 1: - return LayoutDirection.LTR; - case 2: - return LayoutDirection.RTL; - default: - throw new IllegalArgumentException("Unsupported layout direction: " + layoutDirection); - } - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.updateLayout(mReactTag, mX, mY, mWidth, mHeight); - } - - public int getX() { - return mX; - } - - public int getY() { - return mY; - } - - public int getHeight() { - return mHeight; - } - - public int getWidth() { - return mWidth; - } - - public int getLayoutDirection() { - return mLayoutDirection; - } - - @Override - public String toString() { - return "UpdateLayoutMountItem [" - + mReactTag - + "] - x: " - + mX - + " - y: " - + mY - + " - height: " - + mHeight - + " - width: " - + mWidth - + " - layoutDirection: " - + +mLayoutDirection; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java deleted file mode 100644 index e0403627bbd99d..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import androidx.annotation.NonNull; -import com.facebook.react.fabric.mounting.MountingManager; - -/** - * A MountItem that represents setting the padding properties of a view (left, top, right, bottom). - * This is distinct from layout because it happens far less frequently from layout; so it is a perf - * optimization to transfer this data and execute the methods strictly less than the layout-related - * properties. - */ -public class UpdatePaddingMountItem implements MountItem { - - private final int mReactTag; - private final int mLeft; - private final int mTop; - private final int mRight; - private final int mBottom; - - public UpdatePaddingMountItem(int reactTag, int left, int top, int right, int bottom) { - mReactTag = reactTag; - mLeft = left; - mTop = top; - mRight = right; - mBottom = bottom; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.updatePadding(mReactTag, mLeft, mTop, mRight, mBottom); - } - - @Override - public String toString() { - return "UpdatePaddingMountItem [" - + mReactTag - + "] - left: " - + mLeft - + " - top: " - + mTop - + " - right: " - + mRight - + " - bottom: " - + mBottom; - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePropsMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePropsMountItem.java deleted file mode 100644 index 8b980705e9dc84..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePropsMountItem.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT; - -import androidx.annotation.NonNull; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.fabric.mounting.MountingManager; - -public class UpdatePropsMountItem implements MountItem { - - private final int mReactTag; - @NonNull private final ReadableMap mUpdatedProps; - - public UpdatePropsMountItem(int reactTag, @NonNull ReadableMap updatedProps) { - mReactTag = reactTag; - mUpdatedProps = updatedProps; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.updateProps(mReactTag, mUpdatedProps); - } - - @Override - public String toString() { - StringBuilder result = - new StringBuilder("UpdatePropsMountItem [").append(mReactTag).append("]"); - - if (IS_DEVELOPMENT_ENVIRONMENT) { - result.append(" props: ").append(mUpdatedProps); - } - - return result.toString(); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java deleted file mode 100644 index 4544e8f935e23e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric.mounting.mountitems; - -import static com.facebook.react.fabric.FabricUIManager.IS_DEVELOPMENT_ENVIRONMENT; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.facebook.react.fabric.mounting.MountingManager; -import com.facebook.react.uimanager.StateWrapper; - -public class UpdateStateMountItem implements MountItem { - - private final int mReactTag; - @Nullable private final StateWrapper mStateWrapper; - - public UpdateStateMountItem(int reactTag, @Nullable StateWrapper stateWrapper) { - mReactTag = reactTag; - mStateWrapper = stateWrapper; - } - - @Override - public void execute(@NonNull MountingManager mountingManager) { - mountingManager.updateState(mReactTag, mStateWrapper); - } - - @Override - public String toString() { - StringBuilder result = - new StringBuilder("UpdateStateMountItem [").append(mReactTag).append("]"); - - if (IS_DEVELOPMENT_ENVIRONMENT) { - result.append(" state: ").append(mStateWrapper != null ? mStateWrapper.getState() : ""); - } - - return result.toString(); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK index a1a374ef936b36..d601632a0f3bdb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_nat rn_android_library( name = "jscexecutor", srcs = glob(["*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK b/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK index 26444912bf4e73..d5a734f79243ef 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/jstasks/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "jstasks", srcs = glob(["*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK index b213c9d3133a0f..ec9fc4e9e07e9e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/annotations/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "annotations", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK b/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK index 85f23a35691b69..22d2f5a6625890 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/module/model/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "model", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java index 8ecb0d81f44168..85a2ac54f2eecb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/AccessibilityInfoModule.java @@ -36,7 +36,7 @@ public class AccessibilityInfoModule extends NativeAccessibilityInfoSpec public static final String NAME = "AccessibilityInfo"; - @TargetApi(Build.VERSION_CODES.KITKAT) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private class ReactTouchExplorationStateChangeListener implements AccessibilityManager.TouchExplorationStateChangeListener { @@ -79,10 +79,7 @@ public AccessibilityInfoModule(ReactApplicationContext context) { mContentResolver = getReactApplicationContext().getContentResolver(); mTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled(); mReduceMotionEnabled = this.getIsReduceMotionEnabledValue(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - mTouchExplorationStateChangeListener = new ReactTouchExplorationStateChangeListener(); - } + mTouchExplorationStateChangeListener = new ReactTouchExplorationStateChangeListener(); } @Override @@ -90,7 +87,7 @@ public String getName() { return "AccessibilityInfo"; } - @TargetApi(Build.VERSION_CODES.KITKAT) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private boolean getIsReduceMotionEnabledValue() { String value = Settings.Global.getString(mContentResolver, Settings.Global.TRANSITION_ANIMATION_SCALE); @@ -137,22 +134,20 @@ private void updateAndSendTouchExplorationChangeEvent(boolean enabled) { } @Override - @TargetApi(Build.VERSION_CODES.KITKAT) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void onHostResume() { mAccessibilityManager.addTouchExplorationStateChangeListener( mTouchExplorationStateChangeListener); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - Uri transitionUri = Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); - mContentResolver.registerContentObserver(transitionUri, false, animationScaleObserver); - } + Uri transitionUri = Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE); + mContentResolver.registerContentObserver(transitionUri, false, animationScaleObserver); updateAndSendTouchExplorationChangeEvent(mAccessibilityManager.isTouchExplorationEnabled()); updateAndSendReduceMotionChangeEvent(); } @Override - @TargetApi(Build.VERSION_CODES.KITKAT) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void onHostPause() { mAccessibilityManager.removeTouchExplorationStateChangeListener( mTouchExplorationStateChangeListener); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK index f12d0bf3c4b440..b8c3a1b9b31131 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/accessibilityinfo/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "accessibilityinfo", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -18,5 +19,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK index ef3d7751982482..640c535e0a0de1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "appearance", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -16,5 +17,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK index d54b2cd82034de..727a8d30d1ee91 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appregistry/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target", "rn_android_li rn_android_library( name = "appregistry", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK index 92c4684d3014fe..cacb0a3ca2c04c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "appstate", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", @@ -16,5 +17,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK index 1831ff654368cb..df5de6afb47ae9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "blob", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -31,6 +32,6 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/websocket:websocket"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BlobCollector.cpp b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BlobCollector.cpp index 8883a318d89629..285e881472aa0c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BlobCollector.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BlobCollector.cpp @@ -29,6 +29,7 @@ BlobCollector::~BlobCollector() { static auto removeMethod = jni::findClassStatic(kBlobModuleJavaDescriptor) ->getMethod("remove"); removeMethod(blobModule_, jni::make_jstring(blobId_).get()); + blobModule_.reset(); }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/bundleloader/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/bundleloader/BUCK index 64fb396b12a083..b16ad7c7570d36 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/bundleloader/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/bundleloader/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "bundleloader", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -17,5 +18,5 @@ rn_android_library( react_native_target("java/com/facebook/react/devsupport:interfaces"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK index 13384e7ac49b3d..e516ebe6638852 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "camera", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -18,6 +19,6 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java index 8bf377cfb4cc13..0752be6e554cae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java @@ -12,7 +12,7 @@ import android.os.AsyncTask; import android.util.Base64; import android.util.Base64OutputStream; -import com.facebook.fbreact.specs.NativeImageStoreSpec; +import com.facebook.fbreact.specs.NativeImageStoreAndroidSpec; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.GuardedAsyncTask; import com.facebook.react.bridge.ReactApplicationContext; @@ -25,7 +25,7 @@ import java.io.InputStream; @ReactModule(name = ImageStoreManager.NAME) -public class ImageStoreManager extends NativeImageStoreSpec { +public class ImageStoreManager extends NativeImageStoreAndroidSpec { public static final String NAME = "ImageStoreManager"; private static final int BUFFER_SIZE = 8192; @@ -105,20 +105,4 @@ private static void closeQuietly(Closeable closeable) { // shhh } } - - @Override - public void hasImageForTag(String uri, Callback callback) { - // iOS only - } - - @Override - public void removeImageForTag(String uri) { - // iOS only - } - - @Override - public void addImageFromBase64( - String base64ImageData, Callback successCallback, Callback errorCallback) { - // iOS only - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK index d755fa2dd9aa55..0e46f8795096e5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "clipboard", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK index 47dad24dd0491a..d42deef1d60f4c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/common/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "common", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK index 535ee65d070cc3..31207dd63156b6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/core/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "core", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -21,6 +22,6 @@ rn_android_library( react_native_target("java/com/facebook/react/util:util"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK index f4b8776d0c113e..e1c276c6757c6b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "datepicker", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -22,5 +23,5 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java index 29131862c1dbc7..f3d190b4432e22 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java @@ -15,7 +15,6 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.graphics.drawable.ColorDrawable; -import android.os.Build; import android.os.Bundle; import android.widget.DatePicker; import androidx.annotation.Nullable; @@ -57,52 +56,37 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { DatePickerDialog dialog = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - switch (mode) { - case CALENDAR: - dialog = - new DismissableDatePickerDialog( - activityContext, - activityContext - .getResources() - .getIdentifier( - "CalendarDatePickerDialog", "style", activityContext.getPackageName()), - onDateSetListener, - year, - month, - day); - break; - case SPINNER: - dialog = - new DismissableDatePickerDialog( - activityContext, - android.R.style.Theme_Holo_Light_Dialog, - onDateSetListener, - year, - month, - day); - dialog - .getWindow() - .setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); - break; - case DEFAULT: - dialog = - new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day); - break; - } - } else { - dialog = - new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day); - - switch (mode) { - case CALENDAR: - dialog.getDatePicker().setCalendarViewShown(true); - dialog.getDatePicker().setSpinnersShown(false); - break; - case SPINNER: - dialog.getDatePicker().setCalendarViewShown(false); - break; - } + switch (mode) { + case CALENDAR: + dialog = + new DismissableDatePickerDialog( + activityContext, + activityContext + .getResources() + .getIdentifier( + "CalendarDatePickerDialog", "style", activityContext.getPackageName()), + onDateSetListener, + year, + month, + day); + break; + case SPINNER: + dialog = + new DismissableDatePickerDialog( + activityContext, + android.R.style.Theme_Holo_Light_Dialog, + onDateSetListener, + year, + month, + day); + dialog + .getWindow() + .setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); + break; + case DEFAULT: + dialog = + new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day); + break; } final DatePicker datePicker = dialog.getDatePicker(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java index b1e089921ee4d7..cfcc1fd3c77488 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java @@ -17,12 +17,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -/** - * Certain versions of Android (Jellybean-KitKat) have a bug where when dismissed, the {@link - * DatePickerDialog} still calls the OnDateSetListener. This class works around that issue. - * - *

See: Issue 34833 - */ public class DismissableDatePickerDialog extends DatePickerDialog { public DismissableDatePickerDialog( @@ -46,15 +40,6 @@ public DismissableDatePickerDialog( fixSpinner(context, year, monthOfYear, dayOfMonth); } - @Override - protected void onStop() { - // do *not* call super.onStop() on KitKat on lower, as that would erroneously call the - // OnDateSetListener when the dialog is dismissed, or call it twice when "OK" is pressed. - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - super.onStop(); - } - } - private void fixSpinner(Context context, int year, int month, int dayOfMonth) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) { try { diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK index 389c2d9681cef3..525683f3596eef 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "debug", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -23,13 +24,14 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager:uimanager"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) rn_android_library( name = "interfaces", srcs = glob(["interfaces/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK index 65a9d8d0bb2aca..46f482370c3cd1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "deviceinfo", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -19,6 +20,6 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager:uimanager"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK index b6a6e85c354448..e80e77f2aa3e32 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "dialog", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -23,5 +24,5 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/DialogModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/DialogModule.java index e3a25072156aa6..664b359a27b63b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/DialogModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/DialogModule.java @@ -129,7 +129,8 @@ public AlertFragmentListener(Callback callback) { @Override public void onClick(DialogInterface dialog, int which) { if (!mCallbackConsumed) { - if (getReactApplicationContext().hasActiveCatalystInstance()) { + if (getReactApplicationContext().isBridgeless() + || getReactApplicationContext().hasActiveCatalystInstance()) { mCallback.invoke(ACTION_BUTTON_CLICKED, which); mCallbackConsumed = true; } @@ -139,7 +140,8 @@ public void onClick(DialogInterface dialog, int which) { @Override public void onDismiss(DialogInterface dialog) { if (!mCallbackConsumed) { - if (getReactApplicationContext().hasActiveCatalystInstance()) { + if (getReactApplicationContext().isBridgeless() + || getReactApplicationContext().hasActiveCatalystInstance()) { mCallback.invoke(ACTION_DISMISSED); mCallbackConsumed = true; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK index f88d3d22465bda..361c17d91f7afb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fabric/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target", "rn_android_li rn_android_library( name = "fabric", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK index a0762971a030ed..5f4e8ce6a5815d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "fresco", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK index 2b7eeb854d9425..1b479ecd3e2797 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "i18nmanager", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK index 706425f1bc3e8e..bc4e575b2be95a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/image/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "image", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -24,6 +25,6 @@ rn_android_library( react_native_target("java/com/facebook/react/views/image:image"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK index e3102ed4685ca2..fb94f3fb365c64 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "intent", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -16,5 +17,5 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java index 7c324332e37fa9..41383e528dc3c1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java @@ -15,7 +15,7 @@ import android.nfc.NfcAdapter; import android.provider.Settings; import androidx.annotation.Nullable; -import com.facebook.fbreact.specs.NativeLinkingSpec; +import com.facebook.fbreact.specs.NativeIntentAndroidSpec; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; @@ -26,7 +26,7 @@ /** Intent module. Launch other activities or open URLs. */ @ReactModule(name = IntentModule.NAME) -public class IntentModule extends NativeLinkingSpec { +public class IntentModule extends NativeIntentAndroidSpec { public static final String NAME = "IntentAndroid"; @@ -237,14 +237,4 @@ public void sendIntent(String action, @Nullable ReadableArray extras, Promise pr getReactApplicationContext().startActivity(intent); } - - @Override - public void addListener(String eventName) { - // iOS only - } - - @Override - public void removeListeners(double count) { - // iOS only - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK index 088baa4883eb36..703d1b7b72a31b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "network", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -28,5 +29,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java index d1fce6275e5e7f..63a9fe7ab5a29e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java @@ -15,12 +15,10 @@ import android.os.Message; import android.text.TextUtils; import android.webkit.CookieManager; -import android.webkit.CookieSyncManager; import android.webkit.ValueCallback; import androidx.annotation.Nullable; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.GuardedAsyncTask; -import com.facebook.react.bridge.GuardedResultAsyncTask; import com.facebook.react.bridge.ReactContext; import java.io.IOException; import java.net.CookieHandler; @@ -40,10 +38,6 @@ public class ForwardingCookieHandler extends CookieHandler { private static final String VERSION_ONE_HEADER = "Set-cookie2"; private static final String COOKIE_HEADER = "Cookie"; - // As CookieManager was synchronous before API 21 this class emulates the async behavior on < 21. - private static final boolean USES_LEGACY_STORE = - Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; - private final CookieSaver mCookieSaver; private final ReactContext mContext; private @Nullable CookieManager mCookieManager; @@ -79,26 +73,7 @@ public void put(URI uri, Map> headers) throws IOException { } public void clearCookies(final Callback callback) { - if (USES_LEGACY_STORE) { - new GuardedResultAsyncTask(mContext) { - @Override - protected Boolean doInBackgroundGuarded() { - CookieManager cookieManager = getCookieManager(); - if (cookieManager != null) { - cookieManager.removeAllCookie(); - } - mCookieSaver.onCookiesModified(); - return true; - } - - @Override - protected void onPostExecuteGuarded(Boolean result) { - callback.invoke(result); - } - }.execute(); - } else { - clearCookiesAsync(callback); - } + clearCookiesAsync(callback); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @@ -116,38 +91,17 @@ public void onReceiveValue(Boolean value) { } } - public void destroy() { - if (USES_LEGACY_STORE) { - CookieManager cookieManager = getCookieManager(); - if (cookieManager != null) { - cookieManager.removeExpiredCookie(); - } - mCookieSaver.persistCookies(); - } - } + public void destroy() {} public void addCookies(final String url, final List cookies) { final CookieManager cookieManager = getCookieManager(); if (cookieManager == null) return; - if (USES_LEGACY_STORE) { - runInBackground( - new Runnable() { - @Override - public void run() { - for (String cookie : cookies) { - cookieManager.setCookie(url, cookie); - } - mCookieSaver.onCookiesModified(); - } - }); - } else { - for (String cookie : cookies) { - addCookieAsync(url, cookie); - } - cookieManager.flush(); - mCookieSaver.onCookiesModified(); + for (String cookie : cookies) { + addCookieAsync(url, cookie); } + cookieManager.flush(); + mCookieSaver.onCookiesModified(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @@ -172,8 +126,8 @@ protected void doInBackgroundGuarded(Void... params) { } /** - * Instantiating CookieManager in KitKat+ will load the Chromium task taking a 100ish ms so we do - * it lazily to make sure it's done on a background thread as needed. + * Instantiating CookieManager will load the Chromium task taking a 100ish ms so we do it lazily + * to make sure it's done on a background thread as needed. */ private @Nullable CookieManager getCookieManager() { if (mCookieManager == null) { @@ -199,24 +153,12 @@ protected void doInBackgroundGuarded(Void... params) { throw exception; } } - - if (USES_LEGACY_STORE) { - mCookieManager.removeExpiredCookie(); - } } return mCookieManager; } - private static void possiblyWorkaroundSyncManager(Context context) { - if (USES_LEGACY_STORE) { - // This is to work around a bug where CookieManager may fail to instantiate if - // CookieSyncManager has never been created. Note that the sync() may not be required but is - // here of legacy reasons. - CookieSyncManager syncManager = CookieSyncManager.createInstance(context); - syncManager.sync(); - } - } + private static void possiblyWorkaroundSyncManager(Context context) {} /** * Responsible for flushing cookies to disk. Flushes to disk with a maximum delay of 30 seconds. @@ -246,11 +188,7 @@ public boolean handleMessage(Message msg) { }); } - public void onCookiesModified() { - if (USES_LEGACY_STORE) { - mHandler.sendEmptyMessageDelayed(MSG_PERSIST_COOKIES, TIMEOUT); - } - } + public void onCookiesModified() {} public void persistCookies() { mHandler.removeMessages(MSG_PERSIST_COOKIES); @@ -258,12 +196,7 @@ public void persistCookies() { new Runnable() { @Override public void run() { - if (USES_LEGACY_STORE) { - CookieSyncManager syncManager = CookieSyncManager.getInstance(); - syncManager.sync(); - } else { - flush(); - } + flush(); } }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java index 5515eeb8d95683..38b2a0f961294d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java @@ -8,19 +8,13 @@ package com.facebook.react.modules.network; import android.content.Context; -import android.os.Build; import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; import java.io.File; import java.security.Provider; import java.security.Security; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import okhttp3.Cache; -import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; -import okhttp3.TlsVersion; /** * Helper class that provides the same OkHttpClient instance that will be used for all networking @@ -101,26 +95,6 @@ public static OkHttpClient.Builder createClientBuilder(Context context, int cach enables it. */ public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { - try { - client.sslSocketFactory(new TLSSocketFactory()); - - ConnectionSpec cs = - new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_2) - .build(); - - List specs = new ArrayList<>(); - specs.add(cs); - specs.add(ConnectionSpec.COMPATIBLE_TLS); - specs.add(ConnectionSpec.CLEARTEXT); - - client.connectionSpecs(specs); - } catch (Exception ex) { - FLog.e("OkHttpClientProvider", "Error while enabling TLS 1.2", ex); - } - } - return client; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK index 4943b35a537b3f..14d1f89fa2b651 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/permissions/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "permissions", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", @@ -15,5 +16,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK index 8bcc886c1b0652..d3e98217f6e61d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/share/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "share", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", @@ -15,5 +16,5 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK index aefbb42597bfe6..dc76a82b932c1a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/sound/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "sound", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -19,5 +20,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/uimanager:uimanager"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK index 835340443bbd44..21e2ecf7700065 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "statusbar", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -24,5 +25,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/uimanager:uimanager"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java index 1898a62a127b33..b4a4e80e68485e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java @@ -60,7 +60,7 @@ public String getName() { : 0; String statusBarColorString = "black"; - if (activity != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (activity != null) { final int statusBarColor = activity.getWindow().getStatusBarColor(); statusBarColorString = String.format("#%06X", (0xFFFFFF & statusBarColor)); } @@ -81,38 +81,33 @@ public void setColor(final double colorDouble, final boolean animated) { return; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - - UiThreadUtil.runOnUiThread( - new GuardedRunnable(getReactApplicationContext()) { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void runGuarded() { - activity - .getWindow() - .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - if (animated) { - int curColor = activity.getWindow().getStatusBarColor(); - ValueAnimator colorAnimation = - ValueAnimator.ofObject(new ArgbEvaluator(), curColor, color); - - colorAnimation.addUpdateListener( - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animator) { - activity - .getWindow() - .setStatusBarColor((Integer) animator.getAnimatedValue()); - } - }); - colorAnimation.setDuration(300).setStartDelay(0); - colorAnimation.start(); - } else { - activity.getWindow().setStatusBarColor(color); - } + UiThreadUtil.runOnUiThread( + new GuardedRunnable(getReactApplicationContext()) { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void runGuarded() { + activity + .getWindow() + .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + if (animated) { + int curColor = activity.getWindow().getStatusBarColor(); + ValueAnimator colorAnimation = + ValueAnimator.ofObject(new ArgbEvaluator(), curColor, color); + + colorAnimation.addUpdateListener( + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animator) { + activity.getWindow().setStatusBarColor((Integer) animator.getAnimatedValue()); + } + }); + colorAnimation.setDuration(300).setStartDelay(0); + colorAnimation.start(); + } else { + activity.getWindow().setStatusBarColor(color); } - }); - } + } + }); } @Override @@ -125,36 +120,34 @@ public void setTranslucent(final boolean translucent) { return; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - UiThreadUtil.runOnUiThread( - new GuardedRunnable(getReactApplicationContext()) { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void runGuarded() { - // If the status bar is translucent hook into the window insets calculations - // and consume all the top insets so no padding will be added under the status bar. - View decorView = activity.getWindow().getDecorView(); - if (translucent) { - decorView.setOnApplyWindowInsetsListener( - new View.OnApplyWindowInsetsListener() { - @Override - public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { - WindowInsets defaultInsets = v.onApplyWindowInsets(insets); - return defaultInsets.replaceSystemWindowInsets( - defaultInsets.getSystemWindowInsetLeft(), - 0, - defaultInsets.getSystemWindowInsetRight(), - defaultInsets.getSystemWindowInsetBottom()); - } - }); - } else { - decorView.setOnApplyWindowInsetsListener(null); - } - - ViewCompat.requestApplyInsets(decorView); + UiThreadUtil.runOnUiThread( + new GuardedRunnable(getReactApplicationContext()) { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void runGuarded() { + // If the status bar is translucent hook into the window insets calculations + // and consume all the top insets so no padding will be added under the status bar. + View decorView = activity.getWindow().getDecorView(); + if (translucent) { + decorView.setOnApplyWindowInsetsListener( + new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + WindowInsets defaultInsets = v.onApplyWindowInsets(insets); + return defaultInsets.replaceSystemWindowInsets( + defaultInsets.getSystemWindowInsetLeft(), + 0, + defaultInsets.getSystemWindowInsetRight(), + defaultInsets.getSystemWindowInsetBottom()); + } + }); + } else { + decorView.setOnApplyWindowInsetsListener(null); } - }); - } + + ViewCompat.requestApplyInsets(decorView); + } + }); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/AsyncStorageModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/AsyncStorageModule.java index 2b605a571f9803..34890a98ba3aa0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/AsyncStorageModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/AsyncStorageModule.java @@ -15,7 +15,7 @@ import android.database.sqlite.SQLiteStatement; import android.os.AsyncTask; import com.facebook.common.logging.FLog; -import com.facebook.fbreact.specs.NativeAsyncStorageSpec; +import com.facebook.fbreact.specs.NativeAsyncSQLiteDBStorageSpec; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.GuardedAsyncTask; @@ -32,7 +32,7 @@ import java.util.concurrent.Executor; @ReactModule(name = AsyncStorageModule.NAME) -public final class AsyncStorageModule extends NativeAsyncStorageSpec +public final class AsyncStorageModule extends NativeAsyncSQLiteDBStorageSpec implements ModuleDataCleaner.Cleanable { public static final String NAME = "AsyncSQLiteDBStorage"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK index 716282e68cfcba..c74d5354d7e64d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/storage/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "storage", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -18,5 +19,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/common:common"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK index 89a47d4f0d2ea6..efda55325a7405 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK @@ -1,4 +1,4 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "systeminfo", @@ -6,6 +6,7 @@ rn_android_library( "AndroidInfoModule.java", "ReactNativeVersion.java", ], + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -21,7 +22,7 @@ rn_android_library( react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ":systeminfo-moduleless", ], ) @@ -31,6 +32,7 @@ rn_android_library( srcs = [ "AndroidInfoHelpers.java", ], + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -43,5 +45,5 @@ rn_android_library( react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_target("res:systeminfo"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK index 9cd1eaa53d005c..79edb9b7dc43d0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/toast/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "toast", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", @@ -14,5 +15,5 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK index 69081110ea8600..bcf7ea3376f42a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/vibration/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "vibration", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", @@ -16,5 +17,5 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/modules/core:core"), ], - exported_deps = [react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec")], + exported_deps = [react_native_root_target("Libraries:FBReactNativeSpec")], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK index d80e8fd4d06646..18879f21d4a9b8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "websocket", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -22,6 +23,6 @@ rn_android_library( react_native_target("java/com/facebook/react/modules/network:network"), ], exported_deps = [ - react_native_target("java/com/facebook/fbreact/specs:FBReactNativeSpec"), + react_native_root_target("Libraries:FBReactNativeSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK index 3aa924ecad3ad6..76c5775ea9d04e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/BUCK @@ -5,6 +5,7 @@ rn_android_library( srcs = glob( ["**/*.java"], ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/BUCK b/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/BUCK index d8d99e703d2b02..3575b09bb06b13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/BUCK @@ -7,6 +7,7 @@ rn_android_library( "*.java", ], ), + autoglob = False, labels = [ "supermodule:xplat/default/public.react_native.infra", ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK index 481682cb97c8c3..bd6a96575ac35c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK @@ -1,4 +1,4 @@ -load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_xplat_target", "rn_xplat_cxx_library") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_xplat_target", "rn_xplat_cxx_library") rn_xplat_cxx_library( name = "jni", diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK index e8e27ee8e2b900..7b44b22136b874 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "shell", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK b/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK index beb35ce40c1055..6a21268b9c579b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/surface/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "surface", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK b/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK index 839bd5beb44bb0..c9d6bbbe59e0a9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/touch/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "touch", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK index 721fe18d0cc7f1..e42fe4e012d4d4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/BUCK @@ -8,6 +8,7 @@ rn_android_library( ], exclude = ["CallInvokerHolderImpl.java"], ), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ @@ -40,6 +41,7 @@ rn_android_library( rn_android_library( name = "callinvokerholder", srcs = ["CallInvokerHolderImpl.java"], + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/ReactPackageTurboModuleManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/ReactPackageTurboModuleManagerDelegate.java index 65ee5186e476bc..59c2fc9794ab92 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/ReactPackageTurboModuleManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/ReactPackageTurboModuleManagerDelegate.java @@ -18,10 +18,14 @@ import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class ReactPackageTurboModuleManagerDelegate extends TurboModuleManagerDelegate { private final List mPackages = new ArrayList<>(); + private final Map> mPackageModuleInfos = + new HashMap<>(); private final ReactApplicationContext mReactApplicationContext; protected ReactPackageTurboModuleManagerDelegate( @@ -30,7 +34,9 @@ protected ReactPackageTurboModuleManagerDelegate( mReactApplicationContext = reactApplicationContext; for (ReactPackage reactPackage : packages) { if (reactPackage instanceof TurboReactPackage) { - mPackages.add((TurboReactPackage) reactPackage); + TurboReactPackage pkg = (TurboReactPackage) reactPackage; + mPackages.add(pkg); + mPackageModuleInfos.put(pkg, pkg.getReactModuleInfoProvider().getReactModuleInfos()); } } } @@ -72,8 +78,15 @@ private TurboModule resolveModule(String moduleName) { for (final TurboReactPackage pkg : mPackages) { try { - NativeModule module = pkg.getModule(moduleName, mReactApplicationContext); - if (resolvedModule == null || module != null && module.canOverrideExistingModule()) { + final ReactModuleInfo moduleInfo = mPackageModuleInfos.get(pkg).get(moduleName); + if (moduleInfo == null + || !moduleInfo.isTurboModule() + || resolvedModule != null && !moduleInfo.canOverrideExistingModule()) { + continue; + } + + final NativeModule module = pkg.getModule(moduleName, mReactApplicationContext); + if (module != null) { resolvedModule = module; } } catch (IllegalArgumentException ex) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java index e6e6fcce69e099..39147e62be9d73 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModuleManager.java @@ -15,8 +15,8 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.CxxModuleWrapper; import com.facebook.react.bridge.JSIModule; -import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry; @@ -49,18 +49,17 @@ public class TurboModuleManager implements JSIModule, TurboModuleRegistry { private final HybridData mHybridData; public TurboModuleManager( - JavaScriptContextHolder jsContext, + RuntimeExecutor runtimeExecutor, @Nullable final TurboModuleManagerDelegate delegate, CallInvokerHolder jsCallInvokerHolder, CallInvokerHolder nativeCallInvokerHolder) { maybeLoadSoLibrary(); mHybridData = initHybrid( - jsContext.get(), + runtimeExecutor, (CallInvokerHolderImpl) jsCallInvokerHolder, (CallInvokerHolderImpl) nativeCallInvokerHolder, - delegate, - false); + delegate); installJSIBindings(); mEagerInitModuleNames = @@ -289,11 +288,10 @@ public boolean hasModule(String moduleName) { } private native HybridData initHybrid( - long jsContext, + RuntimeExecutor runtimeExecutor, CallInvokerHolderImpl jsCallInvokerHolder, CallInvokerHolderImpl nativeCallInvokerHolder, - TurboModuleManagerDelegate tmmDelegate, - boolean enablePromiseAsyncDispatch); + TurboModuleManagerDelegate tmmDelegate); private native void installJSIBindings(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModulePerfLogger.java b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModulePerfLogger.java index eb8e49d5dfdae0..36d7d1d010c4de 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModulePerfLogger.java +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/TurboModulePerfLogger.java @@ -7,10 +7,12 @@ package com.facebook.react.turbomodule.core; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.perflogger.NativeModulePerfLogger; import com.facebook.soloader.SoLoader; import javax.annotation.Nullable; +@DoNotStrip public class TurboModulePerfLogger { @Nullable private static NativeModulePerfLogger sNativeModulePerfLogger = null; private static boolean sIsSoLibraryLoaded = false; diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK index ad97b93f20d94a..5526d046ddfef7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/BUCK @@ -5,6 +5,7 @@ rn_android_library( srcs = glob( ["*.java"], ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk index 80ba4096da6480..401429a13ac546 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk @@ -5,6 +5,10 @@ LOCAL_PATH := $(call my-dir) +######################### +### callinvokerholder ### +######################### + include $(CLEAR_VARS) # Header search path for all source files in this module. @@ -15,9 +19,9 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall -LOCAL_STATIC_LIBRARIES = libcallinvoker libreactperfloggerjni +LOCAL_SHARED_LIBRARIES = libfb libfbjni libreactnativeutilsjni -LOCAL_SHARED_LIBRARIES = libfb libfbjni +LOCAL_STATIC_LIBRARIES = libcallinvoker libreactperfloggerjni libruntimeexecutor # Name of this module. LOCAL_MODULE := callinvokerholder @@ -27,3 +31,31 @@ LOCAL_SRC_FILES := $(LOCAL_PATH)/ReactCommon/CallInvokerHolder.cpp # Build the files in this directory as a shared library include $(BUILD_STATIC_LIBRARY) + +################################## +### react_nativemodule_manager ### +################################## + +include $(CLEAR_VARS) + +# Name of this module. +# TODO: rename to react_nativemodule_manager +LOCAL_MODULE := turbomodulejsijni + +# Header search path for all source files in this module. +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ReactCommon + +# Header search path for modules that depend on this module +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +LOCAL_SHARED_LIBRARIES = libfb libfbjni libreact_nativemodule_core + +LOCAL_STATIC_LIBRARIES = libcallinvokerholder libreactperfloggerjni + +# Compile all local c++ files +LOCAL_SRC_FILES := $(LOCAL_PATH)/ReactCommon/TurboModuleManager.cpp $(LOCAL_PATH)/ReactCommon/OnLoad.cpp + +# Build the files in this directory as a shared library +include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK index 84258474072b91..c7f3ec528b1238 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK @@ -1,4 +1,4 @@ -load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "FBJNI_TARGET", "react_native_target", "react_native_xplat_shared_library_target", "react_native_xplat_target", "rn_xplat_cxx_library") rn_xplat_cxx_library( name = "jni", @@ -33,8 +33,9 @@ rn_xplat_cxx_library( ], exported_deps = [ ":callinvokerholder", - "//xplat/jsi:jsi", - react_native_xplat_target("turbomodule/core:core"), + react_native_xplat_shared_library_target("jsi:jsi"), + react_native_xplat_target("react/nativemodule/core:core"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_target("java/com/facebook/react/reactperflogger/jni:jni"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.cpp b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.cpp index 131b41b075ecb3..5878375bd3678d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.cpp @@ -23,12 +23,12 @@ namespace react { TurboModuleManager::TurboModuleManager( jni::alias_ref jThis, - jsi::Runtime *rt, + RuntimeExecutor runtimeExecutor, std::shared_ptr jsCallInvoker, std::shared_ptr nativeCallInvoker, jni::alias_ref delegate) : javaPart_(jni::make_global(jThis)), - runtime_(rt), + runtimeExecutor_(runtimeExecutor), jsCallInvoker_(jsCallInvoker), nativeCallInvoker_(nativeCallInvoker), delegate_(jni::make_global(delegate)), @@ -36,19 +36,16 @@ TurboModuleManager::TurboModuleManager( jni::local_ref TurboModuleManager::initHybrid( jni::alias_ref jThis, - jlong jsContext, + jni::alias_ref runtimeExecutor, jni::alias_ref jsCallInvokerHolder, jni::alias_ref nativeCallInvokerHolder, - jni::alias_ref delegate, - bool enablePromiseAsyncDispatch) { + jni::alias_ref delegate) { auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); auto nativeCallInvoker = nativeCallInvokerHolder->cthis()->getCallInvoker(); - JavaTurboModule::enablePromiseAsyncDispatch(enablePromiseAsyncDispatch); - return makeCxxInstance( jThis, - (jsi::Runtime *)jsContext, + runtimeExecutor->cthis()->get(), jsCallInvoker, nativeCallInvoker, delegate); @@ -63,91 +60,90 @@ void TurboModuleManager::registerNatives() { } void TurboModuleManager::installJSIBindings() { - if (!runtime_ || !jsCallInvoker_) { + if (!jsCallInvoker_) { return; // Runtime doesn't exist when attached to Chrome debugger. } - auto turboModuleProvider = - [turboModuleCache_ = std::weak_ptr(turboModuleCache_), - jsCallInvoker_ = std::weak_ptr(jsCallInvoker_), - nativeCallInvoker_ = std::weak_ptr(nativeCallInvoker_), - delegate_ = jni::make_weak(delegate_), - javaPart_ = jni::make_weak(javaPart_)]( - const std::string &name, - const jsi::Value *schema) -> std::shared_ptr { - auto turboModuleCache = turboModuleCache_.lock(); - auto jsCallInvoker = jsCallInvoker_.lock(); - auto nativeCallInvoker = nativeCallInvoker_.lock(); - auto delegate = delegate_.lockLocal(); - auto javaPart = javaPart_.lockLocal(); - - if (!turboModuleCache || !jsCallInvoker || !nativeCallInvoker || - !delegate || !javaPart) { - return nullptr; - } + runtimeExecutor_([this](jsi::Runtime &runtime) { + auto turboModuleProvider = + [turboModuleCache_ = std::weak_ptr(turboModuleCache_), + jsCallInvoker_ = std::weak_ptr(jsCallInvoker_), + nativeCallInvoker_ = std::weak_ptr(nativeCallInvoker_), + delegate_ = jni::make_weak(delegate_), + javaPart_ = jni::make_weak(javaPart_)]( + const std::string &name) -> std::shared_ptr { + auto turboModuleCache = turboModuleCache_.lock(); + auto jsCallInvoker = jsCallInvoker_.lock(); + auto nativeCallInvoker = nativeCallInvoker_.lock(); + auto delegate = delegate_.lockLocal(); + auto javaPart = javaPart_.lockLocal(); + + if (!turboModuleCache || !jsCallInvoker || !nativeCallInvoker || + !delegate || !javaPart) { + return nullptr; + } + + const char *moduleName = name.c_str(); + + TurboModulePerfLogger::moduleJSRequireBeginningStart(moduleName); + + auto turboModuleLookup = turboModuleCache->find(name); + if (turboModuleLookup != turboModuleCache->end()) { + TurboModulePerfLogger::moduleJSRequireBeginningCacheHit(moduleName); + TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); + return turboModuleLookup->second; + } - const char *moduleName = name.c_str(); + TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); - TurboModulePerfLogger::moduleJSRequireBeginningStart(moduleName); + auto cxxModule = delegate->cthis()->getTurboModule(name, jsCallInvoker); + if (cxxModule) { + turboModuleCache->insert({name, cxxModule}); + return cxxModule; + } + + static auto getLegacyCxxModule = + javaPart->getClass() + ->getMethod( + const std::string &)>("getLegacyCxxModule"); + auto legacyCxxModule = getLegacyCxxModule(javaPart.get(), name); + + if (legacyCxxModule) { + TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); + + auto turboModule = std::make_shared( + legacyCxxModule->cthis()->getModule(), jsCallInvoker); + turboModuleCache->insert({name, turboModule}); + + TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName); + return turboModule; + } + + static auto getJavaModule = + javaPart->getClass() + ->getMethod(const std::string &)>( + "getJavaModule"); + auto moduleInstance = getJavaModule(javaPart.get(), name); + + if (moduleInstance) { + TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); + JavaTurboModule::InitParams params = { + .moduleName = name, + .instance = moduleInstance, + .jsInvoker = jsCallInvoker, + .nativeInvoker = nativeCallInvoker}; + + auto turboModule = delegate->cthis()->getTurboModule(name, params); + turboModuleCache->insert({name, turboModule}); + TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName); + return turboModule; + } - auto turboModuleLookup = turboModuleCache->find(name); - if (turboModuleLookup != turboModuleCache->end()) { - TurboModulePerfLogger::moduleJSRequireBeginningCacheHit(moduleName); - TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); - return turboModuleLookup->second; - } - - TurboModulePerfLogger::moduleJSRequireBeginningEnd(moduleName); - - auto cxxModule = delegate->cthis()->getTurboModule(name, jsCallInvoker); - if (cxxModule) { - turboModuleCache->insert({name, cxxModule}); - return cxxModule; - } - - static auto getLegacyCxxModule = - javaPart->getClass() - ->getMethod( - const std::string &)>("getLegacyCxxModule"); - auto legacyCxxModule = getLegacyCxxModule(javaPart.get(), name); - - if (legacyCxxModule) { - TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); - - auto turboModule = std::make_shared( - legacyCxxModule->cthis()->getModule(), jsCallInvoker); - turboModuleCache->insert({name, turboModule}); - - TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName); - return turboModule; - } - - static auto getJavaModule = - javaPart->getClass() - ->getMethod(const std::string &)>( - "getJavaModule"); - auto moduleInstance = getJavaModule(javaPart.get(), name); - - if (moduleInstance) { - TurboModulePerfLogger::moduleJSRequireEndingStart(moduleName); - JavaTurboModule::InitParams params = {.moduleName = name, - .instance = moduleInstance, - .jsInvoker = jsCallInvoker, - .nativeInvoker = nativeCallInvoker}; - - auto turboModule = delegate->cthis()->getTurboModule(name, params); - turboModuleCache->insert({name, turboModule}); - TurboModulePerfLogger::moduleJSRequireEndingEnd(moduleName); - return turboModule; - } - - return nullptr; - }; - - jsCallInvoker_->invokeAsync( - [this, turboModuleProvider = std::move(turboModuleProvider)]() -> void { - TurboModuleBinding::install(*runtime_, std::move(turboModuleProvider)); - }); + return nullptr; + }; + + TurboModuleBinding::install(runtime, std::move(turboModuleProvider)); + }); } } // namespace react diff --git a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.h b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.h index 899d2a1d1cf8e4..a8b05fda4d5ddd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.h +++ b/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/ReactCommon/TurboModuleManager.h @@ -9,12 +9,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -27,17 +29,16 @@ class TurboModuleManager : public jni::HybridClass { "Lcom/facebook/react/turbomodule/core/TurboModuleManager;"; static jni::local_ref initHybrid( jni::alias_ref jThis, - jlong jsContext, + jni::alias_ref runtimeExecutor, jni::alias_ref jsCallInvokerHolder, jni::alias_ref nativeCallInvokerHolder, - jni::alias_ref delegate, - bool enablePromiseAsyncDispatch); + jni::alias_ref delegate); static void registerNatives(); private: friend HybridBase; jni::global_ref javaPart_; - jsi::Runtime *runtime_; + RuntimeExecutor runtimeExecutor_; std::shared_ptr jsCallInvoker_; std::shared_ptr nativeCallInvoker_; jni::global_ref delegate_; @@ -56,7 +57,7 @@ class TurboModuleManager : public jni::HybridClass { void installJSIBindings(); explicit TurboModuleManager( jni::alias_ref jThis, - jsi::Runtime *rt, + RuntimeExecutor runtimeExecutor, std::shared_ptr jsCallInvoker, std::shared_ptr nativeCallInvoker, jni::alias_ref delegate); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK index 985aeb4e9ed375..6e8ed014b95f13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK @@ -13,6 +13,7 @@ rn_android_library( "DisplayMetricsHolder.java", ], ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -43,7 +44,6 @@ rn_android_library( react_native_target("java/com/facebook/react/touch:touch"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), react_native_target("java/com/facebook/react/uimanager/util:util"), - react_native_target("java/com/facebook/react/uimanager/common:common"), react_native_target("res:uimanager"), ], exported_deps = [ @@ -51,6 +51,7 @@ rn_android_library( react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_target("java/com/facebook/react/uimanager/common:common"), + react_native_target("java/com/facebook/react/uimanager/interfaces:interfaces"), ], ) @@ -59,6 +60,7 @@ rn_android_library( srcs = [ "DisplayMetricsHolder.java", ], + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ 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 2028bdb6082536..7ab93dc676f313 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -183,8 +183,7 @@ public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilitySta && accessibilityState.getType(STATE_CHECKED) == ReadableType.String)) { updateViewContentDescription(view); break; - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && view.isAccessibilityFocused()) { + } else if (view.isAccessibilityFocused()) { // Internally Talkback ONLY uses TYPE_VIEW_CLICKED for "checked" and // "selected" announcements. Send a click event to make sure Talkback // get notified for the state changes that don't happen upon users' click. diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java index b629caa15155ef..8ecd9cdf94221a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java @@ -8,17 +8,12 @@ package com.facebook.react.uimanager; import android.content.Context; -import android.os.Build; import android.util.DisplayMetrics; import android.view.Display; import android.view.WindowManager; import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.common.ReactConstants; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -65,32 +60,7 @@ public static void initDisplayMetrics(Context context) { // // See: // http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - display.getRealMetrics(screenDisplayMetrics); - } else { - // For 14 <= API level <= 16, we need to invoke getRawHeight and getRawWidth to get the real - // dimensions. - // Since react-native only supports API level 16+ we don't have to worry about other cases. - // - // Reflection exceptions are rethrown at runtime. - // - // See: - // http://stackoverflow.com/questions/14341041/how-to-get-real-screen-height-and-width/23861333#23861333 - try { - Method mGetRawH = Display.class.getMethod("getRawHeight"); - Method mGetRawW = Display.class.getMethod("getRawWidth"); - screenDisplayMetrics.widthPixels = (Integer) mGetRawW.invoke(display); - screenDisplayMetrics.heightPixels = (Integer) mGetRawH.invoke(display); - } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { - // this may not be 100% accurate, but it's all we've got - screenDisplayMetrics.widthPixels = display.getWidth(); - screenDisplayMetrics.heightPixels = display.getHeight(); - FLog.e( - ReactConstants.TAG, - "Unable to access getRawHeight and getRawWidth to get real dimensions.", - e); - } - } + display.getRealMetrics(screenDisplayMetrics); DisplayMetricsHolder.setScreenDisplayMetrics(screenDisplayMetrics); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/FabricViewStateManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/FabricViewStateManager.java index 073b91122f0338..f0b7cfb8ff6682 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/FabricViewStateManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/FabricViewStateManager.java @@ -11,7 +11,6 @@ import com.facebook.common.logging.FLog; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.config.ReactFeatureFlags; /** * This is a helper base class for ViewGroups that use Fabric State. @@ -67,26 +66,22 @@ private void setState( return; } - Runnable failureRunnable = null; - if (ReactFeatureFlags.enableExperimentalStateUpdateRetry) { - failureRunnable = - new Runnable() { - @Override - // Run on the UI thread - public void run() { - FLog.e(TAG, "UpdateState failed - retrying! " + numTries); - setState(stateWrapper, stateUpdateCallback, numTries + 1); - } - }; - } + Runnable failureRunnable = + new Runnable() { + @Override + // Run on the UI thread + public void run() { + FLog.e(TAG, "UpdateState failed - retrying! " + numTries); + setState(stateWrapper, stateUpdateCallback, numTries + 1); + } + }; @Nullable WritableMap stateUpdate = stateUpdateCallback.getStateUpdate(); if (stateUpdate == null) { return; } - stateWrapper.updateState( - stateUpdate, - // Failure callback - this is run if the updateState call fails - failureRunnable); + + // TODO: State update cannot fail; remove `failureRunnable` and custom retrying logic. + stateWrapper.updateState(stateUpdate); } public void setState(final StateUpdateCallback stateUpdateCallback) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java index e103cd3923c8e4..db0224d0871cda 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java @@ -50,6 +50,17 @@ public void onChildStartedNativeGesture( mTargetTag = -1; } + private int getSurfaceId() { + if (mRootViewGroup instanceof ReactRoot) { + return ((ReactRoot) mRootViewGroup).getRootViewTag(); + } + if (mRootViewGroup != null && mRootViewGroup.getContext() instanceof ThemedReactContext) { + ThemedReactContext context = (ThemedReactContext) mRootViewGroup.getContext(); + return context.getSurfaceId(); + } + return -1; + } + /** * Main catalyst view is responsible for collecting and sending touch events to JS. This method * reacts for an incoming android native touch events ({@link MotionEvent}) and calls into {@link @@ -70,9 +81,11 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) { // this gesture mChildIsHandlingNativeGesture = false; mGestureStartTime = ev.getEventTime(); + mTargetTag = findTargetTagAndSetCoordinates(ev); eventDispatcher.dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.START, ev, @@ -97,6 +110,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) { findTargetTagAndSetCoordinates(ev); eventDispatcher.dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.END, ev, @@ -111,6 +125,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) { findTargetTagAndSetCoordinates(ev); eventDispatcher.dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.MOVE, ev, @@ -122,6 +137,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) { // New pointer goes down, this can only happen after ACTION_DOWN is sent for the first pointer eventDispatcher.dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.START, ev, @@ -133,6 +149,7 @@ public void handleTouchEvent(MotionEvent ev, EventDispatcher eventDispatcher) { // Exactly onw of the pointers goes up eventDispatcher.dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.END, ev, @@ -181,6 +198,7 @@ private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher event Assertions.assertNotNull(eventDispatcher) .dispatchEvent( TouchEvent.obtain( + getSurfaceId(), mTargetTag, TouchEventType.CANCEL, androidEvent, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index a5e9e13ace4c8a..26dc859215cdb7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -29,6 +29,7 @@ import com.facebook.react.bridge.RetryableMountingLayerException; import com.facebook.react.bridge.SoftAssertions; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.touch.JSResponderHandler; import com.facebook.react.uimanager.layoutanimation.LayoutAnimationController; @@ -69,6 +70,7 @@ public class NativeViewHierarchyManager { private static final String TAG = NativeViewHierarchyManager.class.getSimpleName(); + private final boolean DEBUG_MODE = ReactBuildConfig.DEBUG && false; private final SparseArray mTagsToViews; private final SparseArray mTagsToViewManagers; @@ -128,6 +130,9 @@ public synchronized void updateInstanceHandle(int tag, long instanceHandle) { } public synchronized void updateProperties(int tag, ReactStylesDiffMap props) { + if (DEBUG_MODE) { + FLog.d(TAG, "updateProperties[%d]: %s", tag, props.toString()); + } UiThreadUtil.assertOnUiThread(); try { @@ -143,6 +148,9 @@ public synchronized void updateProperties(int tag, ReactStylesDiffMap props) { } public synchronized void updateViewExtraData(int tag, Object extraData) { + if (DEBUG_MODE) { + FLog.d(TAG, "updateViewExtraData[%d]: %s", tag, extraData.toString()); + } UiThreadUtil.assertOnUiThread(); ViewManager viewManager = resolveViewManager(tag); @@ -152,6 +160,9 @@ public synchronized void updateViewExtraData(int tag, Object extraData) { public synchronized void updateLayout( int parentTag, int tag, int x, int y, int width, int height) { + if (DEBUG_MODE) { + FLog.d(TAG, "updateLayout[%d]->[%d]: %d %d %d %d", tag, parentTag, x, y, width, height); + } UiThreadUtil.assertOnUiThread(); SystraceMessage.beginSection( Systrace.TRACE_TAG_REACT_VIEW, "NativeViewHierarchyManager_updateLayout") @@ -250,6 +261,14 @@ public synchronized void createView( int tag, String className, @Nullable ReactStylesDiffMap initialProps) { + if (DEBUG_MODE) { + FLog.d( + TAG, + "createView[%d]: %s %s", + tag, + className, + (initialProps != null ? initialProps.toString() : "")); + } UiThreadUtil.assertOnUiThread(); SystraceMessage.beginSection( Systrace.TRACE_TAG_REACT_VIEW, "NativeViewHierarchyManager_createView") @@ -259,7 +278,7 @@ public synchronized void createView( try { ViewManager viewManager = mViewManagers.get(className); - View view = viewManager.createView(themedContext, null, null, mJSResponderHandler); + View view = viewManager.createView(tag, themedContext, null, null, mJSResponderHandler); mTagsToViews.put(tag, view); mTagsToViewManagers.put(tag, viewManager); @@ -372,6 +391,15 @@ public synchronized void manageChildren( @Nullable int[] indicesToRemove, @Nullable ViewAtIndex[] viewsToAdd, @Nullable int[] tagsToDelete) { + if (DEBUG_MODE) { + FLog.d( + TAG, + "createView[%d]: %s %s %s", + tag, + (indicesToRemove != null ? indicesToRemove.toString() : ""), + (viewsToAdd != null ? viewsToAdd.toString() : ""), + (tagsToDelete != null ? tagsToDelete.toString() : "")); + } UiThreadUtil.assertOnUiThread(); final Set pendingDeletionTags = getPendingDeletionsForTag(tag); @@ -545,6 +573,13 @@ private static String constructSetChildrenErrorMessage( /** Simplified version of manageChildren that only deals with adding children views */ public synchronized void setChildren(int tag, ReadableArray childrenTags) { + if (DEBUG_MODE) { + FLog.d( + TAG, + "setChildren[%d]: %s", + tag, + (childrenTags != null ? childrenTags.toString() : "")); + } UiThreadUtil.assertOnUiThread(); ViewGroup viewToManage = (ViewGroup) mTagsToViews.get(tag); ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(tag); @@ -568,6 +603,9 @@ public synchronized void addRootView(int tag, View view) { } protected final synchronized void addRootViewGroup(int tag, View view) { + if (DEBUG_MODE) { + FLog.d(TAG, "addRootViewGroup[%d]: %s", tag, (view != null ? view.toString() : "")); + } if (view.getId() != View.NO_ID) { FLog.e( TAG, @@ -587,6 +625,9 @@ protected final synchronized void addRootViewGroup(int tag, View view) { /** Releases all references to given native View. */ protected synchronized void dropView(View view) { + if (DEBUG_MODE) { + FLog.d(TAG, "dropView[%d]", (view != null ? view.getId() : -1)); + } UiThreadUtil.assertOnUiThread(); if (view == null) { // Ignore this drop operation when view is null. @@ -620,6 +661,9 @@ protected synchronized void dropView(View view) { } public synchronized void removeRootView(int rootViewTag) { + if (DEBUG_MODE) { + FLog.d(TAG, "removeRootView[%d]", rootViewTag); + } UiThreadUtil.assertOnUiThread(); if (!mRootTags.get(rootViewTag)) { SoftAssertions.assertUnreachable( @@ -635,6 +679,9 @@ public synchronized void removeRootView(int rootViewTag) { * {x, y, width, height}. */ public synchronized void measure(int tag, int[] outputBuffer) { + if (DEBUG_MODE) { + FLog.d(TAG, "measure[%d]", tag); + } UiThreadUtil.assertOnUiThread(); View v = mTagsToViews.get(tag); if (v == null) { @@ -699,6 +746,9 @@ private void mapRectFromViewToWindowCoords(View view, RectF rect) { * relative to the device window */ public synchronized void measureInWindow(int tag, int[] outputBuffer) { + if (DEBUG_MODE) { + FLog.d(TAG, "measureInWindow[%d]", tag); + } UiThreadUtil.assertOnUiThread(); View v = mTagsToViews.get(tag); if (v == null) { @@ -720,6 +770,9 @@ public synchronized void measureInWindow(int tag, int[] outputBuffer) { } public synchronized int findTargetTagForTouch(int reactTag, float touchX, float touchY) { + if (DEBUG_MODE) { + FLog.d(TAG, "findTargetTagForTouch[%d]: %f %f", reactTag, touchX, touchY); + } UiThreadUtil.assertOnUiThread(); View view = mTagsToViews.get(reactTag); if (view == null) { @@ -765,6 +818,14 @@ void clearLayoutAnimation() { @Deprecated public synchronized void dispatchCommand( int reactTag, int commandId, @Nullable ReadableArray args) { + if (DEBUG_MODE) { + FLog.d( + TAG, + "dispatchCommand[%d]: %d %s", + reactTag, + commandId, + (args != null ? args.toString() : "")); + } UiThreadUtil.assertOnUiThread(); View view = mTagsToViews.get(reactTag); if (view == null) { @@ -780,6 +841,14 @@ public synchronized void dispatchCommand( public synchronized void dispatchCommand( int reactTag, String commandId, @Nullable ReadableArray args) { + if (DEBUG_MODE) { + FLog.d( + TAG, + "dispatchCommand[%d]: %s %s", + reactTag, + commandId, + (args != null ? args.toString() : "")); + } UiThreadUtil.assertOnUiThread(); View view = mTagsToViews.get(reactTag); if (view == null) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/OnLayoutEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/OnLayoutEvent.java index 1278dc253d00b7..d7eb8de6860c28 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/OnLayoutEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/OnLayoutEvent.java @@ -7,11 +7,11 @@ package com.facebook.react.uimanager; +import androidx.annotation.Nullable; import androidx.core.util.Pools; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event used to notify JS component about changes of its position or dimensions */ public class OnLayoutEvent extends Event { @@ -21,12 +21,18 @@ public class OnLayoutEvent extends Event { private int mX, mY, mWidth, mHeight; + @Deprecated public static OnLayoutEvent obtain(int viewTag, int x, int y, int width, int height) { + return obtain(-1, viewTag, x, y, width, height); + } + + public static OnLayoutEvent obtain( + int surfaceId, int viewTag, int x, int y, int width, int height) { OnLayoutEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new OnLayoutEvent(); } - event.init(viewTag, x, y, width, height); + event.init(surfaceId, viewTag, x, y, width, height); return event; } @@ -37,8 +43,13 @@ public void onDispose() { private OnLayoutEvent() {} + @Deprecated protected void init(int viewTag, int x, int y, int width, int height) { - super.init(viewTag); + init(-1, viewTag, x, y, width, height); + } + + protected void init(int surfaceId, int viewTag, int x, int y, int width, int height) { + super.init(surfaceId, viewTag); mX = x; mY = y; mWidth = width; @@ -50,8 +61,9 @@ public String getEventName() { return "topLayout"; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { + protected WritableMap getEventData() { WritableMap layout = Arguments.createMap(); layout.putDouble("x", PixelUtil.toDIPFromPixel(mX)); layout.putDouble("y", PixelUtil.toDIPFromPixel(mY)); @@ -61,7 +73,6 @@ public void dispatch(RCTEventEmitter rctEventEmitter) { WritableMap event = Arguments.createMap(); event.putMap("layout", layout); event.putInt("target", getViewTag()); - - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event); + return event; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 22b82bed0ca1d5..5ff4eb75ee7dfc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -35,7 +35,6 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.events.RCTEventEmitter; import java.util.HashMap; /** @@ -246,6 +245,15 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo } } } + + // Expose the testID prop as the resource-id name of the view. Black-box E2E/UI testing + // frameworks, which interact with the UI through the accessibility framework, do not have + // access to view tags. This allows developers/testers to avoid polluting the + // content-description with test identifiers. + final String testId = (String) host.getTag(R.id.react_test_id); + if (testId != null) { + info.setViewIdResourceName(testId); + } } @Override @@ -286,20 +294,21 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) { ReactContext reactContext = (ReactContext) host.getContext(); if (reactContext.hasActiveCatalystInstance()) { final int reactTag = host.getId(); + final int surfaceId = UIManagerHelper.getSurfaceId(reactContext); UIManager uiManager = UIManagerHelper.getUIManager(reactContext, reactTag); if (uiManager != null) { uiManager .getEventDispatcher() .dispatchEvent( - new Event(reactTag) { + new Event(surfaceId, reactTag) { @Override public String getEventName() { return TOP_ACCESSIBILITY_ACTION_EVENT; } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(reactTag, TOP_ACCESSIBILITY_ACTION_EVENT, event); + protected WritableMap getEventData() { + return event; } }); } @@ -425,7 +434,8 @@ public static void setDelegate(final View view) { if (!ViewCompat.hasAccessibilityDelegate(view) && (view.getTag(R.id.accessibility_role) != null || view.getTag(R.id.accessibility_state) != null - || view.getTag(R.id.accessibility_actions) != null)) { + || view.getTag(R.id.accessibility_actions) != null + || view.getTag(R.id.react_test_id) != null)) { ViewCompat.setAccessibilityDelegate(view, new ReactAccessibilityDelegate()); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactClippingViewGroupHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactClippingViewGroupHelper.java index 077fcd050860cf..393b7cc602b040 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactClippingViewGroupHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactClippingViewGroupHelper.java @@ -8,7 +8,6 @@ package com.facebook.react.uimanager; import android.graphics.Rect; -import android.graphics.RectF; import android.view.View; import android.view.ViewParent; import javax.annotation.concurrent.NotThreadSafe; @@ -57,51 +56,4 @@ public static void calculateClippingRect(View view, Rect outputRect) { } view.getDrawingRect(outputRect); } - - public static boolean getChildVisibleRectHelper( - View child, Rect r, android.graphics.Point offset, View parent, String overflow) { - // This is based on the Android ViewGroup implementation, modified to clip child rects - // if overflow is set to ViewProps.HIDDEN. This effectively solves Issue #23870 which - // appears to have been introduced by FLAG_CLIP_CHILDREN being forced false - // regardless of whether clipping is desired. - final RectF rect = new RectF(); - rect.set(r); - - child.getMatrix().mapRect(rect); - - final int dx = child.getLeft() - parent.getScrollX(); - final int dy = child.getTop() - parent.getScrollY(); - - rect.offset(dx, dy); - - if (offset != null) { - float[] position = new float[2]; - position[0] = offset.x; - position[1] = offset.y; - child.getMatrix().mapPoints(position); - offset.x = Math.round(position[0]) + dx; - offset.y = Math.round(position[1]) + dy; - } - - final int width = parent.getRight() - parent.getLeft(); - final int height = parent.getBottom() - parent.getTop(); - - boolean rectIsVisible = true; - - ViewParent grandparent = parent.getParent(); - if (grandparent == null || ViewProps.HIDDEN.equals(overflow)) { - rectIsVisible = rect.intersect(0, 0, width, height); - } - - r.set( - (int) Math.floor(rect.left), - (int) Math.floor(rect.top), - (int) Math.ceil(rect.right), - (int) Math.ceil(rect.bottom)); - - if (rectIsVisible && grandparent != null) { - rectIsVisible = grandparent.getChildVisibleRect(parent, r, offset); - } - return rectIsVisible; - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java index 2fba8c52164c75..9ce17ea680954a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactRoot.java @@ -11,10 +11,16 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import com.facebook.react.uimanager.common.UIManagerType; +import java.util.concurrent.atomic.AtomicInteger; /** Interface for the root native view of a React native application */ public interface ReactRoot { + /** This constant represents that ReactRoot hasn't started yet or it has been destroyed. */ + int STATE_STOPPED = 0; + /** This constant represents that ReactRoot has started. */ + int STATE_STARTED = 1; + /** Return cached launch properties for app */ @Nullable Bundle getAppProperties(); @@ -58,4 +64,12 @@ public interface ReactRoot { @Deprecated @Nullable String getSurfaceID(); + + /** + * This API is likely to change once the fix of T78832286 is confirmed TODO: T78832286 revisit + * this API + * + * @return an {@link AtomicInteger} that represents the state of the ReactRoot object. WARNING: + */ + AtomicInteger getState(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/StateWrapper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/StateWrapper.java index 51bbc14349a446..c21d2414d0b3a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/StateWrapper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/StateWrapper.java @@ -22,8 +22,8 @@ public interface StateWrapper { ReadableNativeMap getState(); /** - * Pass a map of values back to the C++ layer. /Last/ runnable passed into updateState is called - * if an updateState call fails. + * Pass a map of values back to the C++ layer. The operation is performed synchronously and cannot + * fail. */ - void updateState(WritableMap map, Runnable failureCallback); + void updateState(WritableMap map); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java index 834208a962e676..15701d63618a40 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java @@ -27,20 +27,32 @@ public class ThemedReactContext extends ReactContext { private final ReactApplicationContext mReactApplicationContext; - @Nullable private final String mSurfaceID; + @Nullable private final String mModuleName; + private final int mSurfaceId; + @Deprecated public ThemedReactContext(ReactApplicationContext reactApplicationContext, Context base) { - this(reactApplicationContext, base, null); + this(reactApplicationContext, base, null, -1); } + @Deprecated public ThemedReactContext( - ReactApplicationContext reactApplicationContext, Context base, @Nullable String surfaceID) { + ReactApplicationContext reactApplicationContext, Context base, @Nullable String moduleName) { + this(reactApplicationContext, base, moduleName, -1); + } + + public ThemedReactContext( + ReactApplicationContext reactApplicationContext, + Context base, + @Nullable String moduleName, + int surfaceId) { super(base); if (reactApplicationContext.hasCatalystInstance()) { initializeWithInstance(reactApplicationContext.getCatalystInstance()); } mReactApplicationContext = reactApplicationContext; - mSurfaceID = surfaceID; + mModuleName = moduleName; + mSurfaceId = surfaceId; } @Override @@ -64,11 +76,27 @@ public boolean hasCurrentActivity() { } /** - * @return a {@link String} that represents the ID of the js application that is being rendered - * with this {@link ThemedReactContext} + * This is misnamed but has some uses out in the wild. It will be deleted in a future release of + * RN. + * + * @return a {@link String} that represents the module name of the js application that is being + * rendered with this {@link ThemedReactContext} */ + @Deprecated public @Nullable String getSurfaceID() { - return mSurfaceID; + return mModuleName; + } + + /** + * @return a {@link String} that represents the module name of the js application that is being + * rendered with this {@link ThemedReactContext} + */ + public @Nullable String getModuleName() { + return mModuleName; + } + + public int getSurfaceId() { + return mSurfaceId; } public ReactApplicationContext getReactApplicationContext() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index 16630deff02277..e0fb11950fa33b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -51,6 +51,13 @@ public class UIImplementation { private long mLastCalculateLayoutTime = 0; protected @Nullable LayoutUpdateListener mLayoutUpdateListener; + /** + * When react instance is being shutdown, there could be some pending operations queued in the JS + * thread. This flag ensures view related operations are not triggered if the Catalyst instance + * was destroyed. + */ + private volatile boolean mViewOperationsEnabled = true; + /** Interface definition for a callback to be invoked when the layout has been updated */ public interface LayoutUpdateListener { @@ -234,6 +241,10 @@ public Map getProfiledBatchPerfCounters() { /** Invoked by React to create a new node with a given tag, class name and properties. */ public void createView(int tag, String className, int rootViewTag, ReadableMap props) { + if (!mViewOperationsEnabled) { + return; + } + synchronized (uiImplementationThreadLock) { ReactShadowNode cssNode = createShadowNode(className); ReactShadowNode rootNode = mShadowNodeRegistry.getNode(rootViewTag); @@ -264,6 +275,10 @@ protected void handleCreateView( /** Invoked by React to create a new node with a given tag has its properties changed. */ public void updateView(int tag, String className, ReadableMap props) { + if (!mViewOperationsEnabled) { + return; + } + ViewManager viewManager = mViewManagers.get(className); if (viewManager == null) { throw new IllegalViewOperationException("Got unknown view type: " + className); @@ -314,6 +329,10 @@ public void manageChildren( @Nullable ReadableArray addChildTags, @Nullable ReadableArray addAtIndices, @Nullable ReadableArray removeFrom) { + if (!mViewOperationsEnabled) { + return; + } + synchronized (uiImplementationThreadLock) { ReactShadowNode cssNodeToManage = mShadowNodeRegistry.getNode(viewTag); @@ -420,6 +439,10 @@ public void manageChildren( * @param childrenTags tags of the children */ public void setChildren(int viewTag, ReadableArray childrenTags) { + if (!mViewOperationsEnabled) { + return; + } + synchronized (uiImplementationThreadLock) { ReactShadowNode cssNodeToManage = mShadowNodeRegistry.getNode(viewTag); @@ -530,6 +553,10 @@ public void viewIsDescendantOf( * view and returns the values via an async callback. */ public void measure(int reactTag, Callback callback) { + if (!mViewOperationsEnabled) { + return; + } + // This method is called by the implementation of JS touchable interface (see Touchable.js for // more details) at the moment of touch activation. That is after user starts the gesture from // a touchable view with a given reactTag, or when user drag finger back into the press @@ -543,6 +570,10 @@ public void measure(int reactTag, Callback callback) { * things like the status bar */ public void measureInWindow(int reactTag, Callback callback) { + if (!mViewOperationsEnabled) { + return; + } + mOperationsQueue.enqueueMeasureInWindow(reactTag, callback); } @@ -554,6 +585,10 @@ public void measureInWindow(int reactTag, Callback callback) { */ public void measureLayout( int tag, int ancestorTag, Callback errorCallback, Callback successCallback) { + if (!mViewOperationsEnabled) { + return; + } + try { measureLayout(tag, ancestorTag, mMeasureBuffer); float relativeX = PixelUtil.toDIPFromPixel(mMeasureBuffer[0]); @@ -571,6 +606,10 @@ public void measureLayout( */ public void measureLayoutRelativeToParent( int tag, Callback errorCallback, Callback successCallback) { + if (!mViewOperationsEnabled) { + return; + } + try { measureLayoutRelativeToParent(tag, mMeasureBuffer); float relativeX = PixelUtil.toDIPFromPixel(mMeasureBuffer[0]); @@ -747,6 +786,12 @@ public void onHostPause() { public void onHostDestroy() {} + public void onCatalystInstanceDestroyed() { + if (ReactFeatureFlags.disableNonFabricViewOperationsOnCatalystDestroy) { + mViewOperationsEnabled = false; + } + } + public void setViewHierarchyUpdateDebugListener( @Nullable NotThreadSafeViewHierarchyUpdateDebugListener listener) { mOperationsQueue.setViewHierarchyUpdateDebugListener(listener); @@ -913,6 +958,7 @@ protected void applyUpdatesRecursive(ReactShadowNode cssNode, float absoluteX, f if (frameDidChange && cssNode.shouldNotifyOnLayout()) { mEventDispatcher.dispatchEvent( OnLayoutEvent.obtain( + -1, /* surfaceId not used in classic renderer */ tag, cssNode.getScreenX(), cssNode.getScreenY(), diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java index 65b222408f66ad..dd51fe3a32f318 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java @@ -9,6 +9,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.systrace.Systrace; import java.util.List; /** Provides UIImplementation to use in {@link UIManagerModule}. */ @@ -20,11 +21,17 @@ public UIImplementation createUIImplementation( UIManagerModule.ViewManagerResolver viewManagerResolver, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) { - return new UIImplementation( - reactContext, - viewManagerResolver, - eventDispatcher, - minTimeLeftInFrameForNonBatchedOperationMs); + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementationProvider.createUIImplementation[1]"); + try { + return new UIImplementation( + reactContext, + viewManagerResolver, + eventDispatcher, + minTimeLeftInFrameForNonBatchedOperationMs); + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } } public UIImplementation createUIImplementation( @@ -32,8 +39,17 @@ public UIImplementation createUIImplementation( List viewManagerList, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) { - return new UIImplementation( - reactContext, viewManagerList, eventDispatcher, minTimeLeftInFrameForNonBatchedOperationMs); + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementationProvider.createUIImplementation[2]"); + try { + return new UIImplementation( + reactContext, + viewManagerList, + eventDispatcher, + minTimeLeftInFrameForNonBatchedOperationMs); + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } } UIImplementation createUIImplementation( @@ -41,10 +57,16 @@ UIImplementation createUIImplementation( ViewManagerRegistry viewManagerRegistry, EventDispatcher eventDispatcher, int minTimeLeftInFrameForNonBatchedOperationMs) { - return new UIImplementation( - reactContext, - viewManagerRegistry, - eventDispatcher, - minTimeLeftInFrameForNonBatchedOperationMs); + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementationProvider.createUIImplementation[3]"); + try { + return new UIImplementation( + reactContext, + viewManagerRegistry, + eventDispatcher, + minTimeLeftInFrameForNonBatchedOperationMs); + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index 954dfe95edfb3c..f68548d86ba645 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -52,11 +52,7 @@ private static UIManager getUIManager( @UIManagerType int uiManagerType, boolean returnNullIfCatalystIsInactive) { if (context.isBridgeless()) { - @Nullable - UIManager uiManager = - context.getJSIModule(JSIModuleType.UIManager) != null - ? (UIManager) context.getJSIModule(JSIModuleType.UIManager) - : null; + @Nullable UIManager uiManager = (UIManager) context.getJSIModule(JSIModuleType.UIManager); if (uiManager == null) { ReactSoftException.logSoftException( "UIManagerHelper", @@ -97,7 +93,13 @@ private static UIManager getUIManager( */ @Nullable public static EventDispatcher getEventDispatcherForReactTag(ReactContext context, int reactTag) { - return getEventDispatcher(context, getUIManagerType(reactTag)); + EventDispatcher eventDispatcher = getEventDispatcher(context, getUIManagerType(reactTag)); + if (eventDispatcher == null) { + ReactSoftException.logSoftException( + "UIManagerHelper", + new IllegalStateException("Cannot get EventDispatcher for reactTag " + reactTag)); + } + return eventDispatcher; } /** @@ -115,7 +117,21 @@ public static EventDispatcher getEventDispatcher( return ((EventDispatcherProvider) context).getEventDispatcher(); } UIManager uiManager = getUIManager(context, uiManagerType, false); - return uiManager == null ? null : (EventDispatcher) uiManager.getEventDispatcher(); + if (uiManager == null) { + ReactSoftException.logSoftException( + "UIManagerHelper", + new ReactNoCrashSoftException( + "Unable to find UIManager for UIManagerType " + uiManagerType)); + return null; + } + EventDispatcher eventDispatcher = (EventDispatcher) uiManager.getEventDispatcher(); + if (eventDispatcher == null) { + ReactSoftException.logSoftException( + "UIManagerHelper", + new IllegalStateException( + "Cannot get EventDispatcher for UIManagerType " + uiManagerType)); + } + return eventDispatcher; } /** @@ -134,6 +150,42 @@ public static ReactContext getReactContext(View view) { return (ReactContext) context; } + /** + * @return Get the ThemedReactContext associated with a View, if possible, and then call + * getSurfaceId on it. See above (getReactContext) for additional context. + */ + public static int getSurfaceId(View view) { + int reactTag = view.getId(); + + // In non-Fabric we don't have (or use) SurfaceId + if (getUIManagerType(reactTag) == UIManagerType.DEFAULT) { + return -1; + } + + Context context = view.getContext(); + if (!(context instanceof ThemedReactContext) && context instanceof ContextWrapper) { + context = ((ContextWrapper) context).getBaseContext(); + } + + int surfaceId = getSurfaceId(context); + + // All Fabric-managed Views (should) have a ThemedReactContext attached. + if (surfaceId == -1) { + ReactSoftException.logSoftException( + "UIManagerHelper", + new IllegalStateException( + "Fabric View [" + reactTag + "] does not have SurfaceId associated with it")); + } + return surfaceId; + } + + public static int getSurfaceId(Context context) { + if (context instanceof ThemedReactContext) { + return ((ThemedReactContext) context).getSurfaceId(); + } + return -1; + } + /** * @return the default padding used by Android EditText's. This method returns the padding in an * array to avoid extra classloading during hot-path of RN Android. diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 17480d628e73c3..36457847cb1128 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -15,6 +15,7 @@ import android.content.ComponentCallbacks2; import android.content.res.Configuration; import android.view.View; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.collection.ArrayMap; import com.facebook.common.logging.FLog; @@ -39,6 +40,7 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.common.ReactConstants; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.common.ViewUtil; import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener; @@ -85,6 +87,7 @@ @ReactModule(name = UIManagerModule.NAME) public class UIManagerModule extends ReactContextBaseJavaModule implements OnBatchCompleteListener, LifecycleEventListener, UIManager { + public static final String TAG = UIManagerModule.class.getSimpleName(); /** Enables lazy discovery of a specific {@link ViewManager} by its name. */ public interface ViewManagerResolver { @@ -207,7 +210,7 @@ public UIImplementation getUIImplementation() { } @Override - public String getName() { + public @NonNull String getName() { return NAME; } @@ -242,6 +245,7 @@ public void onHostDestroy() { public void onCatalystInstanceDestroy() { super.onCatalystInstanceDestroy(); mEventDispatcher.onCatalystInstanceDestroyed(); + mUIImplementation.onCatalystInstanceDestroyed(); getReactApplicationContext().unregisterComponentCallbacks(mMemoryTrimCallback); YogaNodePool.get().clear(); @@ -291,11 +295,22 @@ private static Map createConstants( * Helper method to pre-compute the constants for a view manager. This method ensures that we * don't block for getting the constants for view managers during TTI * - * @deprecated this method will not be available in FabricUIManager class. + * @deprecated this method will be removed in the future * @param viewManagerNames {@link List} names of ViewManagers */ @Deprecated - public void preComputeConstantsForViewManager(List viewManagerNames) { + @Override + public void preInitializeViewManagers(List viewManagerNames) { + if (ReactFeatureFlags.enableExperimentalStaticViewConfigs) { + for (String viewManagerName : viewManagerNames) { + mUIImplementation.resolveViewManager(viewManagerName); + } + // When Static view configs are enabled it is not necessary to pre-compute the constants for + // viewManagers, although the pre-initialization of viewManager objects is still necessary + // for performance reasons. + return; + } + Map constantsMap = new ArrayMap<>(); for (String viewManagerName : viewManagerNames) { WritableMap constants = computeConstantsForViewManager(viewManagerName); @@ -406,22 +421,17 @@ public int addRootView(final T rootView) { */ @Override public void synchronouslyUpdateViewOnUIThread(int tag, ReadableMap props) { - int uiManagerType = ViewUtil.getUIManagerType(tag); - if (uiManagerType == FABRIC) { - UIManager fabricUIManager = - UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType); - if (fabricUIManager != null) { - fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props); - } - } else { - mUIImplementation.synchronouslyUpdateViewOnUIThread(tag, new ReactStylesDiffMap(props)); - } + mUIImplementation.synchronouslyUpdateViewOnUIThread(tag, new ReactStylesDiffMap(props)); } /** * Registers a new root view. JS can use the returned tag with manageChildren to add/remove * children to this view. * + *

Calling addRootView through UIManagerModule calls addRootView in the non-Fabric renderer, + * always. This is deprecated in favor of calling startSurface in Fabric, which must be done + * directly through the FabricUIManager. + * *

Note that this must be called after getWidth()/getHeight() actually return something. See * CatalystApplicationFragment as an example. * @@ -433,9 +443,14 @@ public int addRootView( Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIManagerModule.addRootView"); final int tag = ReactRootViewTagGenerator.getNextRootViewTag(); final ReactApplicationContext reactApplicationContext = getReactApplicationContext(); + + // We pass in a surfaceId of -1 here - it is used only in Fabric. final ThemedReactContext themedRootContext = new ThemedReactContext( - reactApplicationContext, rootView.getContext(), ((ReactRoot) rootView).getSurfaceID()); + reactApplicationContext, + rootView.getContext(), + ((ReactRoot) rootView).getSurfaceID(), + -1); mUIImplementation.registerRootView(rootView, tag, themedRootContext); Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); @@ -509,25 +524,7 @@ public void updateView(final int tag, final String className, final ReadableMap FLog.d(ReactConstants.TAG, message); PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.UI_MANAGER, message); } - int uiManagerType = ViewUtil.getUIManagerType(tag); - if (uiManagerType == FABRIC) { - ReactApplicationContext reactApplicationContext = getReactApplicationContext(); - if (reactApplicationContext.hasActiveCatalystInstance()) { - final UIManager fabricUIManager = - UIManagerHelper.getUIManager(reactApplicationContext, uiManagerType); - if (fabricUIManager != null) { - reactApplicationContext.runOnUiQueueThread( - new Runnable() { - @Override - public void run() { - fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props); - } - }); - } - } - } else { - mUIImplementation.updateView(tag, className, props); - } + mUIImplementation.updateView(tag, className, props); } /** @@ -710,8 +707,7 @@ public void clearJSResponder() { @ReactMethod public void dispatchViewManagerCommand( int reactTag, Dynamic commandId, @Nullable ReadableArray commandArgs) { - // TODO: this is a temporary approach to support ViewManagerCommands in Fabric until - // the dispatchViewManagerCommand() method is supported by Fabric JS API. + // Fabric dispatchCommands should go through the JSI API - this will crash in Fabric. @Nullable UIManager uiManager = UIManagerHelper.getUIManager( @@ -926,10 +922,14 @@ public void invalidateNodeLayout(int tag) { /** * Updates the styles of the {@link ReactShadowNode} based on the Measure specs received by - * parameters. + * parameters. offsetX and offsetY aren't used in non-Fabric, so they're ignored here. */ public void updateRootLayoutSpecs( - final int rootViewTag, final int widthMeasureSpec, final int heightMeasureSpec) { + final int rootViewTag, + final int widthMeasureSpec, + final int heightMeasureSpec, + int offsetX, + int offsetY) { ReactApplicationContext reactApplicationContext = getReactApplicationContext(); reactApplicationContext.runOnNativeModulesQueueThread( new GuardedRunnable(reactApplicationContext) { @@ -967,9 +967,16 @@ public View resolveView(int tag) { } @Override - public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event) { + public void receiveEvent(int reactTag, String eventName, @Nullable WritableMap event) { + receiveEvent(-1, reactTag, eventName, event); + } + + @Override + public void receiveEvent( + int surfaceId, int reactTag, String eventName, @Nullable WritableMap event) { + assert ViewUtil.getUIManagerType(reactTag) == DEFAULT; getReactApplicationContext() .getJSModule(RCTEventEmitter.class) - .receiveEvent(targetTag, eventName, event); + .receiveEvent(reactTag, eventName, event); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java index bb3df5f827e710..da69ca8c055f01 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java @@ -118,7 +118,13 @@ public void execute() { uiManager .getEventDispatcher() .dispatchEvent( - OnLayoutEvent.obtain(mTag, mScreenX, mScreenY, mScreenWidth, mScreenHeight)); + OnLayoutEvent.obtain( + -1 /* SurfaceId not used in classic renderer */, + mTag, + mScreenX, + mScreenY, + mScreenWidth, + mScreenHeight)); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java index a806b87a380a34..cf1be7c7ce0b62 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManager.java @@ -39,7 +39,6 @@ public abstract class ViewManager * * @param viewToUpdate * @param props - * @param stateWrapper */ public void updateProperties(@NonNull T viewToUpdate, ReactStylesDiffMap props) { final ViewManagerDelegate delegate; @@ -68,19 +67,14 @@ protected ViewManagerDelegate getDelegate() { return null; } - /** Creates a view and installs event emitters on it. */ - private final @NonNull T createView( - @NonNull ThemedReactContext reactContext, JSResponderHandler jsResponderHandler) { - return createView(reactContext, null, null, jsResponderHandler); - } - /** Creates a view with knowledge of props and state. */ public @NonNull T createView( + int reactTag, @NonNull ThemedReactContext reactContext, @Nullable ReactStylesDiffMap props, @Nullable StateWrapper stateWrapper, JSResponderHandler jsResponderHandler) { - T view = createViewInstance(reactContext, props, stateWrapper); + T view = createViewInstance(reactTag, reactContext, props, stateWrapper); if (view instanceof ReactInterceptingViewGroup) { ((ReactInterceptingViewGroup) view).setOnInterceptTouchEventListener(jsResponderHandler); } @@ -130,13 +124,18 @@ public C createShadowNodeInstance() { * that will call createViewInstance for you. Override it if you need props upon creation of the * view. * - * @param reactContext + * @param reactTag reactTag that should be set as ID of the view instance + * @param reactContext ReactContext used to initialize view instance + * @param initialProps initial props for the view instance + * @param stateWrapper initial state for the view instance */ protected @NonNull T createViewInstance( + int reactTag, @NonNull ThemedReactContext reactContext, @Nullable ReactStylesDiffMap initialProps, @Nullable StateWrapper stateWrapper) { T view = createViewInstance(reactContext); + view.setId(reactTag); addEventEmitters(reactContext, view); if (initialProps != null) { updateProperties(view, initialProps); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java index 73c37c10f12124..a6ceb3e395a670 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java @@ -56,7 +56,11 @@ public ViewManager get(String className) { if (mViewManagerResolver != null) { viewManager = getViewManagerFromResolver(className); if (viewManager != null) return viewManager; - throw new IllegalViewOperationException("ViewManagerResolver returned null for " + className); + throw new IllegalViewOperationException( + "ViewManagerResolver returned null for " + + className + + ", existing names are: " + + mViewManagerResolver.getViewManagerNames()); } throw new IllegalViewOperationException("No ViewManager found for class " + className); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK index 11bc3ba33e01ef..b876ba18bc5b23 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/annotations/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "annotations", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK index d8e9532b1a6a6f..6d46fd8953e9c2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/common/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "common", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -17,7 +18,6 @@ rn_android_library( "PUBLIC", ], deps = [ - # react_native_dep("third-party/android/androidx:appcompat"), react_native_dep("third-party/java/jsr-305:jsr-305"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/BlackHoleEventDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/BlackHoleEventDispatcher.java index 1fce7974087b6a..15abfde7a04268 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/BlackHoleEventDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/BlackHoleEventDispatcher.java @@ -49,6 +49,9 @@ public void removeBatchEventDispatchedListener(BatchEventDispatchedListener list @Override public void registerEventEmitter(int uiManagerType, RCTEventEmitter eventEmitter) {} + @Override + public void registerEventEmitter(int uiManagerType, RCTModernEventEmitter eventEmitter) {} + @Override public void unregisterEventEmitter(int uiManagerType) {} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ContentSizeChangeEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ContentSizeChangeEvent.java index a28bd72b12e683..d65c810b095f74 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ContentSizeChangeEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ContentSizeChangeEvent.java @@ -19,8 +19,13 @@ public class ContentSizeChangeEvent extends Event { private final int mWidth; private final int mHeight; + @Deprecated public ContentSizeChangeEvent(int viewTag, int width, int height) { - super(viewTag); + this(-1, viewTag, width, height); + } + + public ContentSizeChangeEvent(int surfaceId, int viewTag, int width, int height) { + super(surfaceId, viewTag); mWidth = width; mHeight = height; } @@ -31,10 +36,10 @@ public String getEventName() { } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { + protected WritableMap getEventData() { WritableMap data = Arguments.createMap(); data.putDouble("width", PixelUtil.toDIPFromPixel(mWidth)); data.putDouble("height", PixelUtil.toDIPFromPixel(mHeight)); - rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, data); + return data; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java index 7d36c049ed9df8..bd3b06b16e6de1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java @@ -7,32 +7,56 @@ package com.facebook.react.uimanager.events; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.SystemClock; +import com.facebook.react.uimanager.IllegalViewOperationException; /** * A UI event that can be dispatched to JS. * - *

For dispatching events {@link EventDispatcher#dispatchEvent} should be used. Once event object - * is passed to the EventDispatched it should no longer be used as EventDispatcher may decide to - * recycle that object (by calling {@link #dispose}). + *

For dispatching events {@code getEventData} should be used. Once event object is passed to the + * EventDispatched it should no longer be used as EventDispatcher may decide to recycle that object + * (by calling {@link #dispose}). + * + *

If you need advanced customizations and overriding only {@code getEventData} doesn't work for + * you, you must override both {@code dispatch} and {@code dispatchModern}. Both of these will be + * deleted in the distant future and it is highly recommended to use only {@code getEventData}. + * + *

Old, pre-Fabric Events only used viewTag as the identifier, but Fabric needs surfaceId as well + * as viewTag. You may use {@code UIManagerHelper.getSurfaceId} on a Fabric-managed View to get the + * surfaceId. Fabric will work without surfaceId - making {@code Event} backwards-compatible - but + * Events without SurfaceId are slightly slower to propagate. */ public abstract class Event { private static int sUniqueID = 0; private boolean mInitialized; + private int mSurfaceId; private int mViewTag; private long mTimestampMs; private int mUniqueID = sUniqueID++; protected Event() {} + @Deprecated protected Event(int viewTag) { init(viewTag); } - /** This method needs to be called before event is sent to event dispatcher. */ + protected Event(int surfaceId, int viewTag) { + init(surfaceId, viewTag); + } + + @Deprecated protected void init(int viewTag) { + init(-1, viewTag); + } + + /** This method needs to be called before event is sent to event dispatcher. */ + protected void init(int surfaceId, int viewTag) { + mSurfaceId = surfaceId; mViewTag = viewTag; mTimestampMs = SystemClock.uptimeMillis(); mInitialized = true; @@ -43,6 +67,11 @@ public final int getViewTag() { return mViewTag; } + /** @return the surfaceId for the view that generated this event */ + public final int getSurfaceId() { + return mSurfaceId; + } + /** * @return the time at which the event happened in the {@link android.os.SystemClock#uptimeMillis} * base. @@ -100,6 +129,47 @@ public void onDispose() {} /** @return the name of this event as registered in JS */ public abstract String getEventName(); - /** Dispatch this event to JS using the given event emitter. */ - public abstract void dispatch(RCTEventEmitter rctEventEmitter); + /** + * Dispatch this event to JS using the given event emitter. Compatible with old and new renderer. + * Instead of using this or dispatchModern, it is recommended that you simply override + * `getEventData`. In the future + */ + @Deprecated + public void dispatch(RCTEventEmitter rctEventEmitter) { + WritableMap eventData = getEventData(); + if (eventData == null) { + throw new IllegalViewOperationException( + "Event: you must return a valid, non-null value from `getEventData`, or override `dispatch` and `disatchModern`. Event: " + + getEventName()); + } + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); + } + + /** + * Can be overridden by classes to make migrating to RCTModernEventEmitter support easier. If this + * class returns null, the RCTEventEmitter interface will be used instead of + * RCTModernEventEmitter. In the future, returning null here will be an error. + */ + @Nullable + protected WritableMap getEventData() { + return null; + } + + /** + * Dispatch this event to JS using a V2 EventEmitter. If surfaceId is not -1 and `getEventData` is + * non-null, this will use the RCTModernEventEmitter API. Otherwise, it falls back to the + * old-style dispatch function. For Event classes that need to do something different, this method + * can always be overridden entirely, but it is not recommended. + */ + @Deprecated + public void dispatchModern(RCTModernEventEmitter rctEventEmitter) { + if (getSurfaceId() != -1) { + WritableMap eventData = getEventData(); + if (eventData != null) { + rctEventEmitter.receiveEvent(getSurfaceId(), getViewTag(), getEventName(), getEventData()); + return; + } + } + dispatch(rctEventEmitter); + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcher.java index 2ba18340977281..2e9ac90cc2c933 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcher.java @@ -26,8 +26,11 @@ public interface EventDispatcher { void removeBatchEventDispatchedListener(BatchEventDispatchedListener listener); + @Deprecated void registerEventEmitter(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter); + void registerEventEmitter(@UIManagerType int uiManagerType, RCTModernEventEmitter eventEmitter); + void unregisterEventEmitter(@UIManagerType int uiManagerType); void onCatalystInstanceDestroyed(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java index 9754b2de085471..a99d6b1eb31699 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; -import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -91,7 +90,8 @@ public int compare(Event lhs, Event rhs) { private final ArrayList mEventStaging = new ArrayList<>(); private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); - private final List mPostEventDispatchListeners = new ArrayList<>(); + private final CopyOnWriteArrayList mPostEventDispatchListeners = + new CopyOnWriteArrayList<>(); private final ScheduleDispatchFrameCallback mCurrentFrameCallback = new ScheduleDispatchFrameCallback(); private final AtomicInteger mHasDispatchScheduledCount = new AtomicInteger(); @@ -263,6 +263,11 @@ public void registerEventEmitter(@UIManagerType int uiManagerType, RCTEventEmitt mReactEventEmitter.register(uiManagerType, eventEmitter); } + public void registerEventEmitter( + @UIManagerType int uiManagerType, RCTModernEventEmitter eventEmitter) { + mReactEventEmitter.register(uiManagerType, eventEmitter); + } + public void unregisterEventEmitter(@UIManagerType int uiManagerType) { mReactEventEmitter.unregister(uiManagerType); } @@ -361,7 +366,7 @@ public void run() { } Systrace.endAsyncFlow( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, event.getEventName(), event.getUniqueID()); - event.dispatch(mReactEventEmitter); + event.dispatchModern(mReactEventEmitter); event.dispose(); } clearEventsToDispatch(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java index da06d7257d5453..7661d5c57fe76c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java @@ -13,8 +13,18 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +/** Deprecated in favor of RCTModernEventEmitter, which extends this interface. */ @DoNotStrip +@Deprecated public interface RCTEventEmitter extends JavaScriptModule { + /** + * Deprecated in favor of RCTModernEventEmitter.receiveEvent. + * + * @param targetTag + * @param eventName + * @param event + */ + @Deprecated void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event); void receiveTouches(String eventName, WritableArray touches, WritableArray changedIndices); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java new file mode 100644 index 00000000000000..a05f2c83b7d69f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager.events; + +import androidx.annotation.Nullable; +import com.facebook.react.bridge.WritableMap; + +/** + * This is a transitional replacement for RCTEventEmitter that works with Fabric and non-Fabric + * renderers. RCTEventEmitter works with Fabric as well, but there are negative perf implications + * and it should be avoided. + * + *

This interface will *also* be deleted in the distant future and be replaced with a new + * interface that doesn't need the old `receiveEvent` method at all. But for the foreseeable future, + * this is the recommended interface to use for EventEmitters. + */ +public interface RCTModernEventEmitter extends RCTEventEmitter { + void receiveEvent(int surfaceId, int targetTag, String eventName, @Nullable WritableMap event); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java index 28931ad83cc2ea..49b05347a2040c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java @@ -9,9 +9,7 @@ import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_KEY; -import android.util.SparseArray; import androidx.annotation.Nullable; -import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactNoCrashSoftException; @@ -21,11 +19,16 @@ import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.ViewUtil; -public class ReactEventEmitter implements RCTEventEmitter { +public class ReactEventEmitter implements RCTModernEventEmitter { private static final String TAG = "ReactEventEmitter"; - private final SparseArray mEventEmitters = new SparseArray<>(); + @Nullable + private RCTModernEventEmitter mFabricEventEmitter = + null; /* Corresponds to a Fabric EventEmitter */ + + @Nullable + private RCTEventEmitter mRCTEventEmitter = null; /* Corresponds to a Non-Fabric EventEmitter */ private final ReactApplicationContext mReactContext; @@ -33,46 +36,61 @@ public ReactEventEmitter(ReactApplicationContext reactContext) { mReactContext = reactContext; } + public void register(@UIManagerType int uiManagerType, RCTModernEventEmitter eventEmitter) { + assert uiManagerType == UIManagerType.FABRIC; + mFabricEventEmitter = eventEmitter; + } + public void register(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter) { - mEventEmitters.put(uiManagerType, eventEmitter); + assert uiManagerType == UIManagerType.DEFAULT; + mRCTEventEmitter = eventEmitter; } public void unregister(@UIManagerType int uiManagerType) { - mEventEmitters.remove(uiManagerType); + if (uiManagerType == UIManagerType.DEFAULT) { + mRCTEventEmitter = null; + } else { + mFabricEventEmitter = null; + } } @Override public void receiveEvent(int targetReactTag, String eventName, @Nullable WritableMap event) { - RCTEventEmitter eventEmitter = getEventEmitter(targetReactTag); - if (eventEmitter != null) { - eventEmitter.receiveEvent(targetReactTag, eventName, event); - } + receiveEvent(-1, targetReactTag, eventName, event); } @Override public void receiveTouches( String eventName, WritableArray touches, WritableArray changedIndices) { - Assertions.assertCondition(touches.size() > 0); int reactTag = touches.getMap(0).getInt(TARGET_KEY); - RCTEventEmitter eventEmitter = getEventEmitter(reactTag); - if (eventEmitter != null) { - eventEmitter.receiveTouches(eventName, touches, changedIndices); + @UIManagerType int uiManagerType = ViewUtil.getUIManagerType(reactTag); + if (uiManagerType == UIManagerType.FABRIC && mFabricEventEmitter != null) { + mFabricEventEmitter.receiveTouches(eventName, touches, changedIndices); + } else if (uiManagerType == UIManagerType.DEFAULT && getEventEmitter(reactTag) != null) { + mRCTEventEmitter.receiveTouches(eventName, touches, changedIndices); + } else { + ReactSoftException.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Cannot find EventEmitter for receivedTouches: ReactTag[" + + reactTag + + "] UIManagerType[" + + uiManagerType + + "] EventName[" + + eventName + + "]")); } } @Nullable private RCTEventEmitter getEventEmitter(int reactTag) { int type = ViewUtil.getUIManagerType(reactTag); - RCTEventEmitter eventEmitter = mEventEmitters.get(type); - if (eventEmitter == null) { - // TODO T54145494: Refactor RN Event Emitter system to make sure reactTags are always managed - // by RN - FLog.e( - TAG, "Unable to find event emitter for reactTag: %d - uiManagerType: %d", reactTag, type); + assert type == UIManagerType.DEFAULT; + if (mRCTEventEmitter == null) { if (mReactContext.hasActiveCatalystInstance()) { - eventEmitter = mReactContext.getJSModule(RCTEventEmitter.class); + mRCTEventEmitter = mReactContext.getJSModule(RCTEventEmitter.class); } else { ReactSoftException.logSoftException( TAG, @@ -84,6 +102,30 @@ private RCTEventEmitter getEventEmitter(int reactTag) { + " - No active Catalyst instance!")); } } - return eventEmitter; + return mRCTEventEmitter; + } + + @Override + public void receiveEvent( + int surfaceId, int targetReactTag, String eventName, @Nullable WritableMap event) { + @UIManagerType int uiManagerType = ViewUtil.getUIManagerType(targetReactTag); + if (uiManagerType == UIManagerType.FABRIC && mFabricEventEmitter != null) { + mFabricEventEmitter.receiveEvent(surfaceId, targetReactTag, eventName, event); + } else if (uiManagerType == UIManagerType.DEFAULT && getEventEmitter(targetReactTag) != null) { + mRCTEventEmitter.receiveEvent(targetReactTag, eventName, event); + } else { + ReactSoftException.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Cannot find EventEmitter for receiveEvent: SurfaceId[" + + surfaceId + + "] ReactTag[" + + targetReactTag + + "] UIManagerType[" + + uiManagerType + + "] EventName[" + + eventName + + "]")); + } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java index 1445735f6f57f5..fbcb97b1cc3b56 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java @@ -30,6 +30,7 @@ public class TouchEvent extends Event { public static final long UNSET = Long.MIN_VALUE; + @Deprecated public static TouchEvent obtain( int viewTag, TouchEventType touchEventType, @@ -38,11 +39,32 @@ public static TouchEvent obtain( float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { + return obtain( + -1, + viewTag, + touchEventType, + motionEventToCopy, + gestureStartTime, + viewX, + viewY, + touchEventCoalescingKeyHelper); + } + + public static TouchEvent obtain( + int surfaceId, + int viewTag, + TouchEventType touchEventType, + MotionEvent motionEventToCopy, + long gestureStartTime, + float viewX, + float viewY, + TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { TouchEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new TouchEvent(); } event.init( + surfaceId, viewTag, touchEventType, motionEventToCopy, @@ -64,6 +86,7 @@ public static TouchEvent obtain( private TouchEvent() {} private void init( + int surfaceId, int viewTag, TouchEventType touchEventType, MotionEvent motionEventToCopy, @@ -71,7 +94,7 @@ private void init( float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { - super.init(viewTag); + super.init(surfaceId, viewTag); SoftAssertions.assertCondition( gestureStartTime != UNSET, "Gesture start time must be initialized"); @@ -141,7 +164,16 @@ public short getCoalescingKey() { @Override public void dispatch(RCTEventEmitter rctEventEmitter) { TouchesHelper.sendTouchEvent( - rctEventEmitter, Assertions.assertNotNull(mTouchEventType), getViewTag(), this); + rctEventEmitter, + Assertions.assertNotNull(mTouchEventType), + getSurfaceId(), + getViewTag(), + this); + } + + @Override + public void dispatchModern(RCTModernEventEmitter rctEventEmitter) { + dispatch(rctEventEmitter); } public MotionEvent getMotionEvent() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java index 0c222ad95022ca..187e61211604c2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java @@ -16,6 +16,7 @@ /** Class responsible for generating catalyst touch events based on android {@link MotionEvent}. */ public class TouchesHelper { + public static final String TARGET_SURFACE_KEY = "targetSurface"; public static final String TARGET_KEY = "target"; public static final String CHANGED_TOUCHES_KEY = "changedTouches"; public static final String TOUCHES_KEY = "touches"; @@ -34,7 +35,8 @@ public class TouchesHelper { * given {@param event} instance. This method use {@param reactTarget} parameter to set as a * target view id associated with current gesture. */ - private static WritableArray createsPointersArray(int reactTarget, TouchEvent event) { + private static WritableArray createsPointersArray( + int surfaceId, int reactTarget, TouchEvent event) { WritableArray touches = Arguments.createArray(); MotionEvent motionEvent = event.getMotionEvent(); @@ -60,6 +62,7 @@ private static WritableArray createsPointersArray(int reactTarget, TouchEvent ev float locationY = motionEvent.getY(index) - targetViewCoordinateY; touch.putDouble(LOCATION_X_KEY, PixelUtil.toDIPFromPixel(locationX)); touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(locationY)); + touch.putInt(TARGET_SURFACE_KEY, surfaceId); touch.putInt(TARGET_KEY, reactTarget); touch.putDouble(TIMESTAMP_KEY, event.getTimestampMs()); touch.putDouble(POINTER_IDENTIFIER_KEY, motionEvent.getPointerId(index)); @@ -81,10 +84,10 @@ private static WritableArray createsPointersArray(int reactTarget, TouchEvent ev public static void sendTouchEvent( RCTEventEmitter rctEventEmitter, TouchEventType type, + int surfaceId, int reactTarget, TouchEvent touchEvent) { - - WritableArray pointers = createsPointersArray(reactTarget, touchEvent); + WritableArray pointers = createsPointersArray(surfaceId, reactTarget, touchEvent); MotionEvent motionEvent = touchEvent.getMotionEvent(); // For START and END events send only index of the pointer that is associated with that event diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BUCK new file mode 100644 index 00000000000000..8922b82d73d756 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BUCK @@ -0,0 +1,21 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") + +rn_android_library( + name = "interfaces", + srcs = glob(["*.java"]), + autoglob = False, + is_androidx = True, + labels = ["supermodule:xplat/default/public.react_native.infra"], + provided_deps = [ + react_native_dep("third-party/android/androidx:annotation"), + ], + required_for_source_only_abi = True, + visibility = [ + "PUBLIC", + ], + deps = [ + YOGA_TARGET, + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_target("java/com/facebook/react/bridge:bridge"), + ], +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/FloatUtil.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/FloatUtil.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/FloatUtil.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/FloatUtil.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/Spacing.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/Spacing.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewManagerDelegate.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerDelegate.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewManagerDelegate.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java similarity index 100% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java rename to ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK index 6d31563ef3a53f..c8173be0b382a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/util/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "util", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/util/BUCK b/ReactAndroid/src/main/java/com/facebook/react/util/BUCK index 679245155e108d..67fc95476d5954 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/util/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/util/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "util", srcs = glob(["**/*.java"]), + autoglob = False, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerDelegate.java deleted file mode 100644 index 833ffe265d96f7..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerDelegate.java +++ /dev/null @@ -1,42 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class ActivityIndicatorViewManagerDelegate & ActivityIndicatorViewManagerInterface> extends BaseViewManagerDelegate { - public ActivityIndicatorViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "hidesWhenStopped": - mViewManager.setHidesWhenStopped(view, value == null ? false : (boolean) value); - break; - case "animating": - mViewManager.setAnimating(view, value == null ? false : (boolean) value); - break; - case "color": - mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "size": - mViewManager.setSize(view, (String) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerInterface.java deleted file mode 100644 index d217b8bc2fdfbe..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerInterface.java +++ /dev/null @@ -1,20 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface ActivityIndicatorViewManagerInterface { - void setHidesWhenStopped(T view, boolean value); - void setAnimating(T view, boolean value); - void setColor(T view, @Nullable Integer value); - void setSize(T view, @Nullable String value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerDelegate.java deleted file mode 100644 index aee5f3f9c94820..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerDelegate.java +++ /dev/null @@ -1,61 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class AndroidDrawerLayoutManagerDelegate & AndroidDrawerLayoutManagerInterface> extends BaseViewManagerDelegate { - public AndroidDrawerLayoutManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "keyboardDismissMode": - mViewManager.setKeyboardDismissMode(view, (String) value); - break; - case "drawerBackgroundColor": - mViewManager.setDrawerBackgroundColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "drawerPosition": - mViewManager.setDrawerPosition(view, (String) value); - break; - case "drawerWidth": - mViewManager.setDrawerWidth(view, value == null ? null : ((Double) value).floatValue()); - break; - case "drawerLockMode": - mViewManager.setDrawerLockMode(view, (String) value); - break; - case "statusBarBackgroundColor": - mViewManager.setStatusBarBackgroundColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - default: - super.setProperty(view, propName, value); - } - } - - @Override - public void receiveCommand(T view, String commandName, ReadableArray args) { - switch (commandName) { - case "openDrawer": - mViewManager.openDrawer(view); - break; - case "closeDrawer": - mViewManager.closeDrawer(view); - break; - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerInterface.java deleted file mode 100644 index 7654b2d79297a5..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerInterface.java +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface AndroidDrawerLayoutManagerInterface { - void setKeyboardDismissMode(T view, @Nullable String value); - void setDrawerBackgroundColor(T view, @Nullable Integer value); - void setDrawerPosition(T view, @Nullable String value); - void setDrawerWidth(T view, @Nullable Float value); - void setDrawerLockMode(T view, @Nullable String value); - void setStatusBarBackgroundColor(T view, @Nullable Integer value); - void openDrawer(T view); - void closeDrawer(T view); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerDelegate.java index 33d27bb5f28afe..c14ce248b59faf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerDelegate.java @@ -1,12 +1,11 @@ /** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - + * Copyright (c) Facebook, Inc. and its affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + * + * @generated by codegen project: GeneratePropsJavaDelegate.js + */ package com.facebook.react.viewmanagers; import android.view.View; @@ -16,10 +15,14 @@ import com.facebook.react.uimanager.BaseViewManagerInterface; import com.facebook.react.uimanager.LayoutShadowNode; -public class AndroidDropdownPickerManagerDelegate & AndroidDropdownPickerManagerInterface> extends BaseViewManagerDelegate { +public class AndroidDropdownPickerManagerDelegate< + T extends View, + U extends BaseViewManagerInterface & AndroidDropdownPickerManagerInterface> + extends BaseViewManagerDelegate { public AndroidDropdownPickerManagerDelegate(U viewManager) { super(viewManager); } + @Override public void setProperty(T view, String propName, @Nullable Object value) { switch (propName) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerDelegate.java deleted file mode 100644 index b0417eed9ce042..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerDelegate.java +++ /dev/null @@ -1,51 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class AndroidProgressBarManagerDelegate & AndroidProgressBarManagerInterface> extends BaseViewManagerDelegate { - public AndroidProgressBarManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "styleAttr": - mViewManager.setStyleAttr(view, value == null ? null : (String) value); - break; - case "typeAttr": - mViewManager.setTypeAttr(view, value == null ? null : (String) value); - break; - case "indeterminate": - mViewManager.setIndeterminate(view, value == null ? false : (boolean) value); - break; - case "progress": - mViewManager.setProgress(view, value == null ? 0f : ((Double) value).doubleValue()); - break; - case "animating": - mViewManager.setAnimating(view, value == null ? true : (boolean) value); - break; - case "color": - mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "testID": - mViewManager.setTestID(view, value == null ? "" : (String) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerInterface.java deleted file mode 100644 index 814d8e7f7e14c9..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerInterface.java +++ /dev/null @@ -1,23 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface AndroidProgressBarManagerInterface { - void setStyleAttr(T view, @Nullable String value); - void setTypeAttr(T view, @Nullable String value); - void setIndeterminate(T view, boolean value); - void setProgress(T view, double value); - void setAnimating(T view, boolean value); - void setColor(T view, @Nullable Integer value); - void setTestID(T view, @Nullable String value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerDelegate.java deleted file mode 100644 index e5fc3ac7a2c2c2..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerDelegate.java +++ /dev/null @@ -1,58 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class AndroidSwipeRefreshLayoutManagerDelegate & AndroidSwipeRefreshLayoutManagerInterface> extends BaseViewManagerDelegate { - public AndroidSwipeRefreshLayoutManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "enabled": - mViewManager.setEnabled(view, value == null ? true : (boolean) value); - break; - case "colors": - mViewManager.setColors(view, (ReadableArray) value); - break; - case "progressBackgroundColor": - mViewManager.setProgressBackgroundColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "size": - mViewManager.setSize(view, value == null ? 1 : ((Double) value).intValue()); - break; - case "progressViewOffset": - mViewManager.setProgressViewOffset(view, value == null ? 0f : ((Double) value).floatValue()); - break; - case "refreshing": - mViewManager.setRefreshing(view, value == null ? false : (boolean) value); - break; - default: - super.setProperty(view, propName, value); - } - } - - @Override - public void receiveCommand(T view, String commandName, ReadableArray args) { - switch (commandName) { - case "setNativeRefreshing": - mViewManager.setNativeRefreshing(view, args.getBoolean(0)); - break; - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerInterface.java deleted file mode 100644 index 3e81326b3e8ee0..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerInterface.java +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; - -public interface AndroidSwipeRefreshLayoutManagerInterface { - void setEnabled(T view, boolean value); - void setColors(T view, @Nullable ReadableArray value); - void setProgressBackgroundColor(T view, @Nullable Integer value); - void setSize(T view, int value); - void setProgressViewOffset(T view, float value); - void setRefreshing(T view, boolean value); - void setNativeRefreshing(T view, boolean value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerDelegate.java deleted file mode 100644 index 1b2f225d390ae7..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerDelegate.java +++ /dev/null @@ -1,67 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class AndroidSwitchManagerDelegate & AndroidSwitchManagerInterface> extends BaseViewManagerDelegate { - public AndroidSwitchManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "disabled": - mViewManager.setDisabled(view, value == null ? false : (boolean) value); - break; - case "enabled": - mViewManager.setEnabled(view, value == null ? true : (boolean) value); - break; - case "thumbColor": - mViewManager.setThumbColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "trackColorForFalse": - mViewManager.setTrackColorForFalse(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "trackColorForTrue": - mViewManager.setTrackColorForTrue(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "value": - mViewManager.setValue(view, value == null ? false : (boolean) value); - break; - case "on": - mViewManager.setOn(view, value == null ? false : (boolean) value); - break; - case "thumbTintColor": - mViewManager.setThumbTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "trackTintColor": - mViewManager.setTrackTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - default: - super.setProperty(view, propName, value); - } - } - - @Override - public void receiveCommand(T view, String commandName, ReadableArray args) { - switch (commandName) { - case "setNativeValue": - mViewManager.setNativeValue(view, args.getBoolean(0)); - break; - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerInterface.java deleted file mode 100644 index 2ff293b3be663a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerInterface.java +++ /dev/null @@ -1,26 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface AndroidSwitchManagerInterface { - void setDisabled(T view, boolean value); - void setEnabled(T view, boolean value); - void setThumbColor(T view, @Nullable Integer value); - void setTrackColorForFalse(T view, @Nullable Integer value); - void setTrackColorForTrue(T view, @Nullable Integer value); - void setValue(T view, boolean value); - void setOn(T view, boolean value); - void setThumbTintColor(T view, @Nullable Integer value); - void setTrackTintColor(T view, @Nullable Integer value); - void setNativeValue(T view, boolean value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK index 039099fb0d634a..33af2c1e53c0b5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "viewmanagers", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerDelegate.java deleted file mode 100644 index 315e5cd181aebb..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerDelegate.java +++ /dev/null @@ -1,26 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class MaskedViewManagerDelegate & MaskedViewManagerInterface> extends BaseViewManagerDelegate { - public MaskedViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - super.setProperty(view, propName, value); - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerInterface.java deleted file mode 100644 index 0b930ee79c1be0..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; - -public interface MaskedViewManagerInterface { - // No props -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerDelegate.java deleted file mode 100644 index 978224f30f73d5..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerDelegate.java +++ /dev/null @@ -1,54 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class ModalHostViewManagerDelegate & ModalHostViewManagerInterface> extends BaseViewManagerDelegate { - public ModalHostViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "animationType": - mViewManager.setAnimationType(view, (String) value); - break; - case "presentationStyle": - mViewManager.setPresentationStyle(view, (String) value); - break; - case "transparent": - mViewManager.setTransparent(view, value == null ? false : (boolean) value); - break; - case "statusBarTranslucent": - mViewManager.setStatusBarTranslucent(view, value == null ? false : (boolean) value); - break; - case "hardwareAccelerated": - mViewManager.setHardwareAccelerated(view, value == null ? false : (boolean) value); - break; - case "animated": - mViewManager.setAnimated(view, value == null ? false : (boolean) value); - break; - case "supportedOrientations": - mViewManager.setSupportedOrientations(view, (ReadableArray) value); - break; - case "identifier": - mViewManager.setIdentifier(view, value == null ? 0 : ((Double) value).intValue()); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerInterface.java deleted file mode 100644 index bf60387d5180c8..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerInterface.java +++ /dev/null @@ -1,25 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; - -public interface ModalHostViewManagerInterface { - void setAnimationType(T view, @Nullable String value); - void setPresentationStyle(T view, @Nullable String value); - void setTransparent(T view, boolean value); - void setStatusBarTranslucent(T view, boolean value); - void setHardwareAccelerated(T view, boolean value); - void setAnimated(T view, boolean value); - void setSupportedOrientations(T view, @Nullable ReadableArray value); - void setIdentifier(T view, int value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerDelegate.java deleted file mode 100644 index df088d4a87f8ba..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerDelegate.java +++ /dev/null @@ -1,49 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class ProgressViewManagerDelegate & ProgressViewManagerInterface> extends BaseViewManagerDelegate { - public ProgressViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "progressViewStyle": - mViewManager.setProgressViewStyle(view, (String) value); - break; - case "progress": - mViewManager.setProgress(view, value == null ? 0f : ((Double) value).floatValue()); - break; - case "progressTintColor": - mViewManager.setProgressTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "trackTintColor": - mViewManager.setTrackTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "progressImage": - mViewManager.setProgressImage(view, (ReadableMap) value); - break; - case "trackImage": - mViewManager.setTrackImage(view, (ReadableMap) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerInterface.java deleted file mode 100644 index bbfbdf4e31bb02..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerInterface.java +++ /dev/null @@ -1,23 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableMap; - -public interface ProgressViewManagerInterface { - void setProgressViewStyle(T view, @Nullable String value); - void setProgress(T view, float value); - void setProgressTintColor(T view, @Nullable Integer value); - void setTrackTintColor(T view, @Nullable Integer value); - void setProgressImage(T view, @Nullable ReadableMap value); - void setTrackImage(T view, @Nullable ReadableMap value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerDelegate.java deleted file mode 100644 index fdf56b283822cb..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerDelegate.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class SafeAreaViewManagerDelegate & SafeAreaViewManagerInterface> extends BaseViewManagerDelegate { - public SafeAreaViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "emulateUnlessSupported": - mViewManager.setEmulateUnlessSupported(view, value == null ? false : (boolean) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerInterface.java deleted file mode 100644 index 073e2c01c76826..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; - -public interface SafeAreaViewManagerInterface { - void setEmulateUnlessSupported(T view, boolean value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerDelegate.java deleted file mode 100644 index 6763a1f1f53f0b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerDelegate.java +++ /dev/null @@ -1,52 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class SegmentedControlManagerDelegate & SegmentedControlManagerInterface> extends BaseViewManagerDelegate { - public SegmentedControlManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "values": - mViewManager.setValues(view, (ReadableArray) value); - break; - case "selectedIndex": - mViewManager.setSelectedIndex(view, value == null ? 0 : ((Double) value).intValue()); - break; - case "enabled": - mViewManager.setEnabled(view, value == null ? true : (boolean) value); - break; - case "tintColor": - mViewManager.setTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "textColor": - mViewManager.setTextColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "backgroundColor": - mViewManager.setBackgroundColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "momentary": - mViewManager.setMomentary(view, value == null ? false : (boolean) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerInterface.java deleted file mode 100644 index 0ee9d56850941d..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerInterface.java +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableArray; - -public interface SegmentedControlManagerInterface { - void setValues(T view, @Nullable ReadableArray value); - void setSelectedIndex(T view, int value); - void setEnabled(T view, boolean value); - void setTintColor(T view, @Nullable Integer value); - void setTextColor(T view, @Nullable Integer value); - void setBackgroundColor(T view, @Nullable Integer value); - void setMomentary(T view, boolean value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerDelegate.java deleted file mode 100644 index 5eb9360ef8e285..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerDelegate.java +++ /dev/null @@ -1,73 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ColorPropConverter; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class SliderManagerDelegate & SliderManagerInterface> extends BaseViewManagerDelegate { - public SliderManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "disabled": - mViewManager.setDisabled(view, value == null ? false : (boolean) value); - break; - case "enabled": - mViewManager.setEnabled(view, value == null ? true : (boolean) value); - break; - case "maximumTrackImage": - mViewManager.setMaximumTrackImage(view, (ReadableMap) value); - break; - case "maximumTrackTintColor": - mViewManager.setMaximumTrackTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "maximumValue": - mViewManager.setMaximumValue(view, value == null ? 1f : ((Double) value).doubleValue()); - break; - case "minimumTrackImage": - mViewManager.setMinimumTrackImage(view, (ReadableMap) value); - break; - case "minimumTrackTintColor": - mViewManager.setMinimumTrackTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "minimumValue": - mViewManager.setMinimumValue(view, value == null ? 0f : ((Double) value).doubleValue()); - break; - case "step": - mViewManager.setStep(view, value == null ? 0f : ((Double) value).doubleValue()); - break; - case "testID": - mViewManager.setTestID(view, value == null ? "" : (String) value); - break; - case "thumbImage": - mViewManager.setThumbImage(view, (ReadableMap) value); - break; - case "thumbTintColor": - mViewManager.setThumbTintColor(view, ColorPropConverter.getColor(value, view.getContext())); - break; - case "trackImage": - mViewManager.setTrackImage(view, (ReadableMap) value); - break; - case "value": - mViewManager.setValue(view, value == null ? 0f : ((Double) value).doubleValue()); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerInterface.java deleted file mode 100644 index 2d5c752f62cbba..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerInterface.java +++ /dev/null @@ -1,31 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableMap; - -public interface SliderManagerInterface { - void setDisabled(T view, boolean value); - void setEnabled(T view, boolean value); - void setMaximumTrackImage(T view, @Nullable ReadableMap value); - void setMaximumTrackTintColor(T view, @Nullable Integer value); - void setMaximumValue(T view, double value); - void setMinimumTrackImage(T view, @Nullable ReadableMap value); - void setMinimumTrackTintColor(T view, @Nullable Integer value); - void setMinimumValue(T view, double value); - void setStep(T view, double value); - void setTestID(T view, @Nullable String value); - void setThumbImage(T view, @Nullable ReadableMap value); - void setThumbTintColor(T view, @Nullable Integer value); - void setTrackImage(T view, @Nullable ReadableMap value); - void setValue(T view, double value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerDelegate.java deleted file mode 100644 index f90b2c3b25fa11..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerDelegate.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaDelegate.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; -import com.facebook.react.uimanager.BaseViewManagerDelegate; -import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; - -public class UnimplementedNativeViewManagerDelegate & UnimplementedNativeViewManagerInterface> extends BaseViewManagerDelegate { - public UnimplementedNativeViewManagerDelegate(U viewManager) { - super(viewManager); - } - @Override - public void setProperty(T view, String propName, @Nullable Object value) { - switch (propName) { - case "name": - mViewManager.setName(view, value == null ? "" : (String) value); - break; - default: - super.setProperty(view, propName, value); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerInterface.java deleted file mode 100644 index c76951e2225c1a..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerInterface.java +++ /dev/null @@ -1,17 +0,0 @@ -/** -* Copyright (c) Facebook, Inc. and its affiliates. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface UnimplementedNativeViewManagerInterface { - void setName(T view, @Nullable String value); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/Android.mk b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/Android.mk deleted file mode 100644 index cc37b42fdbe2e2..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := react_render_viewmanagers - -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp $(LOCAL_PATH)/react/renderer/components/rncore/*.cpp) - -LOCAL_SHARED_LIBRARIES := libreact_render_components_view libfolly_json libreact_render_core libreact_render_graphics - -LOCAL_STATIC_LIBRARIES := - -LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/rncore/ - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) - -LOCAL_CFLAGS := \ - -DLOG_TAG=\"Fabric\" - -LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall - -include $(BUILD_SHARED_LIBRARY) - -$(call import-module,react/renderer/components/view) diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ComponentDescriptors.h b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ComponentDescriptors.h deleted file mode 100644 index cc3c195dd3a24f..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ComponentDescriptors.h +++ /dev/null @@ -1,31 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateComponentDescriptorH.js - */ - -#pragma once - -#include -#include - -namespace facebook { -namespace react { - -using ActivityIndicatorViewComponentDescriptor = ConcreteComponentDescriptor; -using DatePickerComponentDescriptor = ConcreteComponentDescriptor; -using AndroidDrawerLayoutComponentDescriptor = ConcreteComponentDescriptor; -using RCTMaskedViewComponentDescriptor = ConcreteComponentDescriptor; -using RCTProgressViewComponentDescriptor = ConcreteComponentDescriptor; -using AndroidSwipeRefreshLayoutComponentDescriptor = ConcreteComponentDescriptor; -using PullToRefreshViewComponentDescriptor = ConcreteComponentDescriptor; -using RCTSegmentedControlComponentDescriptor = ConcreteComponentDescriptor; -using SwitchComponentDescriptor = ConcreteComponentDescriptor; -using UnimplementedNativeViewComponentDescriptor = ConcreteComponentDescriptor; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.cpp b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.cpp deleted file mode 100644 index 68ba41cdd1c633..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.cpp +++ /dev/null @@ -1,141 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateEventEmitterCpp.js - */ - -#include - -namespace facebook { -namespace react { - - -void DatePickerEventEmitter::onChange(OnChange event) const { - dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "timestamp", event.timestamp); - return payload; - }); -} -void AndroidDrawerLayoutEventEmitter::onDrawerSlide(OnDrawerSlide event) const { - dispatchEvent("drawerSlide", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "offset", event.offset); - return payload; - }); -} -void AndroidDrawerLayoutEventEmitter::onDrawerStateChanged(OnDrawerStateChanged event) const { - dispatchEvent("drawerStateChanged", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "drawerState", event.drawerState); - return payload; - }); -} -void AndroidDrawerLayoutEventEmitter::onDrawerOpen(OnDrawerOpen event) const { - dispatchEvent("drawerOpen", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} -void AndroidDrawerLayoutEventEmitter::onDrawerClose(OnDrawerClose event) const { - dispatchEvent("drawerClose", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} - - - -void AndroidSwipeRefreshLayoutEventEmitter::onRefresh(OnRefresh event) const { - dispatchEvent("refresh", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} -void PullToRefreshViewEventEmitter::onRefresh(OnRefresh event) const { - dispatchEvent("refresh", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} - -void RCTSegmentedControlEventEmitter::onChange(OnChange event) const { - dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); -payload.setProperty(runtime, "selectedSegmentIndex", event.selectedSegmentIndex); - return payload; - }); -} -void SliderEventEmitter::onChange(OnChange event) const { - dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); -payload.setProperty(runtime, "fromUser", event.fromUser); - return payload; - }); -} -void SliderEventEmitter::onValueChange(OnValueChange event) const { - dispatchEvent("valueChange", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); -payload.setProperty(runtime, "fromUser", event.fromUser); - return payload; - }); -} -void SliderEventEmitter::onSlidingComplete(OnSlidingComplete event) const { - dispatchEvent("slidingComplete", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); -payload.setProperty(runtime, "fromUser", event.fromUser); - return payload; - }); -} -void AndroidSwitchEventEmitter::onChange(OnChange event) const { - dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); - return payload; - }); -} -void SwitchEventEmitter::onChange(OnChange event) const { - dispatchEvent("change", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "value", event.value); - return payload; - }); -} - - -void ModalHostViewEventEmitter::onRequestClose(OnRequestClose event) const { - dispatchEvent("requestClose", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} -void ModalHostViewEventEmitter::onShow(OnShow event) const { - dispatchEvent("show", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - - return payload; - }); -} -void ModalHostViewEventEmitter::onOrientationChange(OnOrientationChange event) const { - dispatchEvent("orientationChange", [event=std::move(event)](jsi::Runtime &runtime) { - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "orientation", toString(event.orientation)); - return payload; - }); -} - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.h b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.h deleted file mode 100644 index 412c956aad8770..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.h +++ /dev/null @@ -1,223 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateEventEmitterH.js - */ -#pragma once - -#include - -namespace facebook { -namespace react { - -class ActivityIndicatorViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class DatePickerEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnChange { - Float timestamp; - }; - - void onChange(OnChange value) const; -}; -class AndroidDrawerLayoutEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnDrawerSlide { - Float offset; - }; - - struct OnDrawerStateChanged { - int drawerState; - }; - - struct OnDrawerOpen { - - }; - - struct OnDrawerClose { - - }; - - void onDrawerSlide(OnDrawerSlide value) const; - - void onDrawerStateChanged(OnDrawerStateChanged value) const; - - void onDrawerOpen(OnDrawerOpen value) const; - - void onDrawerClose(OnDrawerClose value) const; -}; -class RCTMaskedViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class AndroidProgressBarEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class RCTProgressViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class AndroidSwipeRefreshLayoutEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnRefresh { - - }; - - void onRefresh(OnRefresh value) const; -}; -class PullToRefreshViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnRefresh { - - }; - - void onRefresh(OnRefresh value) const; -}; -class SafeAreaViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class RCTSegmentedControlEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnChange { - int value; - int selectedSegmentIndex; - }; - - void onChange(OnChange value) const; -}; -class SliderEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnChange { - double value; - bool fromUser; - }; - - struct OnValueChange { - double value; - bool fromUser; - }; - - struct OnSlidingComplete { - double value; - bool fromUser; - }; - - void onChange(OnChange value) const; - - void onValueChange(OnValueChange value) const; - - void onSlidingComplete(OnSlidingComplete value) const; -}; -class AndroidSwitchEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnChange { - bool value; - }; - - void onChange(OnChange value) const; -}; -class SwitchEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnChange { - bool value; - }; - - void onChange(OnChange value) const; -}; -class InputAccessoryEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class UnimplementedNativeViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - - - -}; -class ModalHostViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - - struct OnRequestClose { - - }; - - struct OnShow { - - }; - - enum class OnOrientationChangeOrientation { - Portrait, - Landscape - }; - - static char const *toString(const OnOrientationChangeOrientation value) { - switch (value) { - case OnOrientationChangeOrientation::Portrait: return "portrait"; - case OnOrientationChangeOrientation::Landscape: return "landscape"; - } - } - - struct OnOrientationChange { - OnOrientationChangeOrientation orientation; - }; - - void onRequestClose(OnRequestClose value) const; - - void onShow(OnShow value) const; - - void onOrientationChange(OnOrientationChange value) const; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.cpp b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.cpp deleted file mode 100644 index fcce261612f836..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.cpp +++ /dev/null @@ -1,191 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GeneratePropsCpp.js - */ - -#include -#include -#include - -namespace facebook { -namespace react { - -ActivityIndicatorViewProps::ActivityIndicatorViewProps( - const ActivityIndicatorViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - hidesWhenStopped(convertRawProp(rawProps, "hidesWhenStopped", sourceProps.hidesWhenStopped, {false})), - animating(convertRawProp(rawProps, "animating", sourceProps.animating, {false})), - color(convertRawProp(rawProps, "color", sourceProps.color, {})), - size(convertRawProp(rawProps, "size", sourceProps.size, {ActivityIndicatorViewSize::Small})) - {} -DatePickerProps::DatePickerProps( - const DatePickerProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - date(convertRawProp(rawProps, "date", sourceProps.date, {0.0})), - initialDate(convertRawProp(rawProps, "initialDate", sourceProps.initialDate, {0.0})), - locale(convertRawProp(rawProps, "locale", sourceProps.locale, {})), - maximumDate(convertRawProp(rawProps, "maximumDate", sourceProps.maximumDate, {0.0})), - minimumDate(convertRawProp(rawProps, "minimumDate", sourceProps.minimumDate, {0.0})), - minuteInterval(convertRawProp(rawProps, "minuteInterval", sourceProps.minuteInterval, {DatePickerMinuteInterval::MinuteInterval1})), - mode(convertRawProp(rawProps, "mode", sourceProps.mode, {DatePickerMode::Date})), - timeZoneOffsetInMinutes(convertRawProp(rawProps, "timeZoneOffsetInMinutes", sourceProps.timeZoneOffsetInMinutes, {0.0})) - {} -AndroidDrawerLayoutProps::AndroidDrawerLayoutProps( - const AndroidDrawerLayoutProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - keyboardDismissMode(convertRawProp(rawProps, "keyboardDismissMode", sourceProps.keyboardDismissMode, {AndroidDrawerLayoutKeyboardDismissMode::None})), - drawerBackgroundColor(convertRawProp(rawProps, "drawerBackgroundColor", sourceProps.drawerBackgroundColor, {})), - drawerPosition(convertRawProp(rawProps, "drawerPosition", sourceProps.drawerPosition, {AndroidDrawerLayoutDrawerPosition::Left})), - drawerWidth(convertRawProp(rawProps, "drawerWidth", sourceProps.drawerWidth, {})), - drawerLockMode(convertRawProp(rawProps, "drawerLockMode", sourceProps.drawerLockMode, {AndroidDrawerLayoutDrawerLockMode::Unlocked})), - statusBarBackgroundColor(convertRawProp(rawProps, "statusBarBackgroundColor", sourceProps.statusBarBackgroundColor, {})) - {} -RCTMaskedViewProps::RCTMaskedViewProps( - const RCTMaskedViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps) - - - {} -AndroidProgressBarProps::AndroidProgressBarProps( - const AndroidProgressBarProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - styleAttr(convertRawProp(rawProps, "styleAttr", sourceProps.styleAttr, {})), - typeAttr(convertRawProp(rawProps, "typeAttr", sourceProps.typeAttr, {})), - indeterminate(convertRawProp(rawProps, "indeterminate", sourceProps.indeterminate, {false})), - progress(convertRawProp(rawProps, "progress", sourceProps.progress, {0.0})), - animating(convertRawProp(rawProps, "animating", sourceProps.animating, {true})), - color(convertRawProp(rawProps, "color", sourceProps.color, {})), - testID(convertRawProp(rawProps, "testID", sourceProps.testID, {""})) - {} -RCTProgressViewProps::RCTProgressViewProps( - const RCTProgressViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - progressViewStyle(convertRawProp(rawProps, "progressViewStyle", sourceProps.progressViewStyle, {RCTProgressViewProgressViewStyle::Default})), - progress(convertRawProp(rawProps, "progress", sourceProps.progress, {0.0})), - progressTintColor(convertRawProp(rawProps, "progressTintColor", sourceProps.progressTintColor, {})), - trackTintColor(convertRawProp(rawProps, "trackTintColor", sourceProps.trackTintColor, {})), - progressImage(convertRawProp(rawProps, "progressImage", sourceProps.progressImage, {})), - trackImage(convertRawProp(rawProps, "trackImage", sourceProps.trackImage, {})) - {} -AndroidSwipeRefreshLayoutProps::AndroidSwipeRefreshLayoutProps( - const AndroidSwipeRefreshLayoutProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})), - colors(convertRawProp(rawProps, "colors", sourceProps.colors, {})), - progressBackgroundColor(convertRawProp(rawProps, "progressBackgroundColor", sourceProps.progressBackgroundColor, {})), - size(convertRawProp(rawProps, "size", sourceProps.size, {1})), - progressViewOffset(convertRawProp(rawProps, "progressViewOffset", sourceProps.progressViewOffset, {0.0})), - refreshing(convertRawProp(rawProps, "refreshing", sourceProps.refreshing, {false})) - {} -PullToRefreshViewProps::PullToRefreshViewProps( - const PullToRefreshViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - tintColor(convertRawProp(rawProps, "tintColor", sourceProps.tintColor, {})), - titleColor(convertRawProp(rawProps, "titleColor", sourceProps.titleColor, {})), - title(convertRawProp(rawProps, "title", sourceProps.title, {})), - refreshing(convertRawProp(rawProps, "refreshing", sourceProps.refreshing, {false})) - {} -SafeAreaViewProps::SafeAreaViewProps( - const SafeAreaViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - emulateUnlessSupported(convertRawProp(rawProps, "emulateUnlessSupported", sourceProps.emulateUnlessSupported, {false})) - {} -RCTSegmentedControlProps::RCTSegmentedControlProps( - const RCTSegmentedControlProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - values(convertRawProp(rawProps, "values", sourceProps.values, {})), - selectedIndex(convertRawProp(rawProps, "selectedIndex", sourceProps.selectedIndex, {0})), - enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})), - tintColor(convertRawProp(rawProps, "tintColor", sourceProps.tintColor, {})), - textColor(convertRawProp(rawProps, "textColor", sourceProps.textColor, {})), - backgroundColor(convertRawProp(rawProps, "backgroundColor", sourceProps.backgroundColor, {})), - momentary(convertRawProp(rawProps, "momentary", sourceProps.momentary, {false})) - {} -SliderProps::SliderProps( - const SliderProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - disabled(convertRawProp(rawProps, "disabled", sourceProps.disabled, {false})), - enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})), - maximumTrackImage(convertRawProp(rawProps, "maximumTrackImage", sourceProps.maximumTrackImage, {})), - maximumTrackTintColor(convertRawProp(rawProps, "maximumTrackTintColor", sourceProps.maximumTrackTintColor, {})), - maximumValue(convertRawProp(rawProps, "maximumValue", sourceProps.maximumValue, {1.0})), - minimumTrackImage(convertRawProp(rawProps, "minimumTrackImage", sourceProps.minimumTrackImage, {})), - minimumTrackTintColor(convertRawProp(rawProps, "minimumTrackTintColor", sourceProps.minimumTrackTintColor, {})), - minimumValue(convertRawProp(rawProps, "minimumValue", sourceProps.minimumValue, {0.0})), - step(convertRawProp(rawProps, "step", sourceProps.step, {0.0})), - testID(convertRawProp(rawProps, "testID", sourceProps.testID, {""})), - thumbImage(convertRawProp(rawProps, "thumbImage", sourceProps.thumbImage, {})), - thumbTintColor(convertRawProp(rawProps, "thumbTintColor", sourceProps.thumbTintColor, {})), - trackImage(convertRawProp(rawProps, "trackImage", sourceProps.trackImage, {})), - value(convertRawProp(rawProps, "value", sourceProps.value, {0.0})) - {} -AndroidSwitchProps::AndroidSwitchProps( - const AndroidSwitchProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - disabled(convertRawProp(rawProps, "disabled", sourceProps.disabled, {false})), - enabled(convertRawProp(rawProps, "enabled", sourceProps.enabled, {true})), - thumbColor(convertRawProp(rawProps, "thumbColor", sourceProps.thumbColor, {})), - trackColorForFalse(convertRawProp(rawProps, "trackColorForFalse", sourceProps.trackColorForFalse, {})), - trackColorForTrue(convertRawProp(rawProps, "trackColorForTrue", sourceProps.trackColorForTrue, {})), - value(convertRawProp(rawProps, "value", sourceProps.value, {false})), - on(convertRawProp(rawProps, "on", sourceProps.on, {false})), - thumbTintColor(convertRawProp(rawProps, "thumbTintColor", sourceProps.thumbTintColor, {})), - trackTintColor(convertRawProp(rawProps, "trackTintColor", sourceProps.trackTintColor, {})) - {} -SwitchProps::SwitchProps( - const SwitchProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - disabled(convertRawProp(rawProps, "disabled", sourceProps.disabled, {false})), - value(convertRawProp(rawProps, "value", sourceProps.value, {false})), - tintColor(convertRawProp(rawProps, "tintColor", sourceProps.tintColor, {})), - onTintColor(convertRawProp(rawProps, "onTintColor", sourceProps.onTintColor, {})), - thumbTintColor(convertRawProp(rawProps, "thumbTintColor", sourceProps.thumbTintColor, {})), - thumbColor(convertRawProp(rawProps, "thumbColor", sourceProps.thumbColor, {})), - trackColorForFalse(convertRawProp(rawProps, "trackColorForFalse", sourceProps.trackColorForFalse, {})), - trackColorForTrue(convertRawProp(rawProps, "trackColorForTrue", sourceProps.trackColorForTrue, {})) - {} -InputAccessoryProps::InputAccessoryProps( - const InputAccessoryProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - backgroundColor(convertRawProp(rawProps, "backgroundColor", sourceProps.backgroundColor, {})) - {} -UnimplementedNativeViewProps::UnimplementedNativeViewProps( - const UnimplementedNativeViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - name(convertRawProp(rawProps, "name", sourceProps.name, {""})) - {} -ModalHostViewProps::ModalHostViewProps( - const ModalHostViewProps &sourceProps, - const RawProps &rawProps): ViewProps(sourceProps, rawProps), - - animationType(convertRawProp(rawProps, "animationType", sourceProps.animationType, {ModalHostViewAnimationType::None})), - presentationStyle(convertRawProp(rawProps, "presentationStyle", sourceProps.presentationStyle, {ModalHostViewPresentationStyle::FullScreen})), - transparent(convertRawProp(rawProps, "transparent", sourceProps.transparent, {false})), - statusBarTranslucent(convertRawProp(rawProps, "statusBarTranslucent", sourceProps.statusBarTranslucent, {false})), - hardwareAccelerated(convertRawProp(rawProps, "hardwareAccelerated", sourceProps.hardwareAccelerated, {false})), - animated(convertRawProp(rawProps, "animated", sourceProps.animated, {false})), - supportedOrientations(convertRawProp(rawProps, "supportedOrientations", sourceProps.supportedOrientations, {static_cast(ModalHostViewSupportedOrientations::Portrait)})), - identifier(convertRawProp(rawProps, "identifier", sourceProps.identifier, {0})) - {} - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.h b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.h deleted file mode 100644 index b968f7e266817e..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.h +++ /dev/null @@ -1,529 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GeneratePropsH.js - */ -#pragma once - -#include -#include -#include -#include -#include - -namespace facebook { -namespace react { - -enum class ActivityIndicatorViewSize { Small, Large }; - -static inline void fromRawValue(const RawValue &value, ActivityIndicatorViewSize &result) { - auto string = (std::string)value; - if (string == "small") { result = ActivityIndicatorViewSize::Small; return; } - if (string == "large") { result = ActivityIndicatorViewSize::Large; return; } - abort(); -} - -static inline std::string toString(const ActivityIndicatorViewSize &value) { - switch (value) { - case ActivityIndicatorViewSize::Small: return "small"; - case ActivityIndicatorViewSize::Large: return "large"; - } -} - -class ActivityIndicatorViewProps final : public ViewProps { - public: - ActivityIndicatorViewProps() = default; - ActivityIndicatorViewProps(const ActivityIndicatorViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool hidesWhenStopped{false}; - bool animating{false}; - SharedColor color{}; - ActivityIndicatorViewSize size{ActivityIndicatorViewSize::Small}; -}; - -enum class DatePickerMinuteInterval { MinuteInterval1 = 1, MinuteInterval2 = 2, MinuteInterval3 = 3, MinuteInterval4 = 4, MinuteInterval5 = 5, MinuteInterval6 = 6, MinuteInterval10 = 10, MinuteInterval12 = 12, MinuteInterval15 = 15, MinuteInterval20 = 20, MinuteInterval30 = 30 }; - -static inline void fromRawValue(const RawValue &value, DatePickerMinuteInterval &result) { - assert(value.hasType()); - auto integerValue = (int)value; - switch (integerValue) { - case 1: - result = DatePickerMinuteInterval::MinuteInterval1; - return; - case 2: - result = DatePickerMinuteInterval::MinuteInterval2; - return; - case 3: - result = DatePickerMinuteInterval::MinuteInterval3; - return; - case 4: - result = DatePickerMinuteInterval::MinuteInterval4; - return; - case 5: - result = DatePickerMinuteInterval::MinuteInterval5; - return; - case 6: - result = DatePickerMinuteInterval::MinuteInterval6; - return; - case 10: - result = DatePickerMinuteInterval::MinuteInterval10; - return; - case 12: - result = DatePickerMinuteInterval::MinuteInterval12; - return; - case 15: - result = DatePickerMinuteInterval::MinuteInterval15; - return; - case 20: - result = DatePickerMinuteInterval::MinuteInterval20; - return; - case 30: - result = DatePickerMinuteInterval::MinuteInterval30; - return; - } - abort(); -} - -static inline std::string toString(const DatePickerMinuteInterval &value) { - switch (value) { - case DatePickerMinuteInterval::MinuteInterval1: return "1"; - case DatePickerMinuteInterval::MinuteInterval2: return "2"; - case DatePickerMinuteInterval::MinuteInterval3: return "3"; - case DatePickerMinuteInterval::MinuteInterval4: return "4"; - case DatePickerMinuteInterval::MinuteInterval5: return "5"; - case DatePickerMinuteInterval::MinuteInterval6: return "6"; - case DatePickerMinuteInterval::MinuteInterval10: return "10"; - case DatePickerMinuteInterval::MinuteInterval12: return "12"; - case DatePickerMinuteInterval::MinuteInterval15: return "15"; - case DatePickerMinuteInterval::MinuteInterval20: return "20"; - case DatePickerMinuteInterval::MinuteInterval30: return "30"; - } -} -enum class DatePickerMode { Date, Time, Datetime }; - -static inline void fromRawValue(const RawValue &value, DatePickerMode &result) { - auto string = (std::string)value; - if (string == "date") { result = DatePickerMode::Date; return; } - if (string == "time") { result = DatePickerMode::Time; return; } - if (string == "datetime") { result = DatePickerMode::Datetime; return; } - abort(); -} - -static inline std::string toString(const DatePickerMode &value) { - switch (value) { - case DatePickerMode::Date: return "date"; - case DatePickerMode::Time: return "time"; - case DatePickerMode::Datetime: return "datetime"; - } -} - -class DatePickerProps final : public ViewProps { - public: - DatePickerProps() = default; - DatePickerProps(const DatePickerProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - Float date{0.0}; - Float initialDate{0.0}; - std::string locale{}; - Float maximumDate{0.0}; - Float minimumDate{0.0}; - DatePickerMinuteInterval minuteInterval{DatePickerMinuteInterval::MinuteInterval1}; - DatePickerMode mode{DatePickerMode::Date}; - Float timeZoneOffsetInMinutes{0.0}; -}; - -enum class AndroidDrawerLayoutKeyboardDismissMode { None, OnDrag }; - -static inline void fromRawValue(const RawValue &value, AndroidDrawerLayoutKeyboardDismissMode &result) { - auto string = (std::string)value; - if (string == "none") { result = AndroidDrawerLayoutKeyboardDismissMode::None; return; } - if (string == "on-drag") { result = AndroidDrawerLayoutKeyboardDismissMode::OnDrag; return; } - abort(); -} - -static inline std::string toString(const AndroidDrawerLayoutKeyboardDismissMode &value) { - switch (value) { - case AndroidDrawerLayoutKeyboardDismissMode::None: return "none"; - case AndroidDrawerLayoutKeyboardDismissMode::OnDrag: return "on-drag"; - } -} -enum class AndroidDrawerLayoutDrawerPosition { Left, Right }; - -static inline void fromRawValue(const RawValue &value, AndroidDrawerLayoutDrawerPosition &result) { - auto string = (std::string)value; - if (string == "left") { result = AndroidDrawerLayoutDrawerPosition::Left; return; } - if (string == "right") { result = AndroidDrawerLayoutDrawerPosition::Right; return; } - abort(); -} - -static inline std::string toString(const AndroidDrawerLayoutDrawerPosition &value) { - switch (value) { - case AndroidDrawerLayoutDrawerPosition::Left: return "left"; - case AndroidDrawerLayoutDrawerPosition::Right: return "right"; - } -} -enum class AndroidDrawerLayoutDrawerLockMode { Unlocked, LockedClosed, LockedOpen }; - -static inline void fromRawValue(const RawValue &value, AndroidDrawerLayoutDrawerLockMode &result) { - auto string = (std::string)value; - if (string == "unlocked") { result = AndroidDrawerLayoutDrawerLockMode::Unlocked; return; } - if (string == "locked-closed") { result = AndroidDrawerLayoutDrawerLockMode::LockedClosed; return; } - if (string == "locked-open") { result = AndroidDrawerLayoutDrawerLockMode::LockedOpen; return; } - abort(); -} - -static inline std::string toString(const AndroidDrawerLayoutDrawerLockMode &value) { - switch (value) { - case AndroidDrawerLayoutDrawerLockMode::Unlocked: return "unlocked"; - case AndroidDrawerLayoutDrawerLockMode::LockedClosed: return "locked-closed"; - case AndroidDrawerLayoutDrawerLockMode::LockedOpen: return "locked-open"; - } -} - -class AndroidDrawerLayoutProps final : public ViewProps { - public: - AndroidDrawerLayoutProps() = default; - AndroidDrawerLayoutProps(const AndroidDrawerLayoutProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - AndroidDrawerLayoutKeyboardDismissMode keyboardDismissMode{AndroidDrawerLayoutKeyboardDismissMode::None}; - SharedColor drawerBackgroundColor{}; - AndroidDrawerLayoutDrawerPosition drawerPosition{AndroidDrawerLayoutDrawerPosition::Left}; - Float drawerWidth{}; - AndroidDrawerLayoutDrawerLockMode drawerLockMode{AndroidDrawerLayoutDrawerLockMode::Unlocked}; - SharedColor statusBarBackgroundColor{}; -}; - -class RCTMaskedViewProps final : public ViewProps { - public: - RCTMaskedViewProps() = default; - RCTMaskedViewProps(const RCTMaskedViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - -}; - -class AndroidProgressBarProps final : public ViewProps { - public: - AndroidProgressBarProps() = default; - AndroidProgressBarProps(const AndroidProgressBarProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - std::string styleAttr{}; - std::string typeAttr{}; - bool indeterminate{false}; - double progress{0.0}; - bool animating{true}; - SharedColor color{}; - std::string testID{""}; -}; - -enum class RCTProgressViewProgressViewStyle { Default, Bar }; - -static inline void fromRawValue(const RawValue &value, RCTProgressViewProgressViewStyle &result) { - auto string = (std::string)value; - if (string == "default") { result = RCTProgressViewProgressViewStyle::Default; return; } - if (string == "bar") { result = RCTProgressViewProgressViewStyle::Bar; return; } - abort(); -} - -static inline std::string toString(const RCTProgressViewProgressViewStyle &value) { - switch (value) { - case RCTProgressViewProgressViewStyle::Default: return "default"; - case RCTProgressViewProgressViewStyle::Bar: return "bar"; - } -} - -class RCTProgressViewProps final : public ViewProps { - public: - RCTProgressViewProps() = default; - RCTProgressViewProps(const RCTProgressViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - RCTProgressViewProgressViewStyle progressViewStyle{RCTProgressViewProgressViewStyle::Default}; - Float progress{0.0}; - SharedColor progressTintColor{}; - SharedColor trackTintColor{}; - ImageSource progressImage{}; - ImageSource trackImage{}; -}; - -class AndroidSwipeRefreshLayoutProps final : public ViewProps { - public: - AndroidSwipeRefreshLayoutProps() = default; - AndroidSwipeRefreshLayoutProps(const AndroidSwipeRefreshLayoutProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool enabled{true}; - std::vector colors{}; - SharedColor progressBackgroundColor{}; - int size{1}; - Float progressViewOffset{0.0}; - bool refreshing{false}; -}; - -class PullToRefreshViewProps final : public ViewProps { - public: - PullToRefreshViewProps() = default; - PullToRefreshViewProps(const PullToRefreshViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - SharedColor tintColor{}; - SharedColor titleColor{}; - std::string title{}; - bool refreshing{false}; -}; - -class SafeAreaViewProps final : public ViewProps { - public: - SafeAreaViewProps() = default; - SafeAreaViewProps(const SafeAreaViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool emulateUnlessSupported{false}; -}; - -class RCTSegmentedControlProps final : public ViewProps { - public: - RCTSegmentedControlProps() = default; - RCTSegmentedControlProps(const RCTSegmentedControlProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - std::vector values{}; - int selectedIndex{0}; - bool enabled{true}; - SharedColor tintColor{}; - SharedColor textColor{}; - SharedColor backgroundColor{}; - bool momentary{false}; -}; - -class SliderProps final : public ViewProps { - public: - SliderProps() = default; - SliderProps(const SliderProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool disabled{false}; - bool enabled{true}; - ImageSource maximumTrackImage{}; - SharedColor maximumTrackTintColor{}; - double maximumValue{1.0}; - ImageSource minimumTrackImage{}; - SharedColor minimumTrackTintColor{}; - double minimumValue{0.0}; - double step{0.0}; - std::string testID{""}; - ImageSource thumbImage{}; - SharedColor thumbTintColor{}; - ImageSource trackImage{}; - double value{0.0}; -}; - -class AndroidSwitchProps final : public ViewProps { - public: - AndroidSwitchProps() = default; - AndroidSwitchProps(const AndroidSwitchProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool disabled{false}; - bool enabled{true}; - SharedColor thumbColor{}; - SharedColor trackColorForFalse{}; - SharedColor trackColorForTrue{}; - bool value{false}; - bool on{false}; - SharedColor thumbTintColor{}; - SharedColor trackTintColor{}; -}; - -class SwitchProps final : public ViewProps { - public: - SwitchProps() = default; - SwitchProps(const SwitchProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - bool disabled{false}; - bool value{false}; - SharedColor tintColor{}; - SharedColor onTintColor{}; - SharedColor thumbTintColor{}; - SharedColor thumbColor{}; - SharedColor trackColorForFalse{}; - SharedColor trackColorForTrue{}; -}; - -class InputAccessoryProps final : public ViewProps { - public: - InputAccessoryProps() = default; - InputAccessoryProps(const InputAccessoryProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - SharedColor backgroundColor{}; -}; - -class UnimplementedNativeViewProps final : public ViewProps { - public: - UnimplementedNativeViewProps() = default; - UnimplementedNativeViewProps(const UnimplementedNativeViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - std::string name{""}; -}; - -enum class ModalHostViewAnimationType { None, Slide, Fade }; - -static inline void fromRawValue(const RawValue &value, ModalHostViewAnimationType &result) { - auto string = (std::string)value; - if (string == "none") { result = ModalHostViewAnimationType::None; return; } - if (string == "slide") { result = ModalHostViewAnimationType::Slide; return; } - if (string == "fade") { result = ModalHostViewAnimationType::Fade; return; } - abort(); -} - -static inline std::string toString(const ModalHostViewAnimationType &value) { - switch (value) { - case ModalHostViewAnimationType::None: return "none"; - case ModalHostViewAnimationType::Slide: return "slide"; - case ModalHostViewAnimationType::Fade: return "fade"; - } -} -enum class ModalHostViewPresentationStyle { FullScreen, PageSheet, FormSheet, OverFullScreen }; - -static inline void fromRawValue(const RawValue &value, ModalHostViewPresentationStyle &result) { - auto string = (std::string)value; - if (string == "fullScreen") { result = ModalHostViewPresentationStyle::FullScreen; return; } - if (string == "pageSheet") { result = ModalHostViewPresentationStyle::PageSheet; return; } - if (string == "formSheet") { result = ModalHostViewPresentationStyle::FormSheet; return; } - if (string == "overFullScreen") { result = ModalHostViewPresentationStyle::OverFullScreen; return; } - abort(); -} - -static inline std::string toString(const ModalHostViewPresentationStyle &value) { - switch (value) { - case ModalHostViewPresentationStyle::FullScreen: return "fullScreen"; - case ModalHostViewPresentationStyle::PageSheet: return "pageSheet"; - case ModalHostViewPresentationStyle::FormSheet: return "formSheet"; - case ModalHostViewPresentationStyle::OverFullScreen: return "overFullScreen"; - } -} -using ModalHostViewSupportedOrientationsMask = uint32_t; - -enum class ModalHostViewSupportedOrientations: ModalHostViewSupportedOrientationsMask { - Portrait = 1 << 0, - PortraitUpsideDown = 1 << 1, - Landscape = 1 << 2, - LandscapeLeft = 1 << 3, - LandscapeRight = 1 << 4 -}; - -constexpr bool operator&( - ModalHostViewSupportedOrientationsMask const lhs, - enum ModalHostViewSupportedOrientations const rhs) { - return lhs & static_cast(rhs); -} - -constexpr ModalHostViewSupportedOrientationsMask operator|( - ModalHostViewSupportedOrientationsMask const lhs, - enum ModalHostViewSupportedOrientations const rhs) { - return lhs | static_cast(rhs); -} - -constexpr void operator|=( - ModalHostViewSupportedOrientationsMask &lhs, - enum ModalHostViewSupportedOrientations const rhs) { - lhs = lhs | static_cast(rhs); -} - -static inline void fromRawValue(const RawValue &value, ModalHostViewSupportedOrientationsMask &result) { - auto items = std::vector{value}; - for (const auto &item : items) { - if (item == "portrait") { - result |= ModalHostViewSupportedOrientations::Portrait; - continue; - } - if (item == "portrait-upside-down") { - result |= ModalHostViewSupportedOrientations::PortraitUpsideDown; - continue; - } - if (item == "landscape") { - result |= ModalHostViewSupportedOrientations::Landscape; - continue; - } - if (item == "landscape-left") { - result |= ModalHostViewSupportedOrientations::LandscapeLeft; - continue; - } - if (item == "landscape-right") { - result |= ModalHostViewSupportedOrientations::LandscapeRight; - continue; - } - abort(); - } -} - -static inline std::string toString(const ModalHostViewSupportedOrientationsMask &value) { - auto result = std::string{}; - auto separator = std::string{", "}; - - if (value & ModalHostViewSupportedOrientations::Portrait) { - result += "portrait" + separator; - } - if (value & ModalHostViewSupportedOrientations::PortraitUpsideDown) { - result += "portrait-upside-down" + separator; - } - if (value & ModalHostViewSupportedOrientations::Landscape) { - result += "landscape" + separator; - } - if (value & ModalHostViewSupportedOrientations::LandscapeLeft) { - result += "landscape-left" + separator; - } - if (value & ModalHostViewSupportedOrientations::LandscapeRight) { - result += "landscape-right" + separator; - } - if (!result.empty()) { - result.erase(result.length() - separator.length()); - } - return result; -} - -class ModalHostViewProps final : public ViewProps { - public: - ModalHostViewProps() = default; - ModalHostViewProps(const ModalHostViewProps &sourceProps, const RawProps &rawProps); - -#pragma mark - Props - - ModalHostViewAnimationType animationType{ModalHostViewAnimationType::None}; - ModalHostViewPresentationStyle presentationStyle{ModalHostViewPresentationStyle::FullScreen}; - bool transparent{false}; - bool statusBarTranslucent{false}; - bool hardwareAccelerated{false}; - bool animated{false}; - ModalHostViewSupportedOrientationsMask supportedOrientations{static_cast(ModalHostViewSupportedOrientations::Portrait)}; - int identifier{0}; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.cpp b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.cpp deleted file mode 100644 index befdb19c30df35..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.cpp +++ /dev/null @@ -1,28 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateShadowNodeCpp.js - */ - -#include - -namespace facebook { -namespace react { - -extern const char ActivityIndicatorViewComponentName[] = "ActivityIndicatorView"; -extern const char DatePickerComponentName[] = "DatePicker"; -extern const char AndroidDrawerLayoutComponentName[] = "AndroidDrawerLayout"; -extern const char RCTMaskedViewComponentName[] = "RCTMaskedView"; -extern const char RCTProgressViewComponentName[] = "RCTProgressView"; -extern const char AndroidSwipeRefreshLayoutComponentName[] = "AndroidSwipeRefreshLayout"; -extern const char PullToRefreshViewComponentName[] = "PullToRefreshView"; -extern const char RCTSegmentedControlComponentName[] = "RCTSegmentedControl"; -extern const char SwitchComponentName[] = "Switch"; -extern const char UnimplementedNativeViewComponentName[] = "UnimplementedNativeView"; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.h b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.h deleted file mode 100644 index f8a84f5836b01b..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.h +++ /dev/null @@ -1,117 +0,0 @@ - -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateShadowNodeH.js - */ - -#pragma once - -#include -#include -#include - -namespace facebook { -namespace react { - -extern const char ActivityIndicatorViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using ActivityIndicatorViewShadowNode = ConcreteViewShadowNode< - ActivityIndicatorViewComponentName, - ActivityIndicatorViewProps>; - -extern const char DatePickerComponentName[]; - -/* - * `ShadowNode` for component. - */ -using DatePickerShadowNode = ConcreteViewShadowNode< - DatePickerComponentName, - DatePickerProps, -DatePickerEventEmitter>; - -extern const char AndroidDrawerLayoutComponentName[]; - -/* - * `ShadowNode` for component. - */ -using AndroidDrawerLayoutShadowNode = ConcreteViewShadowNode< - AndroidDrawerLayoutComponentName, - AndroidDrawerLayoutProps, -AndroidDrawerLayoutEventEmitter>; - -extern const char RCTMaskedViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using RCTMaskedViewShadowNode = ConcreteViewShadowNode< - RCTMaskedViewComponentName, - RCTMaskedViewProps>; - -extern const char RCTProgressViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using RCTProgressViewShadowNode = ConcreteViewShadowNode< - RCTProgressViewComponentName, - RCTProgressViewProps>; - -extern const char AndroidSwipeRefreshLayoutComponentName[]; - -/* - * `ShadowNode` for component. - */ -using AndroidSwipeRefreshLayoutShadowNode = ConcreteViewShadowNode< - AndroidSwipeRefreshLayoutComponentName, - AndroidSwipeRefreshLayoutProps, -AndroidSwipeRefreshLayoutEventEmitter>; - -extern const char PullToRefreshViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using PullToRefreshViewShadowNode = ConcreteViewShadowNode< - PullToRefreshViewComponentName, - PullToRefreshViewProps, -PullToRefreshViewEventEmitter>; - -extern const char RCTSegmentedControlComponentName[]; - -/* - * `ShadowNode` for component. - */ -using RCTSegmentedControlShadowNode = ConcreteViewShadowNode< - RCTSegmentedControlComponentName, - RCTSegmentedControlProps, -RCTSegmentedControlEventEmitter>; - -extern const char SwitchComponentName[]; - -/* - * `ShadowNode` for component. - */ -using SwitchShadowNode = ConcreteViewShadowNode< - SwitchComponentName, - SwitchProps, -SwitchEventEmitter>; - -extern const char UnimplementedNativeViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -using UnimplementedNativeViewShadowNode = ConcreteViewShadowNode< - UnimplementedNativeViewComponentName, - UnimplementedNativeViewProps>; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK index 2b6f2c1e932a8e..720c0618c0f9a8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "common", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK index ac71cc153ec774..e500ae5c9c15d7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "drawer", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -25,6 +26,6 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), react_native_target("java/com/facebook/react/views/scroll:scroll"), - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java index 712353eb0a42f2..b3d9cc11bcdc22 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java @@ -20,7 +20,7 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.ViewManagerDelegate; import com.facebook.react.uimanager.annotations.ReactProp; @@ -56,12 +56,13 @@ public ReactDrawerLayoutManager() { @Override protected void addEventEmitters(ThemedReactContext reactContext, ReactDrawerLayout view) { - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - if (uiManager == null) { + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId()); + if (eventDispatcher == null) { return; } - view.addDrawerListener(new DrawerEventEmitter(view, uiManager.getEventDispatcher())); + view.addDrawerListener(new DrawerEventEmitter(view, eventDispatcher)); } @Override @@ -252,22 +253,30 @@ public DrawerEventEmitter(DrawerLayout drawerLayout, EventDispatcher eventDispat @Override public void onDrawerSlide(@NonNull View view, float v) { - mEventDispatcher.dispatchEvent(new DrawerSlideEvent(mDrawerLayout.getId(), v)); + mEventDispatcher.dispatchEvent( + new DrawerSlideEvent( + UIManagerHelper.getSurfaceId(mDrawerLayout), mDrawerLayout.getId(), v)); } @Override public void onDrawerOpened(@NonNull View view) { - mEventDispatcher.dispatchEvent(new DrawerOpenedEvent(mDrawerLayout.getId())); + mEventDispatcher.dispatchEvent( + new DrawerOpenedEvent( + UIManagerHelper.getSurfaceId(mDrawerLayout), mDrawerLayout.getId())); } @Override public void onDrawerClosed(@NonNull View view) { - mEventDispatcher.dispatchEvent(new DrawerClosedEvent(mDrawerLayout.getId())); + mEventDispatcher.dispatchEvent( + new DrawerClosedEvent( + UIManagerHelper.getSurfaceId(mDrawerLayout), mDrawerLayout.getId())); } @Override public void onDrawerStateChanged(int i) { - mEventDispatcher.dispatchEvent(new DrawerStateChangedEvent(mDrawerLayout.getId(), i)); + mEventDispatcher.dispatchEvent( + new DrawerStateChangedEvent( + UIManagerHelper.getSurfaceId(mDrawerLayout), mDrawerLayout.getId(), i)); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerClosedEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerClosedEvent.java index e6bd567032fa4a..06be4490ab2b9f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerClosedEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerClosedEvent.java @@ -8,15 +8,20 @@ package com.facebook.react.views.drawer.events; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; public class DrawerClosedEvent extends Event { public static final String EVENT_NAME = "topDrawerClose"; + @Deprecated public DrawerClosedEvent(int viewId) { - super(viewId); + this(-1, viewId); + } + + public DrawerClosedEvent(int surfaceId, int viewId) { + super(surfaceId, viewId); } @Override @@ -25,13 +30,13 @@ public String getEventName() { } @Override - public short getCoalescingKey() { - // All events for a given view can be coalesced. - return 0; + protected WritableMap getEventData() { + return Arguments.createMap(); } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), Arguments.createMap()); + public short getCoalescingKey() { + // All events for a given view can be coalesced. + return 0; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerOpenedEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerOpenedEvent.java index 2e754dc5207996..35adbe6b71b403 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerOpenedEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerOpenedEvent.java @@ -8,15 +8,20 @@ package com.facebook.react.views.drawer.events; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; public class DrawerOpenedEvent extends Event { public static final String EVENT_NAME = "topDrawerOpen"; + @Deprecated public DrawerOpenedEvent(int viewId) { - super(viewId); + this(-1, viewId); + } + + public DrawerOpenedEvent(int surfaceId, int viewId) { + super(surfaceId, viewId); } @Override @@ -25,13 +30,13 @@ public String getEventName() { } @Override - public short getCoalescingKey() { - // All events for a given view can be coalesced. - return 0; + protected WritableMap getEventData() { + return Arguments.createMap(); } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), Arguments.createMap()); + public short getCoalescingKey() { + // All events for a given view can be coalesced. + return 0; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerSlideEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerSlideEvent.java index 7d3a0af18dded5..d8dda5c560a532 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerSlideEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerSlideEvent.java @@ -10,7 +10,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by a DrawerLayout as it is being moved open/closed. */ public class DrawerSlideEvent extends Event { @@ -19,8 +18,13 @@ public class DrawerSlideEvent extends Event { private final float mOffset; + @Deprecated public DrawerSlideEvent(int viewId, float offset) { - super(viewId); + this(-1, viewId, offset); + } + + public DrawerSlideEvent(int surfaceId, int viewId, float offset) { + super(surfaceId, viewId); mOffset = offset; } @@ -40,11 +44,7 @@ public short getCoalescingKey() { } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putDouble("offset", getOffset()); return eventData; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerStateChangedEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerStateChangedEvent.java index 009217934d3d6d..abdb8a38a76d2d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerStateChangedEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/events/DrawerStateChangedEvent.java @@ -10,7 +10,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; public class DrawerStateChangedEvent extends Event { @@ -18,8 +17,13 @@ public class DrawerStateChangedEvent extends Event { private final int mDrawerState; + @Deprecated public DrawerStateChangedEvent(int viewId, int drawerState) { - super(viewId); + this(-1, viewId, drawerState); + } + + public DrawerStateChangedEvent(int surfaceId, int viewId, int drawerState) { + super(surfaceId, viewId); mDrawerState = drawerState; } @@ -39,11 +43,7 @@ public short getCoalescingKey() { } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putDouble("drawerState", getDrawerState()); return eventData; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK index 663357ac133d7f..40f0d2f5592b3f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK @@ -7,6 +7,7 @@ IMAGE_EVENT_FILES = [ rn_android_library( name = "imageevents", srcs = IMAGE_EVENT_FILES, + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -31,6 +32,7 @@ rn_android_library( ["*.java"], exclude = IMAGE_EVENT_FILES, ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.java index 69778f028f5a94..130cb67ad8b60f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.java @@ -12,7 +12,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -35,8 +34,35 @@ public class ImageLoadEvent extends Event { private final int mLoaded; private final int mTotal; + @Deprecated public static final ImageLoadEvent createLoadStartEvent(int viewId) { - return new ImageLoadEvent(viewId, ON_LOAD_START); + return createLoadStartEvent(-1, viewId); + } + + @Deprecated + public static final ImageLoadEvent createProgressEvent( + int viewId, @Nullable String imageUri, int loaded, int total) { + return createProgressEvent(-1, viewId, imageUri, loaded, total); + } + + @Deprecated + public static final ImageLoadEvent createLoadEvent( + int viewId, @Nullable String imageUri, int width, int height) { + return createLoadEvent(-1, viewId, imageUri, width, height); + } + + @Deprecated + public static final ImageLoadEvent createErrorEvent(int viewId, Throwable throwable) { + return createErrorEvent(-1, viewId, throwable); + } + + @Deprecated + public static final ImageLoadEvent createLoadEndEvent(int viewId) { + return createLoadEndEvent(-1, viewId); + } + + public static final ImageLoadEvent createLoadStartEvent(int surfaceId, int viewId) { + return new ImageLoadEvent(surfaceId, viewId, ON_LOAD_START); } /** @@ -45,28 +71,31 @@ public static final ImageLoadEvent createLoadStartEvent(int viewId) { * @param total Amount that `loaded` will be when the image is fully loaded. */ public static final ImageLoadEvent createProgressEvent( - int viewId, @Nullable String imageUri, int loaded, int total) { - return new ImageLoadEvent(viewId, ON_PROGRESS, null, imageUri, 0, 0, loaded, total); + int surfaceId, int viewId, @Nullable String imageUri, int loaded, int total) { + return new ImageLoadEvent(surfaceId, viewId, ON_PROGRESS, null, imageUri, 0, 0, loaded, total); } public static final ImageLoadEvent createLoadEvent( - int viewId, @Nullable String imageUri, int width, int height) { - return new ImageLoadEvent(viewId, ON_LOAD, null, imageUri, width, height, 0, 0); + int surfaceId, int viewId, @Nullable String imageUri, int width, int height) { + return new ImageLoadEvent(surfaceId, viewId, ON_LOAD, null, imageUri, width, height, 0, 0); } - public static final ImageLoadEvent createErrorEvent(int viewId, Throwable throwable) { - return new ImageLoadEvent(viewId, ON_ERROR, throwable.getMessage(), null, 0, 0, 0, 0); + public static final ImageLoadEvent createErrorEvent( + int surfaceId, int viewId, Throwable throwable) { + return new ImageLoadEvent( + surfaceId, viewId, ON_ERROR, throwable.getMessage(), null, 0, 0, 0, 0); } - public static final ImageLoadEvent createLoadEndEvent(int viewId) { - return new ImageLoadEvent(viewId, ON_LOAD_END); + public static final ImageLoadEvent createLoadEndEvent(int surfaceId, int viewId) { + return new ImageLoadEvent(surfaceId, viewId, ON_LOAD_END); } - private ImageLoadEvent(int viewId, @ImageEventType int eventType) { - this(viewId, eventType, null, null, 0, 0, 0, 0); + private ImageLoadEvent(int surfaceId, int viewId, @ImageEventType int eventType) { + this(surfaceId, viewId, eventType, null, null, 0, 0, 0, 0); } private ImageLoadEvent( + int surfaceId, int viewId, @ImageEventType int eventType, @Nullable String errorMessage, @@ -75,7 +104,7 @@ private ImageLoadEvent( int height, int loaded, int total) { - super(viewId); + super(surfaceId, viewId); mEventType = eventType; mErrorMessage = errorMessage; mSourceUri = sourceUri; @@ -115,26 +144,23 @@ public short getCoalescingKey() { } @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - WritableMap eventData = null; + protected WritableMap getEventData() { + WritableMap eventData = Arguments.createMap(); switch (mEventType) { case ON_PROGRESS: - eventData = Arguments.createMap(); eventData.putInt("loaded", mLoaded); eventData.putInt("total", mTotal); break; case ON_LOAD: - eventData = Arguments.createMap(); eventData.putMap("source", createEventDataSource()); break; case ON_ERROR: - eventData = Arguments.createMap(); eventData.putString("error", mErrorMessage); break; } - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData); + return eventData; } private WritableMap createEventDataSource() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java index 46e9573fdb0ca1..cb1c6a336048ee 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactCallerContextFactory.java @@ -20,9 +20,9 @@ public interface ReactCallerContextFactory { /** * This method will be called at the time {@link ReactImageManager} creates {@link ReactImageView} * - * @param surfaceID {@link String} used to log the name of the surface + * @param surfaceName {@link String} used to log the name of the surface * @return an {@link Object} that represents the CallerContext. */ @Nullable - Object getOrCreateCallerContext(@Nullable String surfaceID, @Nullable String analyticTag); + Object getOrCreateCallerContext(@Nullable String surfaceName, @Nullable String analyticTag); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index 397a8378d603f4..d1250c7563ff05 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -107,7 +107,7 @@ public Object getCallerContext() { public ReactImageView createViewInstance(ThemedReactContext context) { Object callerContext = mCallerContextFactory != null - ? mCallerContextFactory.getOrCreateCallerContext(context.getSurfaceID(), null) + ? mCallerContextFactory.getOrCreateCallerContext(context.getModuleName(), null) : getCallerContext(); return new ReactImageView( context, getDraweeControllerBuilder(), mGlobalImageLoadListener, callerContext); @@ -129,7 +129,7 @@ public void setInternal_AnalyticsTag(ReactImageView view, @Nullable String analy if (mCallerContextFactory != null) { view.updateCallerContext( mCallerContextFactory.getOrCreateCallerContext( - ((ThemedReactContext) view.getContext()).getSurfaceID(), analyticTag)); + ((ThemedReactContext) view.getContext()).getModuleName(), analyticTag)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index 68ada3dfc70627..a25658a27f2bb0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -23,6 +23,7 @@ import android.net.Uri; import android.widget.Toast; import androidx.annotation.Nullable; +import com.facebook.common.internal.Objects; import com.facebook.common.references.CloseableReference; import com.facebook.common.util.UriUtil; import com.facebook.drawee.controller.AbstractDraweeControllerBuilder; @@ -90,8 +91,10 @@ public class ReactImageView extends GenericDraweeView { private ImageResizeMethod mResizeMethod = ImageResizeMethod.AUTO; public void updateCallerContext(@Nullable Object callerContext) { - mCallerContext = callerContext; - mIsDirty = true; + if (!Objects.equal(mCallerContext, callerContext)) { + mCallerContext = callerContext; + mIsDirty = true; + } } private class RoundedCornerPostprocessor extends BasePostprocessor { @@ -229,6 +232,11 @@ public ReactImageView( } public void setShouldNotifyLoadEvents(boolean shouldNotify) { + // Skip update if shouldNotify is already in sync with the download listener + if (shouldNotify == (mDownloadListener != null)) { + return; + } + if (!shouldNotify) { mDownloadListener = null; } else { @@ -242,12 +250,18 @@ public void onProgressChange(int loaded, int total) { // TODO: Somehow get image size and convert `loaded` and `total` to image bytes. mEventDispatcher.dispatchEvent( ImageLoadEvent.createProgressEvent( - getId(), mImageSource.getSource(), loaded, total)); + UIManagerHelper.getSurfaceId(ReactImageView.this), + getId(), + mImageSource.getSource(), + loaded, + total)); } @Override public void onSubmit(String id, Object callerContext) { - mEventDispatcher.dispatchEvent(ImageLoadEvent.createLoadStartEvent(getId())); + mEventDispatcher.dispatchEvent( + ImageLoadEvent.createLoadStartEvent( + UIManagerHelper.getSurfaceId(ReactImageView.this), getId())); } @Override @@ -256,17 +270,22 @@ public void onFinalImageSet( if (imageInfo != null) { mEventDispatcher.dispatchEvent( ImageLoadEvent.createLoadEvent( + UIManagerHelper.getSurfaceId(ReactImageView.this), getId(), mImageSource.getSource(), imageInfo.getWidth(), imageInfo.getHeight())); - mEventDispatcher.dispatchEvent(ImageLoadEvent.createLoadEndEvent(getId())); + mEventDispatcher.dispatchEvent( + ImageLoadEvent.createLoadEndEvent( + UIManagerHelper.getSurfaceId(ReactImageView.this), getId())); } } @Override public void onFailure(String id, Throwable throwable) { - mEventDispatcher.dispatchEvent(ImageLoadEvent.createErrorEvent(getId(), throwable)); + mEventDispatcher.dispatchEvent( + ImageLoadEvent.createErrorEvent( + UIManagerHelper.getSurfaceId(ReactImageView.this), getId(), throwable)); } }; } @@ -295,18 +314,25 @@ public void setBackgroundColor(int backgroundColor) { } public void setBorderColor(int borderColor) { - mBorderColor = borderColor; - mIsDirty = true; + if (mBorderColor != borderColor) { + mBorderColor = borderColor; + mIsDirty = true; + } } public void setOverlayColor(int overlayColor) { - mOverlayColor = overlayColor; - mIsDirty = true; + if (mOverlayColor != overlayColor) { + mOverlayColor = overlayColor; + mIsDirty = true; + } } public void setBorderWidth(float borderWidth) { - mBorderWidth = PixelUtil.toPixelFromDIP(borderWidth); - mIsDirty = true; + float newBorderWidth = PixelUtil.toPixelFromDIP(borderWidth); + if (!FloatUtil.floatsEqual(mBorderWidth, newBorderWidth)) { + mBorderWidth = newBorderWidth; + mIsDirty = true; + } } public void setBorderRadius(float borderRadius) { @@ -329,32 +355,39 @@ public void setBorderRadius(float borderRadius, int position) { } public void setScaleType(ScalingUtils.ScaleType scaleType) { - mScaleType = scaleType; - mIsDirty = true; + if (mScaleType != scaleType) { + mScaleType = scaleType; + mIsDirty = true; + } } public void setTileMode(Shader.TileMode tileMode) { - mTileMode = tileMode; - mIsDirty = true; + if (mTileMode != tileMode) { + mTileMode = tileMode; + mIsDirty = true; + } } public void setResizeMethod(ImageResizeMethod resizeMethod) { - mResizeMethod = resizeMethod; - mIsDirty = true; + if (mResizeMethod != resizeMethod) { + mResizeMethod = resizeMethod; + mIsDirty = true; + } } public void setSource(@Nullable ReadableArray sources) { - mSources.clear(); + List tmpSources = new LinkedList<>(); + if (sources == null || sources.size() == 0) { ImageSource imageSource = new ImageSource(getContext(), REMOTE_TRANSPARENT_BITMAP_URI); - mSources.add(imageSource); + tmpSources.add(imageSource); } else { // Optimize for the case where we have just one uri, case in which we don't need the sizes if (sources.size() == 1) { ReadableMap source = sources.getMap(0); String uri = source.getString("uri"); ImageSource imageSource = new ImageSource(getContext(), uri); - mSources.add(imageSource); + tmpSources.add(imageSource); if (Uri.EMPTY.equals(imageSource.getUri())) { warnImageSource(uri); } @@ -365,28 +398,44 @@ public void setSource(@Nullable ReadableArray sources) { ImageSource imageSource = new ImageSource( getContext(), uri, source.getDouble("width"), source.getDouble("height")); - mSources.add(imageSource); + tmpSources.add(imageSource); if (Uri.EMPTY.equals(imageSource.getUri())) { warnImageSource(uri); } } } } + + // Don't reset sources and dirty node if sources haven't changed + if (mSources.equals(tmpSources)) { + return; + } + + mSources.clear(); + for (ImageSource src : tmpSources) { + mSources.add(src); + } mIsDirty = true; } public void setDefaultSource(@Nullable String name) { - mDefaultImageDrawable = + Drawable newDefaultDrawable = ResourceDrawableIdHelper.getInstance().getResourceDrawable(getContext(), name); - mIsDirty = true; + if (!Objects.equal(mDefaultImageDrawable, newDefaultDrawable)) { + mDefaultImageDrawable = newDefaultDrawable; + mIsDirty = true; + } } public void setLoadingIndicatorSource(@Nullable String name) { Drawable drawable = ResourceDrawableIdHelper.getInstance().getResourceDrawable(getContext(), name); - mLoadingImageDrawable = + Drawable newLoadingIndicatorSource = drawable != null ? (Drawable) new AutoRotateDrawable(drawable, 1000) : null; - mIsDirty = true; + if (!Objects.equal(mLoadingImageDrawable, newLoadingIndicatorSource)) { + mLoadingImageDrawable = newLoadingIndicatorSource; + mIsDirty = true; + } } public void setProgressiveRenderingEnabled(boolean enabled) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK index 4e9cafe129a021..3776c3389f849f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/BUCK @@ -6,6 +6,7 @@ rn_android_library( ["*.java"], exclude = ["MultiSourceHelper.java"], ), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -21,6 +22,7 @@ rn_android_library( rn_android_library( name = "withmultisource", srcs = ["MultiSourceHelper.java"], + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java index 9f95b5bae9af05..065ebbe636682f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ImageSource.java @@ -11,6 +11,7 @@ import android.net.Uri; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Assertions; +import java.util.Objects; /** Class describing an image source (network URI or resource) and size. */ public class ImageSource { @@ -29,6 +30,22 @@ public ImageSource(Context context, String source, double width, double height) mUri = computeUri(context); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ImageSource that = (ImageSource) o; + return Double.compare(that.mSize, mSize) == 0 + && isResource == that.isResource + && Objects.equals(mUri, that.mUri) + && Objects.equals(mSource, that.mSource); + } + + @Override + public int hashCode() { + return Objects.hash(mUri, mSource, mSize, isResource); + } + public ImageSource(Context context, String source) { this(context, source, 0.0d, 0.0d); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK index 53e6a5a987f584..73cedfd484bba5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "modal", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -16,6 +17,7 @@ rn_android_library( YOGA_TARGET, react_native_dep("third-party/java/infer-annotations:infer-annotations"), react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), react_native_target("java/com/facebook/react/bridge:bridge"), react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), @@ -24,7 +26,6 @@ rn_android_library( react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), react_native_target("java/com/facebook/react/views/common:common"), react_native_target("java/com/facebook/react/views/view:view"), - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), react_native_target("res:modal"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java index 35e1f8b27422bf..e10cb5cd33f494 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.java @@ -104,7 +104,8 @@ public void setSupportedOrientations(ReactModalHostView view, @Nullable Readable public void setIdentifier(ReactModalHostView view, int value) {} @Override - protected void addEventEmitters(ThemedReactContext reactContext, final ReactModalHostView view) { + protected void addEventEmitters( + final ThemedReactContext reactContext, final ReactModalHostView view) { final EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId()); if (dispatcher != null) { @@ -112,16 +113,19 @@ protected void addEventEmitters(ThemedReactContext reactContext, final ReactModa new ReactModalHostView.OnRequestCloseListener() { @Override public void onRequestClose(DialogInterface dialog) { - dispatcher.dispatchEvent(new RequestCloseEvent(view.getId())); + dispatcher.dispatchEvent( + new RequestCloseEvent(UIManagerHelper.getSurfaceId(reactContext), view.getId())); } }); view.setOnShowListener( new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { - dispatcher.dispatchEvent(new ShowEvent(view.getId())); + dispatcher.dispatchEvent( + new ShowEvent(UIManagerHelper.getSurfaceId(reactContext), view.getId())); } }); + view.setEventDispatcher(dispatcher); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java index d1bdd2f6faa595..db03bfac47ad45 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java @@ -202,6 +202,10 @@ protected void setHardwareAccelerated(boolean hardwareAccelerated) { mPropertyRequiresNewDialog = true; } + void setEventDispatcher(EventDispatcher eventDispatcher) { + mHostView.setEventDispatcher(eventDispatcher); + } + @Override public void onHostResume() { // We show the dialog again when the host resumes @@ -393,6 +397,7 @@ static class DialogRootViewGroup extends ReactViewGroup private boolean hasAdjustedSize = false; private int viewWidth; private int viewHeight; + private EventDispatcher mEventDispatcher; private final FabricViewStateManager mFabricViewStateManager = new FabricViewStateManager(); @@ -402,6 +407,10 @@ public DialogRootViewGroup(Context context) { super(context); } + private void setEventDispatcher(EventDispatcher eventDispatcher) { + mEventDispatcher = eventDispatcher; + } + @Override protected void onSizeChanged(final int w, final int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); @@ -494,13 +503,13 @@ private ReactContext getReactContext() { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher()); + mJSTouchDispatcher.handleTouchEvent(event, mEventDispatcher); return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { - mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher()); + mJSTouchDispatcher.handleTouchEvent(event, mEventDispatcher); super.onTouchEvent(event); // In case when there is no children interested in handling touch event, we return true from // the root view in order to receive subsequent events related to that gesture @@ -509,7 +518,7 @@ public boolean onTouchEvent(MotionEvent event) { @Override public void onChildStartedNativeGesture(MotionEvent androidEvent) { - mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, getEventDispatcher()); + mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, mEventDispatcher); } @Override @@ -518,11 +527,6 @@ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { // even when some other view disallow that } - private EventDispatcher getEventDispatcher() { - ReactContext reactContext = getReactContext(); - return reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - } - @Override public FabricViewStateManager getFabricViewStateManager() { return mFabricViewStateManager; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/RequestCloseEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/RequestCloseEvent.java index ba01778ed67a76..aa8ed464e570a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/RequestCloseEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/RequestCloseEvent.java @@ -7,16 +7,23 @@ package com.facebook.react.views.modal; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** {@link Event} for dismissing a Dialog. */ /* package */ class RequestCloseEvent extends Event { public static final String EVENT_NAME = "topRequestClose"; + @Deprecated protected RequestCloseEvent(int viewTag) { - super(viewTag); + this(-1, viewTag); + } + + protected RequestCloseEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); } @Override @@ -24,8 +31,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), null); + protected WritableMap getEventData() { + return Arguments.createMap(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ShowEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ShowEvent.java index cccbd347668627..1f126db46830dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ShowEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ShowEvent.java @@ -7,16 +7,23 @@ package com.facebook.react.views.modal; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** {@link Event} for showing a Dialog. */ /* package */ class ShowEvent extends Event { public static final String EVENT_NAME = "topShow"; + @Deprecated protected ShowEvent(int viewTag) { - super(viewTag); + this(-1, viewTag); + } + + protected ShowEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); } @Override @@ -24,8 +31,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), null); + protected WritableMap getEventData() { + return Arguments.createMap(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK index 00b41242092acb..3cc6179ada7bb7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "picker", srcs = glob(["**/*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDropdownPickerManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDropdownPickerManager.java index 23f4163cb74b5a..04b3f3d341d69d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDropdownPickerManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDropdownPickerManager.java @@ -8,6 +8,7 @@ package com.facebook.react.views.picker; import android.widget.Spinner; +import androidx.annotation.NonNull; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewManagerDelegate; @@ -41,4 +42,9 @@ protected ReactPicker createViewInstance(ThemedReactContext reactContext) { protected ViewManagerDelegate getDelegate() { return mDelegate; } + + @Override + public void setBackgroundColor(@NonNull ReactPicker view, int backgroundColor) { + view.setStagedBackgroundColor(backgroundColor); + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java index c629f26a461642..8eff2dd4f7bf26 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java @@ -8,12 +8,14 @@ package com.facebook.react.views.picker; import android.content.Context; +import android.content.res.ColorStateList; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; import android.widget.Spinner; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatSpinner; +import androidx.core.view.ViewCompat; import com.facebook.react.common.annotations.VisibleForTesting; import java.util.List; @@ -173,6 +175,7 @@ public OnSelectListener getOnSelectListener() { && adapter != null && mStagedPrimaryTextColor != adapter.getPrimaryTextColor()) { adapter.setPrimaryTextColor(mStagedPrimaryTextColor); + ViewCompat.setBackgroundTintList(this, ColorStateList.valueOf(mStagedPrimaryTextColor)); mStagedPrimaryTextColor = null; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java index e5c42e059905e6..3927dc86d37e03 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java @@ -13,7 +13,7 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.EventDispatcher; @@ -62,13 +62,9 @@ protected void onAfterUpdateTransaction(ReactPicker view) { @Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactPicker picker) { - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - - if (uiManager == null) { - return; - } - - picker.setOnSelectListener(new PickerEventEmitter(picker, uiManager.getEventDispatcher())); + picker.setOnSelectListener( + new PickerEventEmitter( + picker, UIManagerHelper.getEventDispatcherForReactTag(reactContext, picker.getId()))); } @Override @@ -95,7 +91,9 @@ public PickerEventEmitter(ReactPicker reactPicker, EventDispatcher eventDispatch @Override public void onItemSelected(int position) { - mEventDispatcher.dispatchEvent(new PickerItemSelectEvent(mReactPicker.getId(), position)); + mEventDispatcher.dispatchEvent( + new PickerItemSelectEvent( + UIManagerHelper.getSurfaceId(mReactPicker), mReactPicker.getId(), position)); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/events/PickerItemSelectEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/events/PickerItemSelectEvent.java index c64ccda134a7f6..445b0cbec38849 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/events/PickerItemSelectEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/events/PickerItemSelectEvent.java @@ -7,18 +7,23 @@ package com.facebook.react.views.picker.events; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; public class PickerItemSelectEvent extends Event { public static final String EVENT_NAME = "topSelect"; private final int mPosition; - public PickerItemSelectEvent(int id, int position) { - super(id); + @Deprecated + public PickerItemSelectEvent(int reactTag, int position) { + this(-1, reactTag, position); + } + + public PickerItemSelectEvent(int surfaceId, int reactTag, int position) { + super(surfaceId, reactTag); mPosition = position; } @@ -27,12 +32,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("position", mPosition); return eventData; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK index af7909efc1e8ee..14f9498a4be8ae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "progressbar", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -18,6 +19,6 @@ rn_android_library( react_native_target("java/com/facebook/react/module/annotations:annotations"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK index 736a73dc537560..60f607899a3a10 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "scroll", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ 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 61b1a712332a5d..80e64aa9b1edba 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 @@ -34,7 +34,6 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.ReactConstants; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PixelUtil; @@ -266,6 +265,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { int scrollToY = pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY(); reactScrollTo(scrollToX, scrollToY); + ReactScrollViewHelper.emitLayoutEvent(this); } /** @@ -545,9 +545,7 @@ public void getClippingRect(Rect outClippingRect) { @Override public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - return ReactFeatureFlags.clipChildRectsIfOverflowIsHidden - ? ReactClippingViewGroupHelper.getChildVisibleRectHelper(child, r, offset, this, mOverflow) - : super.getChildVisibleRect(child, r, offset); + return super.getChildVisibleRect(child, r, offset); } private int getSnapInterval() { @@ -816,7 +814,7 @@ private void flingAndSnap(int velocityX) { } // get the nearest snap points to the target offset - if (mSnapOffsets != null) { + if (mSnapOffsets != null && !mSnapOffsets.isEmpty()) { firstOffset = mSnapOffsets.get(0); lastOffset = mSnapOffsets.get(mSnapOffsets.size() - 1); 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 6497c6bce989b2..52088a86349829 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 @@ -30,7 +30,6 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.ReactConstants; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PixelUtil; @@ -223,6 +222,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { int scrollToY = pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY(); reactScrollTo(scrollToX, scrollToY); + ReactScrollViewHelper.emitLayoutEvent(this); } @Override @@ -382,9 +382,7 @@ public void getClippingRect(Rect outClippingRect) { @Override public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - return ReactFeatureFlags.clipChildRectsIfOverflowIsHidden - ? ReactClippingViewGroupHelper.getChildVisibleRectHelper(child, r, offset, this, mOverflow) - : super.getChildVisibleRect(child, r, offset); + return super.getChildVisibleRect(child, r, offset); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java index 5183f24c44bd80..b46874aaf14454 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java @@ -14,6 +14,8 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerHelper; +import java.util.ArrayList; +import java.util.List; /** Helper class that deals with emitting Scroll Events. */ public class ReactScrollViewHelper { @@ -23,6 +25,16 @@ public class ReactScrollViewHelper { public static final String AUTO = "auto"; public static final String OVER_SCROLL_NEVER = "never"; + public interface ScrollListener { + void onScroll( + ViewGroup scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity); + + void onLayout(ViewGroup scrollView); + } + + // Support global native listeners for scroll events + private static List sScrollListeners = new ArrayList<>(); + // If all else fails, this is the hardcoded value in OverScroller.java, in AOSP. // The default is defined here (as of this diff): // https://android.googlesource.com/platform/frameworks/base/+/ae5bcf23b5f0875e455790d6af387184dbd009c1/core/java/android/widget/OverScroller.java#44 @@ -64,10 +76,16 @@ private static void emitScrollEvent( return; } + for (ScrollListener scrollListener : sScrollListeners) { + scrollListener.onScroll(scrollView, scrollEventType, xVelocity, yVelocity); + } + ReactContext reactContext = (ReactContext) scrollView.getContext(); + int surfaceId = UIManagerHelper.getSurfaceId(reactContext); UIManagerHelper.getEventDispatcherForReactTag(reactContext, scrollView.getId()) .dispatchEvent( ScrollEvent.obtain( + surfaceId, scrollView.getId(), scrollEventType, scrollView.getScrollX(), @@ -80,6 +98,13 @@ private static void emitScrollEvent( scrollView.getHeight())); } + /** This is only for Java listeners. onLayout events emitted to JS are handled elsewhere. */ + public static void emitLayoutEvent(ViewGroup scrollView) { + for (ScrollListener scrollListener : sScrollListeners) { + scrollListener.onLayout(scrollView); + } + } + public static int parseOverScrollMode(String jsOverScrollMode) { if (jsOverScrollMode == null || jsOverScrollMode.equals(AUTO)) { return View.OVER_SCROLL_IF_CONTENT_SCROLLS; @@ -130,4 +155,12 @@ public void startScroll(int startX, int startY, int dx, int dy, int duration) { mScrollAnimationDuration = duration; } } + + public static void addScrollListener(ScrollListener listener) { + sScrollListeners.add(listener); + } + + public static void removeScrollListener(ScrollListener listener) { + sScrollListeners.remove(listener); + } } 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 23ad78a5a880a8..c9733b096970ac 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 @@ -305,7 +305,7 @@ public void setFadingEdgeLength(ReactScrollView view, int value) { } } - @ReactProp(name = "contentOffset") + @ReactProp(name = "contentOffset", customType = "Point") public void setContentOffset(ReactScrollView view, ReadableMap value) { if (value != null) { double x = value.hasKey("x") ? value.getDouble("x") : 0; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ScrollEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ScrollEvent.java index 91876fc2e3b90e..9d4ba87d9b147c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ScrollEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ScrollEvent.java @@ -14,7 +14,6 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** A event dispatched from a ScrollView scrolling. */ public class ScrollEvent extends Event { @@ -32,6 +31,7 @@ public class ScrollEvent extends Event { private int mScrollViewHeight; private @Nullable ScrollEventType mScrollEventType; + @Deprecated public static ScrollEvent obtain( int viewTag, ScrollEventType scrollEventType, @@ -43,11 +43,38 @@ public static ScrollEvent obtain( int contentHeight, int scrollViewWidth, int scrollViewHeight) { + return obtain( + -1, + viewTag, + scrollEventType, + scrollX, + scrollY, + xVelocity, + yVelocity, + contentWidth, + contentHeight, + scrollViewWidth, + scrollViewHeight); + } + + public static ScrollEvent obtain( + int surfaceId, + int viewTag, + ScrollEventType scrollEventType, + int scrollX, + int scrollY, + float xVelocity, + float yVelocity, + int contentWidth, + int contentHeight, + int scrollViewWidth, + int scrollViewHeight) { ScrollEvent event = EVENTS_POOL.acquire(); if (event == null) { event = new ScrollEvent(); } event.init( + surfaceId, viewTag, scrollEventType, scrollX, @@ -69,6 +96,7 @@ public void onDispose() { private ScrollEvent() {} private void init( + int surfaceId, int viewTag, ScrollEventType scrollEventType, int scrollX, @@ -79,7 +107,7 @@ private void init( int contentHeight, int scrollViewWidth, int scrollViewHeight) { - super.init(viewTag); + super.init(surfaceId, viewTag); mScrollEventType = scrollEventType; mScrollX = scrollX; mScrollY = scrollY; @@ -111,12 +139,9 @@ public boolean canCoalesce() { return false; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap contentInset = Arguments.createMap(); contentInset.putDouble("top", 0); contentInset.putDouble("bottom", 0); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK index 63f1658e470b6f..8568b1101e6942 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "slider", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ @@ -21,6 +22,6 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java index 9c8bc9ced0bca5..3d7d8fdec04815 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java @@ -26,10 +26,11 @@ import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewManagerDelegate; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.viewmanagers.SliderManagerDelegate; import com.facebook.react.viewmanagers.SliderManagerInterface; import com.facebook.yoga.YogaMeasureFunction; @@ -95,16 +96,13 @@ public long measure( @Override public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) { ReactContext reactContext = (ReactContext) seekbar.getContext(); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - - if (uiManager != null) { - uiManager - .getEventDispatcher() - .dispatchEvent( - new ReactSliderEvent( - seekbar.getId(), - ((ReactSlider) seekbar).toRealProgress(progress), - fromUser)); + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(reactContext, seekbar.getId()); + + if (eventDispatcher != null) { + eventDispatcher.dispatchEvent( + new ReactSliderEvent( + seekbar.getId(), ((ReactSlider) seekbar).toRealProgress(progress), fromUser)); } } @@ -114,15 +112,15 @@ public void onStartTrackingTouch(SeekBar seekbar) {} @Override public void onStopTrackingTouch(SeekBar seekbar) { ReactContext reactContext = (ReactContext) seekbar.getContext(); - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - - if (uiManager != null) { - uiManager - .getEventDispatcher() - .dispatchEvent( - new ReactSlidingCompleteEvent( - seekbar.getId(), - ((ReactSlider) seekbar).toRealProgress(seekbar.getProgress()))); + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(reactContext, seekbar.getId()); + + if (eventDispatcher != null) { + eventDispatcher.dispatchEvent( + new ReactSlidingCompleteEvent( + UIManagerHelper.getSurfaceId(seekbar), + seekbar.getId(), + ((ReactSlider) seekbar).toRealProgress(seekbar.getProgress()))); } } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSlidingCompleteEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSlidingCompleteEvent.java index 2e2e9470707a8e..075fd7b46e8a37 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSlidingCompleteEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSlidingCompleteEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.slider; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted when the user finishes dragging the slider. */ public class ReactSlidingCompleteEvent extends Event { @@ -19,8 +19,13 @@ public class ReactSlidingCompleteEvent extends Event private final double mValue; + @Deprecated public ReactSlidingCompleteEvent(int viewId, double value) { - super(viewId); + this(-1, viewId, value); + } + + public ReactSlidingCompleteEvent(int surfaceId, int viewId, double value) { + super(surfaceId, viewId); mValue = value; } @@ -33,6 +38,15 @@ public String getEventName() { return EVENT_NAME; } + @Nullable + @Override + protected WritableMap getEventData() { + WritableMap eventData = Arguments.createMap(); + eventData.putInt("target", getViewTag()); + eventData.putDouble("value", getValue()); + return eventData; + } + @Override public short getCoalescingKey() { return 0; @@ -42,16 +56,4 @@ public short getCoalescingKey() { public boolean canCoalesce() { return false; } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { - WritableMap eventData = Arguments.createMap(); - eventData.putInt("target", getViewTag()); - eventData.putDouble("value", getValue()); - return eventData; - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK index 528c4af8a55056..1209f9a3f38ae0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "swiperefresh", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -25,6 +26,6 @@ rn_android_library( react_native_target("java/com/facebook/react/views/scroll:scroll"), ], exported_deps = [ - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/RefreshEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/RefreshEvent.java index ca012572e71dbb..85d23cff992d53 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/RefreshEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/RefreshEvent.java @@ -7,13 +7,20 @@ package com.facebook.react.views.swiperefresh; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; public class RefreshEvent extends Event { + @Deprecated protected RefreshEvent(int viewTag) { - super(viewTag); + this(-1, viewTag); + } + + protected RefreshEvent(int surfaceId, int viewTag) { + super(surfaceId, viewTag); } @Override @@ -21,8 +28,9 @@ public String getEventName() { return "topRefresh"; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), null); + protected WritableMap getEventData() { + return Arguments.createMap(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java index c8462a138ccdc5..888c7d8c0a308c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager.java @@ -88,11 +88,21 @@ public void setProgressBackgroundColor(ReactSwipeRefreshLayout view, Integer col } // TODO(T46143833): Remove this method once the 'size' prop has been migrated to String in JS. - @Override public void setSize(ReactSwipeRefreshLayout view, int value) { view.setSize(value); } + @Override + public void setSize(ReactSwipeRefreshLayout view, String size) { + if (size == null || size.equals("default")) { + view.setSize(SwipeRefreshLayout.DEFAULT); + } else if (size.equals("large")) { + view.setSize(SwipeRefreshLayout.LARGE); + } else { + throw new IllegalArgumentException("Size must be 'default' or 'large', received: " + size); + } + } + // This prop temporarily takes both 0 and 1 as well as 'default' and 'large'. // 0 and 1 are deprecated and will be removed in a future release. // See T46143833 @@ -103,15 +113,7 @@ public void setSize(ReactSwipeRefreshLayout view, Dynamic size) { } else if (size.getType() == ReadableType.Number) { view.setSize(size.asInt()); } else if (size.getType() == ReadableType.String) { - final String sizeStr = size.asString(); - if (sizeStr.equals("default")) { - view.setSize(SwipeRefreshLayout.DEFAULT); - } else if (sizeStr.equals("large")) { - view.setSize(SwipeRefreshLayout.LARGE); - } else { - throw new IllegalArgumentException( - "Size must be 'default' or 'large', received: " + sizeStr); - } + setSize(view, size.asString()); } else { throw new IllegalArgumentException("Size must be 'default' or 'large'"); } @@ -144,7 +146,8 @@ public void onRefresh() { EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId()); if (eventDispatcher != null) { - eventDispatcher.dispatchEvent(new RefreshEvent(view.getId())); + eventDispatcher.dispatchEvent( + new RefreshEvent(UIManagerHelper.getSurfaceId(view), view.getId())); } } }); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK index cd59cc2b720430..9d6bbcad36a0da 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/BUCK @@ -1,8 +1,9 @@ -load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library") +load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library") rn_android_library( name = "switchview", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ @@ -23,6 +24,6 @@ rn_android_library( react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), - react_native_target("java/com/facebook/react/viewmanagers:viewmanagers"), + react_native_root_target("Libraries:generated_components_java-FBReactNativeComponentSpec"), ], ) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchEvent.java index 9cc34d0e43951a..38d0a76c91e210 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.switchview; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by a ReactSwitchManager once a switch is fully switched on/off */ /*package*/ class ReactSwitchEvent extends Event { @@ -19,8 +19,13 @@ private final boolean mIsChecked; + @Deprecated public ReactSwitchEvent(int viewId, boolean isChecked) { - super(viewId); + this(-1, viewId, isChecked); + } + + public ReactSwitchEvent(int surfaceId, int viewId, boolean isChecked) { + super(surfaceId, viewId); mIsChecked = isChecked; } @@ -33,21 +38,18 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public short getCoalescingKey() { - // All switch events for a given view can be coalesced. - return 0; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("target", getViewTag()); eventData.putBoolean("value", getIsChecked()); return eventData; } + + @Override + public short getCoalescingKey() { + // All switch events for a given view can be coalesced. + return 0; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java index c2196f3ff142dc..e1a20562ae1032 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/switchview/ReactSwitchManager.java @@ -20,6 +20,7 @@ import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManagerDelegate; import com.facebook.react.uimanager.ViewProps; @@ -89,7 +90,9 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { uiManager .getEventDispatcher() - .dispatchEvent(new ReactSwitchEvent(buttonView.getId(), isChecked)); + .dispatchEvent( + new ReactSwitchEvent( + UIManagerHelper.getSurfaceId(reactContext), buttonView.getId(), isChecked)); } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK index ac69e03c258350..49b14f8a7176a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "text", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan.java index 9959bea4b828f1..0c8208468badce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomLineHeightSpan.java @@ -17,7 +17,7 @@ public class CustomLineHeightSpan implements LineHeightSpan, ReactSpan { private final int mHeight; - CustomLineHeightSpan(float height) { + public CustomLineHeightSpan(float height) { this.mHeight = (int) Math.ceil(height); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java index 1becdbacaf63d9..cf0c8b141b0073 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/CustomStyleSpan.java @@ -10,7 +10,6 @@ import android.content.res.AssetManager; import android.graphics.Paint; import android.graphics.Typeface; -import android.os.Build; import android.text.TextPaint; import android.text.style.MetricAffectingSpan; import androidx.annotation.NonNull; @@ -83,9 +82,7 @@ private static void apply( AssetManager assetManager) { Typeface typeface = ReactTypefaceUtils.applyStyles(paint.getTypeface(), style, weight, family, assetManager); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - paint.setFontFeatureSettings(fontFeatureSettings); - } + paint.setFontFeatureSettings(fontFeatureSettings); paint.setTypeface(typeface); paint.setSubpixelText(true); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java index 6835918b587d54..f685bf567b2455 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java @@ -178,15 +178,12 @@ private static void buildSpannedFromShadowNode( new SetSpanOperation( start, end, new ReactBackgroundColorSpan(textShadowNode.mBackgroundColor))); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - float effectiveLetterSpacing = textAttributes.getEffectiveLetterSpacing(); - if (!Float.isNaN(effectiveLetterSpacing) - && (parentTextAttributes == null - || parentTextAttributes.getEffectiveLetterSpacing() != effectiveLetterSpacing)) { - ops.add( - new SetSpanOperation( - start, end, new CustomLetterSpacingSpan(effectiveLetterSpacing))); - } + float effectiveLetterSpacing = textAttributes.getEffectiveLetterSpacing(); + if (!Float.isNaN(effectiveLetterSpacing) + && (parentTextAttributes == null + || parentTextAttributes.getEffectiveLetterSpacing() != effectiveLetterSpacing)) { + ops.add( + new SetSpanOperation(start, end, new CustomLetterSpacingSpan(effectiveLetterSpacing))); } int effectiveFontSize = textAttributes.getEffectiveFontSize(); if ( // `getEffectiveFontSize` always returns a value so don't need to check for anything like diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactClickableSpan.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactClickableSpan.java new file mode 100644 index 00000000000000..bb093d2691ddca --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactClickableSpan.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.views.text; + +import android.text.TextPaint; +import android.text.style.ClickableSpan; +import android.view.View; +import androidx.annotation.NonNull; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.uimanager.UIManagerHelper; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.view.ViewGroupClickEvent; + +/** + * This class is used in {@link TextLayoutManager} to linkify and style a span of text with + * accessibilityRole="link". This is needed to make nested Text components accessible. + * + *

For example, if your React component looks like this: + * + *

{@code
+ * 
+ *   Some text with
+ *   a link
+ *   in the middle.
+ * 
+ * }
+ * + * then only one {@link ReactTextView} will be created, for the parent. The child Text component + * does not exist as a native view, and therefore has no accessibility properties. Instead, we have + * to use spans on the parent's {@link ReactTextView} to properly style the child, and to make it + * accessible (TalkBack announces that the text has links available, and the links are exposed in + * the context menu). + */ +class ReactClickableSpan extends ClickableSpan implements ReactSpan { + + private final int mReactTag; + private final int mForegroundColor; + + ReactClickableSpan(int reactTag, int foregroundColor) { + mReactTag = reactTag; + mForegroundColor = foregroundColor; + } + + @Override + public void onClick(@NonNull View view) { + ReactContext context = (ReactContext) view.getContext(); + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(context, mReactTag); + if (eventDispatcher != null) { + eventDispatcher.dispatchEvent( + new ViewGroupClickEvent(UIManagerHelper.getSurfaceId(context), mReactTag)); + } + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + ds.setColor(mForegroundColor); + ds.setUnderlineText(false); + } + + public int getReactTag() { + return mReactTag; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java index ac84caae1e07d9..5dbd0796e53363 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java @@ -144,6 +144,9 @@ public long measure( } } + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.Q) { + layoutWidth = (float) Math.ceil(layoutWidth); + } float layoutHeight = height; if (heightMode != YogaMeasureMode.EXACTLY) { layoutHeight = layout.getLineBottom(lineCount - 1); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java index 31a1139b697a76..7400b1df909e86 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextUpdate.java @@ -11,8 +11,6 @@ import android.text.Layout; import android.text.Spannable; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.ReadableMap; /** * Class that contains the data needed for a text update. Used by both and @@ -33,7 +31,7 @@ public class ReactTextUpdate { private final int mSelectionEnd; private final int mJustificationMode; - public @Nullable ReadableMap mAttributedString = null; + public boolean mContainsMultipleFragments; /** * @deprecated Use a non-deprecated constructor for ReactTextUpdate instead. This one remains @@ -145,14 +143,13 @@ public static ReactTextUpdate buildReactTextUpdateFromState( int textAlign, int textBreakStrategy, int justificationMode, - ReadableMap attributedString) { + boolean containsMultipleFragments) { - ReactTextUpdate textUpdate = + ReactTextUpdate reactTextUpdate = new ReactTextUpdate( text, jsEventCounter, false, textAlign, textBreakStrategy, justificationMode); - - textUpdate.mAttributedString = attributedString; - return textUpdate; + reactTextUpdate.mContainsMultipleFragments = containsMultipleFragments; + return reactTextUpdate; } public Spannable getText() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 29e3e2969fb879..f99e24019e5236 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -17,6 +17,7 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaDirection; @@ -72,6 +73,9 @@ public class TextAttributeProps { protected boolean mIsLineThroughTextDecorationSet = false; protected boolean mIncludeFontPadding = true; + protected @Nullable ReactAccessibilityDelegate.AccessibilityRole mAccessibilityRole = null; + protected boolean mIsAccessibilityRoleSet = false; + /** * mFontStyle can be {@link Typeface#NORMAL} or {@link Typeface#ITALIC}. mFontWeight can be {@link * Typeface#NORMAL} or {@link Typeface#BOLD}. @@ -134,6 +138,7 @@ public TextAttributeProps(ReactStylesDiffMap props) { setTextShadowColor(getIntProp(PROP_SHADOW_COLOR, DEFAULT_TEXT_SHADOW_COLOR)); setTextTransform(getStringProp(PROP_TEXT_TRANSFORM)); setLayoutDirection(getStringProp(ViewProps.LAYOUT_DIRECTION)); + setAccessibilityRole(getStringProp(ViewProps.ACCESSIBILITY_ROLE)); } public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) { @@ -412,6 +417,14 @@ public void setTextTransform(@Nullable String textTransform) { } } + public void setAccessibilityRole(@Nullable String accessibilityRole) { + if (accessibilityRole != null) { + mIsAccessibilityRoleSet = accessibilityRole != null; + mAccessibilityRole = + ReactAccessibilityDelegate.AccessibilityRole.fromValue(accessibilityRole); + } + } + public static int getTextBreakStrategy(@Nullable String textBreakStrategy) { int androidTextBreakStrategy = DEFAULT_BREAK_STRATEGY; if (textBreakStrategy != null) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index b9ec0233d8a3ef..c2f428075f451d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -27,8 +27,10 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableNativeMap; -import com.facebook.react.config.ReactFeatureFlags; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaConstants; @@ -42,9 +44,9 @@ public class TextLayoutManager { // TODO T67606397: Refactor configuration of fabric logs - private static final boolean ENABLE_MEASURE_LOGGING = false; + private static final boolean ENABLE_MEASURE_LOGGING = ReactBuildConfig.DEBUG && false; - private static final String TAG = "TextLayoutManager"; + private static final String TAG = TextLayoutManager.class.getSimpleName(); // It's important to pass the ANTI_ALIAS_FLAG flag to the constructor rather than setting it // later by calling setFlags. This is because the latter approach triggers a bug on Android 4.4.2. @@ -61,9 +63,7 @@ public class TextLayoutManager { private static final String INCLUDE_FONT_PADDING_KEY = "includeFontPadding"; private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy"; private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines"; - private static final LruCache sSpannableCache = - new LruCache<>(spannableCacheSize); - private static final LruCache sSpannableCacheV2 = + private static final LruCache sSpannableCache = new LruCache<>(spannableCacheSize); private static final ConcurrentHashMap sTagToSpannableCache = new ConcurrentHashMap<>(); @@ -80,10 +80,16 @@ public static boolean isRTL(ReadableMap attributedString) { } public static void setCachedSpannabledForTag(int reactTag, @NonNull Spannable sp) { + if (ENABLE_MEASURE_LOGGING) { + FLog.e(TAG, "Set cached spannable for tag[" + reactTag + "]: " + sp.toString()); + } sTagToSpannableCache.put(reactTag, sp); } public static void deleteCachedSpannableForTag(int reactTag) { + if (ENABLE_MEASURE_LOGGING) { + FLog.e(TAG, "Delete cached spannable for tag[" + reactTag + "]"); + } sTagToSpannableCache.remove(reactTag); } @@ -115,7 +121,12 @@ private static void buildSpannableFromFragment( sb.length(), new TextInlineViewPlaceholderSpan(reactTag, (int) width, (int) height))); } else if (end >= start) { - if (textAttributes.mIsColorSet) { + if (ReactAccessibilityDelegate.AccessibilityRole.LINK.equals( + textAttributes.mAccessibilityRole)) { + ops.add( + new SetSpanOperation( + start, end, new ReactClickableSpan(reactTag, textAttributes.mColor))); + } else if (textAttributes.mIsColorSet) { ops.add( new SetSpanOperation( start, end, new ReactForegroundColorSpan(textAttributes.mColor))); @@ -125,12 +136,10 @@ private static void buildSpannableFromFragment( new SetSpanOperation( start, end, new ReactBackgroundColorSpan(textAttributes.mBackgroundColor))); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (!Float.isNaN(textAttributes.getLetterSpacing())) { - ops.add( - new SetSpanOperation( - start, end, new CustomLetterSpacingSpan(textAttributes.getLetterSpacing()))); - } + if (!Float.isNaN(textAttributes.getLetterSpacing())) { + ops.add( + new SetSpanOperation( + start, end, new CustomLetterSpacingSpan(textAttributes.getLetterSpacing()))); } ops.add( new SetSpanOperation(start, end, new ReactAbsoluteSizeSpan(textAttributes.mFontSize))); @@ -183,25 +192,11 @@ public static Spannable getOrCreateSpannableForText( @Nullable ReactTextViewManagerCallback reactTextViewManagerCallback) { Spannable preparedSpannableText; - String attributedStringPayload = ""; - - boolean cacheByReadableNativeMap = - ReactFeatureFlags.enableSpannableCacheByReadableNativeMapEquality; - // TODO: T74600554 Cleanup this experiment once positive impact is confirmed in production - if (cacheByReadableNativeMap) { - synchronized (sSpannableCacheLock) { - preparedSpannableText = sSpannableCacheV2.get((ReadableNativeMap) attributedString); - if (preparedSpannableText != null) { - return preparedSpannableText; - } - } - } else { - attributedStringPayload = attributedString.toString(); - synchronized (sSpannableCacheLock) { - preparedSpannableText = sSpannableCache.get(attributedStringPayload); - if (preparedSpannableText != null) { - return preparedSpannableText; - } + + synchronized (sSpannableCacheLock) { + preparedSpannableText = sSpannableCache.get((ReadableNativeMap) attributedString); + if (preparedSpannableText != null) { + return preparedSpannableText; } } @@ -209,15 +204,10 @@ public static Spannable getOrCreateSpannableForText( createSpannableFromAttributedString( context, attributedString, reactTextViewManagerCallback); - if (cacheByReadableNativeMap) { - synchronized (sSpannableCacheLock) { - sSpannableCacheV2.put((ReadableNativeMap) attributedString, preparedSpannableText); - } - } else { - synchronized (sSpannableCacheLock) { - sSpannableCache.put(attributedStringPayload, preparedSpannableText); - } + synchronized (sSpannableCacheLock) { + sSpannableCache.put((ReadableNativeMap) attributedString, preparedSpannableText); } + return preparedSpannableText; } @@ -251,51 +241,19 @@ private static Spannable createSpannableFromAttributedString( return sb; } - public static long measureText( - Context context, - ReadableMap attributedString, - ReadableMap paragraphAttributes, + private static Layout createLayout( + Spannable text, + BoringLayout.Metrics boring, float width, YogaMeasureMode widthYogaMeasureMode, - float height, - YogaMeasureMode heightYogaMeasureMode, - ReactTextViewManagerCallback reactTextViewManagerCallback, - @Nullable float[] attachmentsPositions) { - - // TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic) + boolean includeFontPadding, + int textBreakStrategy) { + Layout layout; + int spanLength = text.length(); + boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0; TextPaint textPaint = sTextPaintInstance; - Spannable text; - if (attributedString.hasKey("cacheId")) { - int cacheId = attributedString.getInt("cacheId"); - if (sTagToSpannableCache.containsKey(cacheId)) { - text = sTagToSpannableCache.get(attributedString.getInt("cacheId")); - } else { - return 0; - } - } else { - text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback); - } - - int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy( - paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY)); - boolean includeFontPadding = - paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) - ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) - : DEFAULT_INCLUDE_FONT_PADDING; - - if (text == null) { - throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout"); - } - - BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint); float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN; - // technically, width should never be negative, but there is currently a bug in - boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0; - - Layout layout; - int spanLength = text.length(); if (boring == null && (unconstrainedWidth || (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) { @@ -351,17 +309,80 @@ public static long measureText( 0.f, includeFontPadding); } else { - layout = + StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, spanLength, textPaint, (int) width) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(0.f, 1.f) .setIncludePad(includeFontPadding) .setBreakStrategy(textBreakStrategy) - .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) - .build(); + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(true); + } + + layout = builder.build(); + } + } + return layout; + } + + public static long measureText( + Context context, + ReadableMap attributedString, + ReadableMap paragraphAttributes, + float width, + YogaMeasureMode widthYogaMeasureMode, + float height, + YogaMeasureMode heightYogaMeasureMode, + ReactTextViewManagerCallback reactTextViewManagerCallback, + @Nullable float[] attachmentsPositions) { + + // TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic) + TextPaint textPaint = sTextPaintInstance; + Spannable text; + if (attributedString.hasKey("cacheId")) { + int cacheId = attributedString.getInt("cacheId"); + if (ENABLE_MEASURE_LOGGING) { + FLog.e(TAG, "Get cached spannable for cacheId[" + cacheId + "]"); + } + if (sTagToSpannableCache.containsKey(cacheId)) { + text = sTagToSpannableCache.get(cacheId); + if (ENABLE_MEASURE_LOGGING) { + FLog.e(TAG, "Text for spannable found for cacheId[" + cacheId + "]: " + text.toString()); + } + } else { + if (ENABLE_MEASURE_LOGGING) { + FLog.e(TAG, "No cached spannable found for cacheId[" + cacheId + "]"); + } + return 0; } + } else { + text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback); + } + + int textBreakStrategy = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY)); + boolean includeFontPadding = + paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) + ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) + : DEFAULT_INCLUDE_FONT_PADDING; + + if (text == null) { + throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout"); } + BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint); + float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN; + + // technically, width should never be negative, but there is currently a bug in + boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0; + + Layout layout = + createLayout( + text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy); + int maximumNumberOfLines = paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY) ? paragraphAttributes.getInt(MAXIMUM_NUMBER_OF_LINES_KEY) @@ -402,9 +423,9 @@ public static long measureText( // follows a similar logic than used in pre-fabric (see ReactTextView.onLayout method). int attachmentIndex = 0; int lastAttachmentFoundInSpan; - for (int i = 0; i < spanLength; i = lastAttachmentFoundInSpan) { + for (int i = 0; i < text.length(); i = lastAttachmentFoundInSpan) { lastAttachmentFoundInSpan = - text.nextSpanTransition(i, spanLength, TextInlineViewPlaceholderSpan.class); + text.nextSpanTransition(i, text.length(), TextInlineViewPlaceholderSpan.class); TextInlineViewPlaceholderSpan[] placeholders = text.getSpans(i, lastAttachmentFoundInSpan, TextInlineViewPlaceholderSpan.class); for (TextInlineViewPlaceholderSpan placeholder : placeholders) { @@ -426,7 +447,7 @@ public static long measureText( // There's a bug on Samsung devices where calling getPrimaryHorizontal on // the last offset in the layout will result in an endless loop. Work around // this bug by avoiding getPrimaryHorizontal in that case. - if (start == spanLength - 1) { + if (start == text.length() - 1) { placeholderLeftPosition = isRtlParagraph // Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect @@ -496,18 +517,41 @@ public static long measureText( return YogaMeasureOutput.make(widthInSP, heightInSP); } + public static WritableArray measureLines( + @NonNull Context context, + ReadableMap attributedString, + ReadableMap paragraphAttributes, + float width) { + TextPaint textPaint = sTextPaintInstance; + Spannable text = getOrCreateSpannableForText(context, attributedString, null); + BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint); + + int textBreakStrategy = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY)); + boolean includeFontPadding = + paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY) + ? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY) + : DEFAULT_INCLUDE_FONT_PADDING; + + Layout layout = + createLayout( + text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy); + return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context); + } + // TODO T31905686: This class should be private public static class SetSpanOperation { protected int start, end; protected ReactSpan what; - SetSpanOperation(int start, int end, ReactSpan what) { + public SetSpanOperation(int start, int end, ReactSpan what) { this.start = start; this.end = end; this.what = what; } - public void execute(SpannableStringBuilder sb, int priority) { + public void execute(Spannable sb, int priority) { // All spans will automatically extend to the right of the text, but not the left - except // for spans that start at the beginning of the text. int spanFlags = Spannable.SPAN_EXCLUSIVE_INCLUSIVE; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK index fef31ebea6c4aa..38985bbf96b449 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "frescosupport", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK index 3b408b3d319e69..ae5cec1338544f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "textinput", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], required_for_source_only_abi = True, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactContentSizeChangedEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactContentSizeChangedEvent.java index 432347821a9a32..9d0d205a5f23bc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactContentSizeChangedEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactContentSizeChangedEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when content size changes. */ public class ReactContentSizeChangedEvent extends Event { @@ -20,8 +20,14 @@ public class ReactContentSizeChangedEvent extends Event { private float mContentWidth; private float mContentHeight; + @Deprecated public ReactContentSizeChangedEvent(int viewId, float contentSizeWidth, float contentSizeHeight) { - super(viewId); + this(-1, viewId, contentSizeWidth, contentSizeHeight); + } + + public ReactContentSizeChangedEvent( + int surfaceId, int viewId, float contentSizeWidth, float contentSizeHeight) { + super(surfaceId, viewId); mContentWidth = contentSizeWidth; mContentHeight = contentSizeHeight; } @@ -31,12 +37,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); WritableMap contentSize = Arguments.createMap(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 79f35211152662..8e1e74ab845ac7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -8,6 +8,7 @@ package com.facebook.react.views.textinput; import static com.facebook.react.uimanager.UIManagerHelper.getReactContext; +import static com.facebook.react.views.text.TextAttributeProps.UNSET; import android.content.Context; import android.graphics.Rect; @@ -17,7 +18,7 @@ import android.os.Bundle; import android.text.Editable; import android.text.InputType; -import android.text.SpannableString; +import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -37,10 +38,18 @@ import androidx.appcompat.widget.AppCompatEditText; import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; +import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReactSoftException; +import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.text.CustomLetterSpacingSpan; +import com.facebook.react.views.text.CustomLineHeightSpan; +import com.facebook.react.views.text.CustomStyleSpan; +import com.facebook.react.views.text.ReactAbsoluteSizeSpan; import com.facebook.react.views.text.ReactSpan; import com.facebook.react.views.text.ReactTextUpdate; import com.facebook.react.views.text.ReactTypefaceUtils; @@ -49,6 +58,7 @@ import com.facebook.react.views.text.TextLayoutManager; import com.facebook.react.views.view.ReactViewBackgroundManager; import java.util.ArrayList; +import java.util.List; /** * A wrapper around the EditText that lets us better control what happens when an EditText gets @@ -64,12 +74,15 @@ */ public class ReactEditText extends AppCompatEditText implements FabricViewStateManager.HasFabricViewStateManager { - private final InputMethodManager mInputMethodManager; + private final String TAG = ReactEditText.class.getSimpleName(); + public static final boolean DEBUG_MODE = ReactBuildConfig.DEBUG && false; + // This flag is set to true when we set the text of the EditText explicitly. In that case, no // *TextChanged events should be triggered. This is less expensive than removing the text // listeners and adding them back again after the text change is completed. protected boolean mIsSettingTextFromJS; + protected boolean mIsSettingTextFromCacheUpdate = false; private int mDefaultGravityHorizontal; private int mDefaultGravityVertical; @@ -107,6 +120,7 @@ public class ReactEditText extends AppCompatEditText protected boolean mIsSettingTextFromState = false; private static final KeyListener sKeyListener = QwertyKeyListener.getInstanceForFullKeyboard(); + private @Nullable EventDispatcher mEventDispatcher; public ReactEditText(Context context) { super(context); @@ -162,6 +176,9 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) { @Override protected void finalize() { + if (DEBUG_MODE) { + FLog.e(TAG, "finalize[" + getId() + "] delete cached spannable"); + } TextLayoutManager.deleteCachedSpannableForTag(getId()); } @@ -232,7 +249,8 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) { InputConnection inputConnection = super.onCreateInputConnection(outAttrs); if (inputConnection != null && mOnKeyPress) { inputConnection = - new ReactEditTextInputConnectionWrapper(inputConnection, reactContext, this); + new ReactEditTextInputConnectionWrapper( + inputConnection, reactContext, this, mEventDispatcher); } if (isMultiline() && getBlurOnSubmit()) { @@ -319,13 +337,20 @@ public void maybeSetSelection(int eventCounter, int start, int end) { @Override public void setSelection(int start, int end) { + if (DEBUG_MODE) { + FLog.e(TAG, "setSelection[" + getId() + "]: " + start + " " + end); + } super.setSelection(start, end); } @Override protected void onSelectionChanged(int selStart, int selEnd) { + if (DEBUG_MODE) { + FLog.e(TAG, "onSelectionChanged[" + getId() + "]: " + selStart + " " + selEnd); + } + super.onSelectionChanged(selStart, selEnd); - if (mSelectionWatcher != null && hasFocus()) { + if (!mIsSettingTextFromCacheUpdate && mSelectionWatcher != null && hasFocus()) { mSelectionWatcher.onSelectionChanged(selStart, selEnd); } } @@ -397,11 +422,10 @@ public String getReturnKeyType() { @Override public void setInputType(int type) { Typeface tf = super.getTypeface(); - // Input type password defaults to monospace font, so we need to re-apply the font - super.setTypeface(tf); - super.setInputType(type); mStagedInputType = type; + // Input type password defaults to monospace font, so we need to re-apply the font + super.setTypeface(tf); /** * If set forces multiline on input, because of a restriction on Android source that enables @@ -495,6 +519,17 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { return; } + if (DEBUG_MODE) { + FLog.e( + TAG, + "maybeSetText[" + + getId() + + "]: current text: " + + getText() + + " update: " + + reactTextUpdate.getText()); + } + // The current text gets replaced with the text received from JS. However, the spans on the // current text need to be adapted to the new text. Since TextView#setText() will remove or // reset some of these spans even if they are set directly, SpannableStringBuilder#replace() is @@ -502,7 +537,7 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(reactTextUpdate.getText()); - manageSpans(spannableStringBuilder); + manageSpans(spannableStringBuilder, reactTextUpdate.mContainsMultipleFragments); mContainsImages = reactTextUpdate.containsImages(); // When we update text, we trigger onChangeText code that will @@ -528,10 +563,8 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { } } - // Update cached spans (in Fabric only) - if (this.getFabricViewStateManager() != null) { - TextLayoutManager.setCachedSpannabledForTag(getId(), spannableStringBuilder); - } + // Update cached spans (in Fabric only). + updateCachedSpannable(false); } /** @@ -540,30 +573,42 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { * will adapt to the new text, hence why {@link SpannableStringBuilder#replace} never removes * them. */ - private void manageSpans(SpannableStringBuilder spannableStringBuilder) { + private void manageSpans( + SpannableStringBuilder spannableStringBuilder, boolean skipAddSpansForMeasurements) { Object[] spans = getText().getSpans(0, length(), Object.class); for (int spanIdx = 0; spanIdx < spans.length; spanIdx++) { + Object span = spans[spanIdx]; + int spanFlags = getText().getSpanFlags(span); + boolean isExclusiveExclusive = + (spanFlags & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; + // Remove all styling spans we might have previously set - if (spans[spanIdx] instanceof ReactSpan) { - getText().removeSpan(spans[spanIdx]); + if (span instanceof ReactSpan) { + getText().removeSpan(span); } - if ((getText().getSpanFlags(spans[spanIdx]) & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) - != Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) { + // We only add spans back for EXCLUSIVE_EXCLUSIVE spans + if (!isExclusiveExclusive) { continue; } - Object span = spans[spanIdx]; - final int spanStart = getText().getSpanStart(spans[spanIdx]); - final int spanEnd = getText().getSpanEnd(spans[spanIdx]); - final int spanFlags = getText().getSpanFlags(spans[spanIdx]); + + final int spanStart = getText().getSpanStart(span); + final int spanEnd = getText().getSpanEnd(span); // Make sure the span is removed from existing text, otherwise the spans we set will be // ignored or it will cover text that has changed. - getText().removeSpan(spans[spanIdx]); + getText().removeSpan(span); if (sameTextForSpan(getText(), spannableStringBuilder, spanStart, spanEnd)) { spannableStringBuilder.setSpan(span, spanStart, spanEnd, spanFlags); } } + + // In Fabric only, apply necessary styles to entire span + // If the Spannable was constructed from multiple fragments, we don't apply any spans that could + // impact the whole Spannable, because that would override "local" styles per-fragment + if (!skipAddSpansForMeasurements) { + addSpansForMeasurement(getText()); + } } private static boolean sameTextForSpan( @@ -582,6 +627,73 @@ private static boolean sameTextForSpan( return true; } + // This is hacked in for Fabric. When we delete non-Fabric code, we might be able to simplify or + // clean this up a bit. + private void addSpansForMeasurement(Spannable spannable) { + if (!mFabricViewStateManager.hasStateWrapper()) { + return; + } + + boolean originalDisableTextDiffing = mDisableTextDiffing; + mDisableTextDiffing = true; + + int start = 0; + int end = spannable.length(); + + // Remove duplicate spans we might add here + Object[] spans = spannable.getSpans(0, length(), Object.class); + for (Object span : spans) { + int spanFlags = spannable.getSpanFlags(span); + boolean isInclusive = + (spanFlags & Spanned.SPAN_INCLUSIVE_INCLUSIVE) == Spanned.SPAN_INCLUSIVE_INCLUSIVE + || (spanFlags & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) == Spanned.SPAN_INCLUSIVE_EXCLUSIVE; + if (isInclusive + && span instanceof ReactSpan + && spannable.getSpanStart(span) == start + && spannable.getSpanEnd(span) == end) { + spannable.removeSpan(span); + } + } + + List ops = new ArrayList<>(); + + if (!Float.isNaN(mTextAttributes.getLetterSpacing())) { + ops.add( + new TextLayoutManager.SetSpanOperation( + start, end, new CustomLetterSpacingSpan(mTextAttributes.getLetterSpacing()))); + } + ops.add( + new TextLayoutManager.SetSpanOperation( + start, end, new ReactAbsoluteSizeSpan((int) mTextAttributes.getEffectiveFontSize()))); + if (mFontStyle != UNSET || mFontWeight != UNSET || mFontFamily != null) { + ops.add( + new TextLayoutManager.SetSpanOperation( + start, + end, + new CustomStyleSpan( + mFontStyle, + mFontWeight, + null, // TODO: do we need to support FontFeatureSettings / fontVariant? + mFontFamily, + getReactContext(ReactEditText.this).getAssets()))); + } + if (!Float.isNaN(mTextAttributes.getEffectiveLineHeight())) { + ops.add( + new TextLayoutManager.SetSpanOperation( + start, end, new CustomLineHeightSpan(mTextAttributes.getEffectiveLineHeight()))); + } + + int priority = 0; + for (TextLayoutManager.SetSpanOperation op : ops) { + // Actual order of calling {@code execute} does NOT matter, + // but the {@code priority} DOES matter. + op.execute(spannable, priority); + priority++; + } + + mDisableTextDiffing = originalDisableTextDiffing; + } + protected boolean showSoftKeyboard() { return mInputMethodManager.showSoftInput(this, 0); } @@ -741,6 +853,13 @@ public void onStartTemporaryDetach() { @Override public void onAttachedToWindow() { super.onAttachedToWindow(); + + // Used to ensure that text is selectable inside of removeClippedSubviews + // See https://github.com/facebook/react-native/issues/6805 for original + // fix that was ported to here. + + super.setTextIsSelectable(true); + if (mContainsImages) { Spanned text = getText(); TextInlineImageSpan[] spans = text.getSpans(0, text.length(), TextInlineImageSpan.class); @@ -829,11 +948,9 @@ protected void applyTextAttributes() { // `Float.NaN`. setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextAttributes.getEffectiveFontSize()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); - if (!Float.isNaN(effectiveLetterSpacing)) { - setLetterSpacing(effectiveLetterSpacing); - } + float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing(); + if (!Float.isNaN(effectiveLetterSpacing)) { + setLetterSpacing(effectiveLetterSpacing); } } @@ -842,6 +959,97 @@ public FabricViewStateManager getFabricViewStateManager() { return mFabricViewStateManager; } + /** + * Update the cached Spannable used in TextLayoutManager to measure the text in Fabric. This is + * mostly copied from ReactTextInputShadowNode.java (the non-Fabric version) and + * TextLayoutManager.java with some very minor modifications. There's some duplication between + * here and TextLayoutManager, so there might be an opportunity for refactor. + */ + private void updateCachedSpannable(boolean resetStyles) { + // Noops in non-Fabric + if (!mFabricViewStateManager.hasStateWrapper()) { + return; + } + // If this view doesn't have an ID yet, we don't have a cache key, so bail here + if (getId() == -1) { + return; + } + + if (resetStyles) { + mIsSettingTextFromCacheUpdate = true; + addSpansForMeasurement(getText()); + mIsSettingTextFromCacheUpdate = false; + } + + Editable currentText = getText(); + boolean haveText = currentText != null && currentText.length() > 0; + + SpannableStringBuilder sb = new SpannableStringBuilder(); + + // A note of caution: appending currentText to sb appends all the spans of currentText - not + // copies of the Spans, but the actual span objects. Any modifications to sb after that point + // can modify the spans of sb/currentText, impact the text or spans visible on screen, and + // also call the TextChangeWatcher methods. + if (haveText) { + // This is here as a workaround for T76236115, which looks like this: + // Hopefully we can delete all this stuff if we can get rid of the soft errors. + // - android.text.SpannableStringBuilder.charAt (SpannableStringBuilder.java:123) + // - android.text.CharSequenceCharacterIterator.current + // (CharSequenceCharacterIterator.java:58) + // - android.text.CharSequenceCharacterIterator.setIndex + // (CharSequenceCharacterIterator.java:83) + // - android.icu.text.RuleBasedBreakIterator.CISetIndex32 (RuleBasedBreakIterator.java:1126) + // - android.icu.text.RuleBasedBreakIterator.isBoundary (RuleBasedBreakIterator.java:503) + // - android.text.method.WordIterator.isBoundary (WordIterator.java:95) + // - android.widget.Editor$SelectionHandleView.positionAtCursorOffset (Editor.java:6666) + // - android.widget.Editor$HandleView.invalidate (Editor.java:5241) + // - android.widget.Editor$SelectionModifierCursorController.invalidateHandles + // (Editor.java:7442) + // - android.widget.Editor.invalidateHandlesAndActionMode (Editor.java:2112) + // - android.widget.TextView.spanChange (TextView.java:11189) + // - android.widget.TextView$ChangeWatcher.onSpanAdded (TextView.java:14189) + // - android.text.SpannableStringBuilder.sendSpanAdded (SpannableStringBuilder.java:1283) + // - android.text.SpannableStringBuilder.sendToSpanWatchers (SpannableStringBuilder.java:663) + // - android.text.SpannableStringBuilder.replace (SpannableStringBuilder.java:579) + // - android.text.SpannableStringBuilder.append (SpannableStringBuilder.java:269) + // - ReactEditText.updateCachedSpannable (ReactEditText.java:995) + // - ReactEditText$TextWatcherDelegator.onTextChanged (ReactEditText.java:1044) + // - android.widget.TextView.sendOnTextChanged (TextView.java:10972) + // ... + // - android.text.method.BaseKeyListener.onKeyDown (BaseKeyListener.java:479) + // - android.text.method.QwertyKeyListener.onKeyDown (QwertyKeyListener.java:362) + // - ReactEditText$InternalKeyListener.onKeyDown (ReactEditText.java:1094) + // ... + // - android.app.Activity.dispatchKeyEvent (Activity.java:3447) + try { + sb.append(currentText.subSequence(0, currentText.length())); + } catch (IndexOutOfBoundsException e) { + ReactSoftException.logSoftException(TAG, e); + } + } + + // If we don't have text, make sure we have *something* to measure. + // Hint has the same dimensions - the only thing that's different is background or foreground + // color + if (!haveText) { + if (getHint() != null && getHint().length() > 0) { + sb.append(getHint()); + } else { + // Measure something so we have correct height, even if there's no string. + sb.append("I"); + } + + // Make sure that all text styles are applied when we're measurable the hint or "blank" text + addSpansForMeasurement(sb); + } + + TextLayoutManager.setCachedSpannabledForTag(getId(), sb); + } + + void setEventDispatcher(@Nullable EventDispatcher eventDispatcher) { + mEventDispatcher = eventDispatcher; + } + /** * This class will redirect *TextChanged calls to the listeners only in the case where the text is * changed by the user, and not explicitly set by JS. @@ -849,7 +1057,7 @@ public FabricViewStateManager getFabricViewStateManager() { private class TextWatcherDelegator implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - if (!mIsSettingTextFromJS && mListeners != null) { + if (!mIsSettingTextFromCacheUpdate && !mIsSettingTextFromJS && mListeners != null) { for (TextWatcher listener : mListeners) { listener.beforeTextChanged(s, start, count, after); } @@ -858,14 +1066,20 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - if (!mIsSettingTextFromJS && mListeners != null) { - for (TextWatcher listener : mListeners) { - listener.onTextChanged(s, start, before, count); - } + if (DEBUG_MODE) { + FLog.e( + TAG, "onTextChanged[" + getId() + "]: " + s + " " + start + " " + before + " " + count); } - if (getFabricViewStateManager() != null) { - TextLayoutManager.setCachedSpannabledForTag(getId(), new SpannableString(getText())); + if (!mIsSettingTextFromCacheUpdate) { + if (!mIsSettingTextFromJS && mListeners != null) { + for (TextWatcher listener : mListeners) { + listener.onTextChanged(s, start, before, count); + } + } + + updateCachedSpannable( + !mIsSettingTextFromJS && !mIsSettingTextFromState && start == 0 && before == 0); } onContentSizeChange(); @@ -873,7 +1087,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { @Override public void afterTextChanged(Editable s) { - if (!mIsSettingTextFromJS && mListeners != null) { + if (!mIsSettingTextFromCacheUpdate && !mIsSettingTextFromJS && mListeners != null) { for (TextWatcher listener : mListeners) { listener.afterTextChanged(s); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java index 47b4391c327f11..55ae040054b92e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java @@ -12,9 +12,7 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionWrapper; import androidx.annotation.Nullable; -import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; -import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; /** @@ -61,11 +59,12 @@ class ReactEditTextInputConnectionWrapper extends InputConnectionWrapper { private @Nullable String mKey = null; public ReactEditTextInputConnectionWrapper( - InputConnection target, final ReactContext reactContext, final ReactEditText editText) { + InputConnection target, + final ReactContext reactContext, + final ReactEditText editText, + EventDispatcher eventDispatcher) { super(target, false); - mEventDispatcher = - Assertions.assertNotNull(reactContext.getNativeModule(UIManagerModule.class)) - .getEventDispatcher(); + mEventDispatcher = eventDispatcher; mEditText = editText; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextChangedEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextChangedEvent.java index a3c7e1cac12e05..f2cce90c50f033 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextChangedEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextChangedEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** * Event emitted by EditText native view when text changes. VisibleForTesting from {@link @@ -23,8 +23,13 @@ public class ReactTextChangedEvent extends Event { private String mText; private int mEventCount; + @Deprecated public ReactTextChangedEvent(int viewId, String text, int eventCount) { - super(viewId); + this(-1, viewId, text, eventCount); + } + + public ReactTextChangedEvent(int surfaceId, int viewId, String text, int eventCount) { + super(surfaceId, viewId); mText = text; mEventCount = eventCount; } @@ -34,12 +39,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putString("text", mText); eventData.putInt("eventCount", mEventCount); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputBlurEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputBlurEvent.java index 5a05bc4440742a..cd6dfca8c39b19 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputBlurEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputBlurEvent.java @@ -7,18 +7,23 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when it loses focus. */ /* package */ class ReactTextInputBlurEvent extends Event { private static final String EVENT_NAME = "topBlur"; + @Deprecated public ReactTextInputBlurEvent(int viewId) { - super(viewId); + this(-1, viewId); + } + + public ReactTextInputBlurEvent(int surfaceId, int viewId) { + super(surfaceId, viewId); } @Override @@ -31,12 +36,9 @@ public boolean canCoalesce() { return false; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("target", getViewTag()); return eventData; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEndEditingEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEndEditingEvent.java index 597fa7d13350bd..1fca01b9fa553e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEndEditingEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEndEditingEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** * Event emitted by EditText native view when text editing ends, because of the user leaving the @@ -22,8 +22,13 @@ class ReactTextInputEndEditingEvent extends Event private String mText; + @Deprecated public ReactTextInputEndEditingEvent(int viewId, String text) { - super(viewId); + this(-1, viewId, text); + } + + public ReactTextInputEndEditingEvent(int surfaceId, int viewId, String text) { + super(surfaceId, viewId); mText = text; } @@ -37,12 +42,9 @@ public boolean canCoalesce() { return false; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("target", getViewTag()); eventData.putString("text", mText); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEvent.java index 09310782055930..2285fbfafb3e47 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** * Event emitted by EditText native view when text changes. VisibleForTesting from {@link @@ -25,9 +25,15 @@ public class ReactTextInputEvent extends Event { private int mRangeStart; private int mRangeEnd; + @Deprecated public ReactTextInputEvent( int viewId, String text, String previousText, int rangeStart, int rangeEnd) { - super(viewId); + this(-1, viewId, text, previousText, rangeStart, rangeEnd); + } + + public ReactTextInputEvent( + int surfaceId, int viewId, String text, String previousText, int rangeStart, int rangeEnd) { + super(surfaceId, viewId); mText = text; mPreviousText = previousText; mRangeStart = rangeStart; @@ -45,12 +51,9 @@ public boolean canCoalesce() { return false; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); WritableMap range = Arguments.createMap(); range.putDouble("start", mRangeStart); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputFocusEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputFocusEvent.java index 0bdaa6c19926f1..61f7250e7cc7bc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputFocusEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputFocusEvent.java @@ -7,38 +7,40 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when it receives focus. */ /* package */ class ReactTextInputFocusEvent extends Event { private static final String EVENT_NAME = "topFocus"; + @Deprecated public ReactTextInputFocusEvent(int viewId) { - super(viewId); + this(-1, viewId); } - @Override - public String getEventName() { - return EVENT_NAME; + public ReactTextInputFocusEvent(int surfaceId, int viewId) { + super(surfaceId, viewId); } @Override - public boolean canCoalesce() { - return false; + public String getEventName() { + return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("target", getViewTag()); return eventData; } + + @Override + public boolean canCoalesce() { + return false; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputKeyPressEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputKeyPressEvent.java index b4193e984eb5d9..0b85f618027603 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputKeyPressEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputKeyPressEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when key pressed */ public class ReactTextInputKeyPressEvent extends Event { @@ -19,8 +19,13 @@ public class ReactTextInputKeyPressEvent extends Event { private String mKey; + @Deprecated ReactTextInputKeyPressEvent(int viewId, final String key) { - super(viewId); + this(-1, viewId, key); + } + + ReactTextInputKeyPressEvent(int surfaceId, int viewId, final String key) { + super(surfaceId, viewId); mKey = key; } @@ -29,21 +34,17 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public boolean canCoalesce() { - // We don't want to miss any textinput event, as event data is incremental. - return false; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putString("key", mKey); - return eventData; } + + @Override + public boolean canCoalesce() { + // We don't want to miss any textinput event, as event data is incremental. + return false; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 774ceb25e46ea6..3a21ef71c4bdb4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -477,21 +477,17 @@ public void setCursorColor(ReactEditText view, @Nullable Integer color) { } } + private static boolean shouldHideCursorForEmailTextInput() { + String manufacturer = Build.MANUFACTURER.toLowerCase(); + return (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && manufacturer.contains("xiaomi")); + } + @ReactProp(name = "caretHidden", defaultBoolean = false) public void setCaretHidden(ReactEditText view, boolean caretHidden) { - // Set cursor's visibility to False to fix a crash on some Xiaomi devices with Android Q. This - // crash happens when focusing on a email EditText, during which a prompt will be triggered but - // the system fail to locate it properly. Here is an example post discussing about this - // issue: https://github.com/facebook/react-native/issues/27204 - String manufacturer = Build.MANUFACTURER.toLowerCase(); - if ((view.getInputType() == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS - || view.getInputType() == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS) - && Build.VERSION.SDK_INT == Build.VERSION_CODES.Q - && manufacturer.contains("xiaomi")) { - view.setCursorVisible(false); + if (view.getStagedInputType() == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + && shouldHideCursorForEmailTextInput()) { return; } - view.setCursorVisible(!caretHidden); } @@ -763,6 +759,15 @@ public void setKeyboardType(ReactEditText view, @Nullable String keyboardType) { flagsToSet = INPUT_TYPE_KEYBOARD_DECIMAL_PAD; } else if (KEYBOARD_TYPE_EMAIL_ADDRESS.equalsIgnoreCase(keyboardType)) { flagsToSet = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT; + + // Set cursor's visibility to False to fix a crash on some Xiaomi devices with Android Q. This + // crash happens when focusing on a email EditText, during which a prompt will be triggered + // but + // the system fail to locate it properly. Here is an example post discussing about this + // issue: https://github.com/facebook/react-native/issues/27204 + if (shouldHideCursorForEmailTextInput()) { + view.setCursorVisible(false); + } } else if (KEYBOARD_TYPE_PHONE_PAD.equalsIgnoreCase(keyboardType)) { flagsToSet = InputType.TYPE_CLASS_PHONE; } else if (KEYBOARD_TYPE_VISIBLE_PASSWORD.equalsIgnoreCase(keyboardType)) { @@ -892,12 +897,14 @@ private class ReactTextInputTextWatcher implements TextWatcher { private EventDispatcher mEventDispatcher; private ReactEditText mEditText; private String mPreviousText; + private int mSurfaceId; public ReactTextInputTextWatcher( final ReactContext reactContext, final ReactEditText editText) { mEventDispatcher = getEventDispatcher(reactContext, editText); mEditText = editText; mPreviousText = null; + mSurfaceId = UIManagerHelper.getSurfaceId(reactContext); } @Override @@ -926,7 +933,6 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { return; } - // Fabric: update representation of AttributedString if (mEditText.getFabricViewStateManager().hasStateWrapper()) { // Fabric: communicate to C++ layer that text has changed // We need to call `incrementAndGetEventCounter` here explicitly because this @@ -951,10 +957,14 @@ public WritableMap getStateUpdate() { // TODO: t7936714 merge these events mEventDispatcher.dispatchEvent( new ReactTextChangedEvent( - mEditText.getId(), s.toString(), mEditText.incrementAndGetEventCounter())); + mSurfaceId, + mEditText.getId(), + s.toString(), + mEditText.incrementAndGetEventCounter())); mEventDispatcher.dispatchEvent( - new ReactTextInputEvent(mEditText.getId(), newText, oldText, start, start + before)); + new ReactTextInputEvent( + mSurfaceId, mEditText.getId(), newText, oldText, start, start + before)); } @Override @@ -964,19 +974,23 @@ public void afterTextChanged(Editable s) {} @Override protected void addEventEmitters( final ThemedReactContext reactContext, final ReactEditText editText) { + editText.setEventDispatcher(getEventDispatcher(reactContext, editText)); editText.addTextChangedListener(new ReactTextInputTextWatcher(reactContext, editText)); editText.setOnFocusChangeListener( new View.OnFocusChangeListener() { public void onFocusChange(View v, boolean hasFocus) { + int surfaceId = reactContext.getSurfaceId(); EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); if (hasFocus) { - eventDispatcher.dispatchEvent(new ReactTextInputFocusEvent(editText.getId())); + eventDispatcher.dispatchEvent( + new ReactTextInputFocusEvent(surfaceId, editText.getId())); } else { - eventDispatcher.dispatchEvent(new ReactTextInputBlurEvent(editText.getId())); + eventDispatcher.dispatchEvent( + new ReactTextInputBlurEvent(surfaceId, editText.getId())); eventDispatcher.dispatchEvent( new ReactTextInputEndEditingEvent( - editText.getId(), editText.getText().toString())); + surfaceId, editText.getId(), editText.getText().toString())); } } }); @@ -1001,7 +1015,9 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) { EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); eventDispatcher.dispatchEvent( new ReactTextInputSubmitEditingEvent( - editText.getId(), editText.getText().toString())); + reactContext.getSurfaceId(), + editText.getId(), + editText.getText().toString())); if (blurOnSubmit) { editText.clearFocus(); @@ -1034,11 +1050,13 @@ private static class ReactContentSizeWatcher implements ContentSizeWatcher { private @Nullable EventDispatcher mEventDispatcher; private int mPreviousContentWidth = 0; private int mPreviousContentHeight = 0; + private int mSurfaceId; public ReactContentSizeWatcher(ReactEditText editText) { mEditText = editText; ReactContext reactContext = getReactContext(editText); mEventDispatcher = getEventDispatcher(reactContext, editText); + mSurfaceId = UIManagerHelper.getSurfaceId(reactContext); } @Override @@ -1068,6 +1086,7 @@ public void onLayout() { mEventDispatcher.dispatchEvent( new ReactContentSizeChangedEvent( + mSurfaceId, mEditText.getId(), PixelUtil.toDIPFromPixel(contentWidth), PixelUtil.toDIPFromPixel(contentHeight))); @@ -1081,12 +1100,14 @@ private class ReactSelectionWatcher implements SelectionWatcher { private EventDispatcher mEventDispatcher; private int mPreviousSelectionStart; private int mPreviousSelectionEnd; + private int mSurfaceId; public ReactSelectionWatcher(ReactEditText editText) { mReactEditText = editText; ReactContext reactContext = getReactContext(editText); mEventDispatcher = getEventDispatcher(reactContext, editText); + mSurfaceId = UIManagerHelper.getSurfaceId(reactContext); } @Override @@ -1102,7 +1123,8 @@ public void onSelectionChanged(int start, int end) { if (mPreviousSelectionStart != realStart || mPreviousSelectionEnd != realEnd) { mEventDispatcher.dispatchEvent( - new ReactTextInputSelectionEvent(mReactEditText.getId(), realStart, realEnd)); + new ReactTextInputSelectionEvent( + mSurfaceId, mReactEditText.getId(), realStart, realEnd)); mPreviousSelectionStart = realStart; mPreviousSelectionEnd = realEnd; @@ -1116,11 +1138,13 @@ private static class ReactScrollWatcher implements ScrollWatcher { private EventDispatcher mEventDispatcher; private int mPreviousHoriz; private int mPreviousVert; + private int mSurfaceId; public ReactScrollWatcher(ReactEditText editText) { mReactEditText = editText; ReactContext reactContext = getReactContext(editText); mEventDispatcher = getEventDispatcher(reactContext, editText); + mSurfaceId = UIManagerHelper.getSurfaceId(reactContext); } @Override @@ -1128,6 +1152,7 @@ public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) { if (mPreviousHoriz != horiz || mPreviousVert != vert) { ScrollEvent event = ScrollEvent.obtain( + mSurfaceId, mReactEditText.getId(), ScrollEventType.SCROLL, horiz, @@ -1179,6 +1204,10 @@ protected EditText createInternalEditText(ThemedReactContext themedReactContext) public Object updateState( ReactEditText view, ReactStylesDiffMap props, @Nullable StateWrapper stateWrapper) { + if (ReactEditText.DEBUG_MODE) { + FLog.e(TAG, "updateState: [" + view.getId() + "]"); + } + view.getFabricViewStateManager().setStateWrapper(stateWrapper); ReadableNativeMap state = stateWrapper.getState(); @@ -1197,6 +1226,9 @@ public Object updateState( TextLayoutManager.getOrCreateSpannableForText( view.getContext(), attributedString, mReactTextViewManagerCallback); + boolean containsMultipleFragments = + attributedString.getArray("fragments").toArrayList().size() > 1; + int textBreakStrategy = TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); @@ -1206,6 +1238,6 @@ public Object updateState( TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), textBreakStrategy, TextAttributeProps.getJustificationMode(props), - attributedString); + containsMultipleFragments); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSelectionEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSelectionEvent.java index 54fc40093f0389..a69ca8766c928b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSelectionEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSelectionEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when the text selection changes. */ /* package */ class ReactTextInputSelectionEvent extends Event { @@ -20,8 +20,14 @@ private int mSelectionStart; private int mSelectionEnd; + @Deprecated public ReactTextInputSelectionEvent(int viewId, int selectionStart, int selectionEnd) { - super(viewId); + this(-1, viewId, selectionStart, selectionEnd); + } + + public ReactTextInputSelectionEvent( + int surfaceId, int viewId, int selectionStart, int selectionEnd) { + super(surfaceId, viewId); mSelectionStart = selectionStart; mSelectionEnd = selectionEnd; } @@ -31,12 +37,9 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); WritableMap selectionData = Arguments.createMap(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.java index fb717e70a23ab2..0dee36ddfac75c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputSubmitEditingEvent.java @@ -7,10 +7,10 @@ package com.facebook.react.views.textinput; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Event emitted by EditText native view when the user submits the text. */ /* package */ class ReactTextInputSubmitEditingEvent @@ -20,8 +20,13 @@ private String mText; + @Deprecated public ReactTextInputSubmitEditingEvent(int viewId, String text) { - super(viewId); + this(-1, viewId, text); + } + + public ReactTextInputSubmitEditingEvent(int surfaceId, int viewId, String text) { + super(surfaceId, viewId); mText = text; } @@ -30,20 +35,17 @@ public String getEventName() { return EVENT_NAME; } + @Nullable @Override - public boolean canCoalesce() { - return false; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { + protected WritableMap getEventData() { WritableMap eventData = Arguments.createMap(); eventData.putInt("target", getViewTag()); eventData.putString("text", mText); return eventData; } + + @Override + public boolean canCoalesce() { + return false; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK index 24d0a3f2d916fa..62b23d28001acf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/unimplementedview/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_tar rn_android_library( name = "unimplementedview", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK index 66386a0ffbfd5c..8dc27557662720 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "r rn_android_library( name = "view", srcs = glob(["*.java"]), + autoglob = False, is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java index 4fb23c95a960f2..b4a3feb9418c86 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java @@ -65,19 +65,11 @@ private static int getAttrId(Context context, String attr) { } private static Drawable getDefaultThemeDrawable(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return context.getResources().getDrawable(sResolveOutValue.resourceId, context.getTheme()); - } else { - return context.getResources().getDrawable(sResolveOutValue.resourceId); - } + return context.getResources().getDrawable(sResolveOutValue.resourceId, context.getTheme()); } private static RippleDrawable getRippleDrawable( Context context, ReadableMap drawableDescriptionDict) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - throw new JSApplicationIllegalArgumentException( - "Ripple drawable is not available on android API <21"); - } int color = getColor(context, drawableDescriptionDict); Drawable mask = getMask(drawableDescriptionDict); ColorStateList colorStateList = diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index 18b8d6b6845403..9065f4bc49fb38 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -7,7 +7,7 @@ package com.facebook.react.views.view; -import static android.os.Build.VERSION_CODES.KITKAT; +import static android.os.Build.VERSION_CODES.LOLLIPOP; import android.annotation.TargetApi; import android.content.Context; @@ -24,7 +24,6 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; -import android.os.Build; import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.common.annotations.VisibleForTesting; @@ -184,10 +183,6 @@ public int getOpacity() { /* Android's elevation implementation requires this to be implemented to know where to draw the shadow. */ @Override public void getOutline(Outline outline) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - super.getOutline(outline); - return; - } if ((!YogaConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) || mBorderCornerRadii != null) { updatePath(); @@ -545,60 +540,58 @@ private void updatePath() { float bottomRightRadius = getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.BOTTOM_RIGHT); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - float topStartRadius = getBorderRadius(BorderRadiusLocation.TOP_START); - float topEndRadius = getBorderRadius(BorderRadiusLocation.TOP_END); - float bottomStartRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_START); - float bottomEndRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_END); + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + float topStartRadius = getBorderRadius(BorderRadiusLocation.TOP_START); + float topEndRadius = getBorderRadius(BorderRadiusLocation.TOP_END); + float bottomStartRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_START); + float bottomEndRadius = getBorderRadius(BorderRadiusLocation.BOTTOM_END); - if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { - if (YogaConstants.isUndefined(topStartRadius)) { - topStartRadius = topLeftRadius; - } + if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { + if (YogaConstants.isUndefined(topStartRadius)) { + topStartRadius = topLeftRadius; + } - if (YogaConstants.isUndefined(topEndRadius)) { - topEndRadius = topRightRadius; - } + if (YogaConstants.isUndefined(topEndRadius)) { + topEndRadius = topRightRadius; + } - if (YogaConstants.isUndefined(bottomStartRadius)) { - bottomStartRadius = bottomLeftRadius; - } + if (YogaConstants.isUndefined(bottomStartRadius)) { + bottomStartRadius = bottomLeftRadius; + } - if (YogaConstants.isUndefined(bottomEndRadius)) { - bottomEndRadius = bottomRightRadius; - } + if (YogaConstants.isUndefined(bottomEndRadius)) { + bottomEndRadius = bottomRightRadius; + } - final float directionAwareTopLeftRadius = isRTL ? topEndRadius : topStartRadius; - final float directionAwareTopRightRadius = isRTL ? topStartRadius : topEndRadius; - final float directionAwareBottomLeftRadius = isRTL ? bottomEndRadius : bottomStartRadius; - final float directionAwareBottomRightRadius = isRTL ? bottomStartRadius : bottomEndRadius; + final float directionAwareTopLeftRadius = isRTL ? topEndRadius : topStartRadius; + final float directionAwareTopRightRadius = isRTL ? topStartRadius : topEndRadius; + final float directionAwareBottomLeftRadius = isRTL ? bottomEndRadius : bottomStartRadius; + final float directionAwareBottomRightRadius = isRTL ? bottomStartRadius : bottomEndRadius; - topLeftRadius = directionAwareTopLeftRadius; - topRightRadius = directionAwareTopRightRadius; - bottomLeftRadius = directionAwareBottomLeftRadius; - bottomRightRadius = directionAwareBottomRightRadius; - } else { - final float directionAwareTopLeftRadius = isRTL ? topEndRadius : topStartRadius; - final float directionAwareTopRightRadius = isRTL ? topStartRadius : topEndRadius; - final float directionAwareBottomLeftRadius = isRTL ? bottomEndRadius : bottomStartRadius; - final float directionAwareBottomRightRadius = isRTL ? bottomStartRadius : bottomEndRadius; + topLeftRadius = directionAwareTopLeftRadius; + topRightRadius = directionAwareTopRightRadius; + bottomLeftRadius = directionAwareBottomLeftRadius; + bottomRightRadius = directionAwareBottomRightRadius; + } else { + final float directionAwareTopLeftRadius = isRTL ? topEndRadius : topStartRadius; + final float directionAwareTopRightRadius = isRTL ? topStartRadius : topEndRadius; + final float directionAwareBottomLeftRadius = isRTL ? bottomEndRadius : bottomStartRadius; + final float directionAwareBottomRightRadius = isRTL ? bottomStartRadius : bottomEndRadius; - if (!YogaConstants.isUndefined(directionAwareTopLeftRadius)) { - topLeftRadius = directionAwareTopLeftRadius; - } + if (!YogaConstants.isUndefined(directionAwareTopLeftRadius)) { + topLeftRadius = directionAwareTopLeftRadius; + } - if (!YogaConstants.isUndefined(directionAwareTopRightRadius)) { - topRightRadius = directionAwareTopRightRadius; - } + if (!YogaConstants.isUndefined(directionAwareTopRightRadius)) { + topRightRadius = directionAwareTopRightRadius; + } - if (!YogaConstants.isUndefined(directionAwareBottomLeftRadius)) { - bottomLeftRadius = directionAwareBottomLeftRadius; - } + if (!YogaConstants.isUndefined(directionAwareBottomLeftRadius)) { + bottomLeftRadius = directionAwareBottomLeftRadius; + } - if (!YogaConstants.isUndefined(directionAwareBottomRightRadius)) { - bottomRightRadius = directionAwareBottomRightRadius; - } + if (!YogaConstants.isUndefined(directionAwareBottomRightRadius)) { + bottomRightRadius = directionAwareBottomRightRadius; } } @@ -1038,43 +1031,41 @@ private void drawRectangularBackgroundWithBorders(Canvas canvas) { int colorRight = getBorderColor(Spacing.RIGHT); int colorBottom = getBorderColor(Spacing.BOTTOM); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - int colorStart = getBorderColor(Spacing.START); - int colorEnd = getBorderColor(Spacing.END); + final boolean isRTL = getResolvedLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + int colorStart = getBorderColor(Spacing.START); + int colorEnd = getBorderColor(Spacing.END); - if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { - if (!isBorderColorDefined(Spacing.START)) { - colorStart = colorLeft; - } + if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(mContext)) { + if (!isBorderColorDefined(Spacing.START)) { + colorStart = colorLeft; + } - if (!isBorderColorDefined(Spacing.END)) { - colorEnd = colorRight; - } + if (!isBorderColorDefined(Spacing.END)) { + colorEnd = colorRight; + } - final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; - final int directionAwareColorRight = isRTL ? colorStart : colorEnd; + final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; + final int directionAwareColorRight = isRTL ? colorStart : colorEnd; - colorLeft = directionAwareColorLeft; - colorRight = directionAwareColorRight; - } else { - final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; - final int directionAwareColorRight = isRTL ? colorStart : colorEnd; + colorLeft = directionAwareColorLeft; + colorRight = directionAwareColorRight; + } else { + final int directionAwareColorLeft = isRTL ? colorEnd : colorStart; + final int directionAwareColorRight = isRTL ? colorStart : colorEnd; - final boolean isColorStartDefined = isBorderColorDefined(Spacing.START); - final boolean isColorEndDefined = isBorderColorDefined(Spacing.END); - final boolean isDirectionAwareColorLeftDefined = - isRTL ? isColorEndDefined : isColorStartDefined; - final boolean isDirectionAwareColorRightDefined = - isRTL ? isColorStartDefined : isColorEndDefined; + final boolean isColorStartDefined = isBorderColorDefined(Spacing.START); + final boolean isColorEndDefined = isBorderColorDefined(Spacing.END); + final boolean isDirectionAwareColorLeftDefined = + isRTL ? isColorEndDefined : isColorStartDefined; + final boolean isDirectionAwareColorRightDefined = + isRTL ? isColorStartDefined : isColorEndDefined; - if (isDirectionAwareColorLeftDefined) { - colorLeft = directionAwareColorLeft; - } + if (isDirectionAwareColorLeftDefined) { + colorLeft = directionAwareColorLeft; + } - if (isDirectionAwareColorRightDefined) { - colorRight = directionAwareColorRight; - } + if (isDirectionAwareColorRightDefined) { + colorRight = directionAwareColorRight; } } @@ -1244,7 +1235,7 @@ private int getBorderColor(int position) { return ReactViewBackgroundDrawable.colorFromAlphaAndRGBComponents(alpha, rgb); } - @TargetApi(KITKAT) + @TargetApi(LOLLIPOP) public RectF getDirectionAwareBorderInsets() { final float borderWidth = getBorderWidthOrDefaultTo(0, Spacing.ALL); final float borderTopWidth = getBorderWidthOrDefaultTo(borderWidth, Spacing.TOP); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index f8fc85cf5826c8..14529b4486e881 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -31,7 +31,6 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.touch.OnInterceptTouchEventListener; import com.facebook.react.touch.ReactHitSlopView; @@ -47,13 +46,15 @@ import com.facebook.react.uimanager.RootViewUtil; import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; import com.facebook.react.uimanager.ViewProps; +import com.facebook.react.uimanager.common.UIManagerType; +import com.facebook.react.uimanager.common.ViewUtil; import com.facebook.yoga.YogaConstants; /** * Backing for a React View. Has support for borders, but since borders aren't common, lazy * initializes most of the storage needed for them. */ -@TargetApi(Build.VERSION_CODES.KITKAT) +@TargetApi(Build.VERSION_CODES.LOLLIPOP) public class ReactViewGroup extends ViewGroup implements ReactInterceptingViewGroup, ReactClippingViewGroup, @@ -119,7 +120,7 @@ public void onLayoutChange( private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable; private @Nullable OnInterceptTouchEventListener mOnInterceptTouchEventListener; private boolean mNeedsOffscreenAlphaCompositing = false; - private final ViewGroupDrawingOrderHelper mDrawingOrderHelper; + private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper = null; private @Nullable Path mPath; private int mLayoutDirection; private float mBackfaceOpacity = 1.f; @@ -128,7 +129,13 @@ public void onLayoutChange( public ReactViewGroup(Context context) { super(context); setClipChildren(false); - mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); + } + + private ViewGroupDrawingOrderHelper getDrawingOrderHelper() { + if (mDrawingOrderHelper == null) { + mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this); + } + return mDrawingOrderHelper; } @Override @@ -411,9 +418,7 @@ private void updateSubviewClipStatus(View subview) { @Override public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { - return ReactFeatureFlags.clipChildRectsIfOverflowIsHidden - ? ReactClippingViewGroupHelper.getChildVisibleRectHelper(child, r, offset, this, mOverflow) - : super.getChildVisibleRect(child, r, offset); + return super.getChildVisibleRect(child, r, offset); } @Override @@ -432,12 +437,24 @@ protected void onAttachedToWindow() { } } + private boolean customDrawOrderDisabled() { + if (getId() == NO_ID) { + return false; + } + return ViewUtil.getUIManagerType(getId()) == UIManagerType.FABRIC; + } + @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { // This will get called for every overload of addView so there is not need to override every // method. - mDrawingOrderHelper.handleAddView(child); - setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder()); + + if (!customDrawOrderDisabled()) { + getDrawingOrderHelper().handleAddView(child); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); + } else { + setChildrenDrawingOrderEnabled(false); + } super.addView(child, index, params); } @@ -446,8 +463,12 @@ public void addView(View child, int index, ViewGroup.LayoutParams params) { public void removeView(View view) { UiThreadUtil.assertOnUiThread(); - mDrawingOrderHelper.handleRemoveView(view); - setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder()); + if (!customDrawOrderDisabled()) { + getDrawingOrderHelper().handleRemoveView(view); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); + } else { + setChildrenDrawingOrderEnabled(false); + } super.removeView(view); } @@ -456,30 +477,47 @@ public void removeView(View view) { public void removeViewAt(int index) { UiThreadUtil.assertOnUiThread(); - mDrawingOrderHelper.handleRemoveView(getChildAt(index)); - setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder()); + if (!customDrawOrderDisabled()) { + getDrawingOrderHelper().handleRemoveView(getChildAt(index)); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); + } else { + setChildrenDrawingOrderEnabled(false); + } super.removeViewAt(index); } @Override protected int getChildDrawingOrder(int childCount, int index) { - return mDrawingOrderHelper.getChildDrawingOrder(childCount, index); + UiThreadUtil.assertOnUiThread(); + + if (!customDrawOrderDisabled()) { + return getDrawingOrderHelper().getChildDrawingOrder(childCount, index); + } else { + return index; + } } @Override public int getZIndexMappedChildIndex(int index) { - if (mDrawingOrderHelper.shouldEnableCustomDrawingOrder()) { - return mDrawingOrderHelper.getChildDrawingOrder(getChildCount(), index); - } else { - return index; + UiThreadUtil.assertOnUiThread(); + + if (!customDrawOrderDisabled() && getDrawingOrderHelper().shouldEnableCustomDrawingOrder()) { + return getDrawingOrderHelper().getChildDrawingOrder(getChildCount(), index); } + + // Fabric behavior + return index; } @Override public void updateDrawingOrder() { - mDrawingOrderHelper.update(); - setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder()); + if (customDrawOrderDisabled()) { + return; + } + + getDrawingOrderHelper().update(); + setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); invalidate(); } @@ -674,9 +712,7 @@ protected void dispatchDraw(Canvas canvas) { try { dispatchOverflowDraw(canvas); super.dispatchDraw(canvas); - } catch (NullPointerException e) { - FLog.e(TAG, "NullPointerException when executing ViewGroup.dispatchDraw method", e); - } catch (StackOverflowError e) { + } catch (NullPointerException | StackOverflowError e) { // Adding special exception management for StackOverflowError for logging purposes. // This will be removed in the future. RootView rootView = RootViewUtil.getRootView(ReactViewGroup.this); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 851ec10c6f331c..1192b50f2e4cc7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -239,7 +239,9 @@ public void onClick(View v) { if (mEventDispatcher == null) { return; } - mEventDispatcher.dispatchEvent(new ViewGroupClickEvent(view.getId())); + mEventDispatcher.dispatchEvent( + new ViewGroupClickEvent( + UIManagerHelper.getSurfaceId(view.getContext()), view.getId())); } }); @@ -335,10 +337,9 @@ private void handleHotspotUpdate(ReactViewGroup root, @Nullable ReadableArray ar throw new JSApplicationIllegalArgumentException( "Illegal number of arguments for 'updateHotspot' command"); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - float x = PixelUtil.toPixelFromDIP(args.getDouble(0)); - float y = PixelUtil.toPixelFromDIP(args.getDouble(1)); - root.drawableHotspotChanged(x, y); - } + + float x = PixelUtil.toPixelFromDIP(args.getDouble(0)); + float y = PixelUtil.toPixelFromDIP(args.getDouble(1)); + root.drawableHotspotChanged(x, y); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ViewGroupClickEvent.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ViewGroupClickEvent.java index c328752a564172..d7a380802fbb0b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ViewGroupClickEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ViewGroupClickEvent.java @@ -7,16 +7,22 @@ package com.facebook.react.views.view; +import androidx.annotation.Nullable; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; /** Represents a Click on the ReactViewGroup */ public class ViewGroupClickEvent extends Event { private static final String EVENT_NAME = "topClick"; + @Deprecated public ViewGroupClickEvent(int viewId) { - super(viewId); + this(-1, viewId); + } + + public ViewGroupClickEvent(int surfaceId, int viewId) { + super(surfaceId, viewId); } @Override @@ -29,8 +35,9 @@ public boolean canCoalesce() { return false; } + @Nullable @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), Arguments.createMap()); + protected WritableMap getEventData() { + return Arguments.createMap(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/systrace/BUCK b/ReactAndroid/src/main/java/com/facebook/systrace/BUCK index 21006f1842c39a..ef6249a999177f 100644 --- a/ReactAndroid/src/main/java/com/facebook/systrace/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/systrace/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library") rn_android_library( name = "systrace", srcs = glob(["*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/main/java/com/facebook/systrace/Systrace.java b/ReactAndroid/src/main/java/com/facebook/systrace/Systrace.java index e88d04928c363c..7da483cd24522d 100644 --- a/ReactAndroid/src/main/java/com/facebook/systrace/Systrace.java +++ b/ReactAndroid/src/main/java/com/facebook/systrace/Systrace.java @@ -7,7 +7,6 @@ package com.facebook.systrace; -import android.os.Build; import android.os.Trace; /** @@ -49,15 +48,11 @@ public static boolean isTracing(long tag) { public static void traceInstant(long tag, final String title, EventScope scope) {} public static void beginSection(long tag, final String sectionName) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - Trace.beginSection(sectionName); - } + Trace.beginSection(sectionName); } public static void endSection(long tag) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - Trace.endSection(); - } + Trace.endSection(); } public static void beginAsyncSection(long tag, final String sectionName, final int cookie) {} diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java index 406e75e5dc3f5e..7ab391cce51cf7 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java @@ -116,6 +116,9 @@ public void swapChildAt(YogaNode newChild, int position) { public YogaNodeJNIBase cloneWithChildren() { try { YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone(); + if (clonedYogaNode.mChildren != null) { + clonedYogaNode.mChildren = new ArrayList<>(clonedYogaNode.mChildren); + } long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer); clonedYogaNode.mOwner = null; clonedYogaNode.mNativePointer = clonedNativePointer; diff --git a/ReactAndroid/src/main/jni/Application.mk b/ReactAndroid/src/main/jni/Application.mk index 84eae80adf4c9d..f90f6b9418beee 100644 --- a/ReactAndroid/src/main/jni/Application.mk +++ b/ReactAndroid/src/main/jni/Application.mk @@ -6,7 +6,7 @@ APP_BUILD_SCRIPT := Android.mk APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 -APP_PLATFORM := android-16 +APP_PLATFORM := android-21 APP_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST))) @@ -22,7 +22,7 @@ APP_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST))) # Where are APP_MK_DIR, THIRD_PARTY_NDK_DIR, etc. defined? # The directories inside NDK_MODULE_PATH (ex: APP_MK_DIR, THIRD_PARTY_NDK_DIR, # etc.) are defined inside build.gradle. -NDK_MODULE_PATH := $(APP_MK_DIR)$(HOST_DIRSEP)$(THIRD_PARTY_NDK_DIR)$(HOST_DIRSEP)$(REACT_COMMON_DIR)$(HOST_DIRSEP)$(APP_MK_DIR)first-party$(HOST_DIRSEP)$(REACT_SRC_DIR) +NDK_MODULE_PATH := $(APP_MK_DIR)$(HOST_DIRSEP)$(THIRD_PARTY_NDK_DIR)$(HOST_DIRSEP)$(REACT_COMMON_DIR)$(HOST_DIRSEP)$(APP_MK_DIR)first-party$(HOST_DIRSEP)$(REACT_SRC_DIR)$(HOST_DIRSEP)$(REACT_GENERATED_SRC_DIR) APP_STL := c++_shared diff --git a/ReactAndroid/src/main/jni/first-party/fb/include/fb/RefPtr.h b/ReactAndroid/src/main/jni/first-party/fb/include/fb/RefPtr.h index 1384b6534a5db3..6b24554ede634d 100644 --- a/ReactAndroid/src/main/jni/first-party/fb/include/fb/RefPtr.h +++ b/ReactAndroid/src/main/jni/first-party/fb/include/fb/RefPtr.h @@ -204,7 +204,7 @@ static inline RefPtr adoptRef(T *ptr) { } template -static inline RefPtr createNew(Args &&... arguments) { +static inline RefPtr createNew(Args &&...arguments) { return RefPtr::adoptRef(new T(std::forward(arguments)...)); } diff --git a/ReactAndroid/src/main/jni/first-party/fb/include/fb/StaticInitialized.h b/ReactAndroid/src/main/jni/first-party/fb/include/fb/StaticInitialized.h index 839400f13a2787..d5c553423aa4cf 100644 --- a/ReactAndroid/src/main/jni/first-party/fb/include/fb/StaticInitialized.h +++ b/ReactAndroid/src/main/jni/first-party/fb/include/fb/StaticInitialized.h @@ -21,7 +21,7 @@ class StaticInitialized { constexpr StaticInitialized() : m_instance(nullptr) {} template - void initialize(Args &&... arguments) { + void initialize(Args &&...arguments) { FBASSERT(!m_instance); m_instance = new T(std::forward(arguments)...); } diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index 70b65082fac834..9831c1aeef2c0e 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -80,7 +80,7 @@ LOCAL_LDLIBS += -landroid LOCAL_SHARED_LIBRARIES := libreactnativeutilsjni libfolly_json libfb libfbjni libglog_init libyoga # The static libraries (.a files) that this module depends on. -LOCAL_STATIC_LIBRARIES := libreactnative libcallinvokerholder libruntimeexecutor +LOCAL_STATIC_LIBRARIES := libreactnative libruntimeexecutor libcallinvokerholder # Name of this module. # @@ -128,14 +128,13 @@ $(call import-module,callinvoker) $(call import-module,reactperflogger) $(call import-module,hermes) $(call import-module,runtimeexecutor) +$(call import-module,react/nativemodule/core) include $(REACT_SRC_DIR)/reactperflogger/jni/Android.mk +# TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..." +# Note: Update this only when ready to minimize breaking changes. include $(REACT_SRC_DIR)/turbomodule/core/jni/Android.mk - -ifeq ($(BUILD_FABRIC),true) - include $(REACT_SRC_DIR)/viewmanagers/jni/Android.mk - include $(REACT_SRC_DIR)/fabric/jni/Android.mk -endif +include $(REACT_SRC_DIR)/fabric/jni/Android.mk # TODO(ramanpreet): # Why doesn't this import-module call generate a jscexecutor.so file? @@ -145,3 +144,5 @@ include $(REACT_SRC_DIR)/jscexecutor/Android.mk include $(REACT_SRC_DIR)/../hermes/reactexecutor/Android.mk include $(REACT_SRC_DIR)/../hermes/instrumentation/Android.mk include $(REACT_SRC_DIR)/modules/blob/jni/Android.mk + +include $(REACT_GENERATED_SRC_DIR)/codegen/jni/Android.mk diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 7d5b1acf483f88..2a33fa3d0f8294 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -92,12 +92,6 @@ CatalystInstanceImpl::initHybrid(jni::alias_ref) { CatalystInstanceImpl::CatalystInstanceImpl() : instance_(std::make_unique()) {} -CatalystInstanceImpl::~CatalystInstanceImpl() { - if (moduleMessageQueue_ != NULL) { - moduleMessageQueue_->quitSynchronous(); - } -} - void CatalystInstanceImpl::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid), @@ -233,7 +227,30 @@ void CatalystInstanceImpl::jniLoadScriptFromFile( const std::string &fileName, const std::string &sourceURL, bool loadSynchronously) { - if (Instance::isIndexedRAMBundle(fileName.c_str())) { + auto reactInstance = instance_; + if (reactInstance && Instance::isHBCBundle(fileName.c_str())) { + std::unique_ptr script; + RecoverableError::runRethrowingAsRecoverable( + [&fileName, &script]() { + script = JSBigFileString::fromPath(fileName); + }); + const char *buffer = script->c_str(); + uint32_t bufferLength = (uint32_t)script->size(); + uint32_t offset = 8; + while (offset < bufferLength) { + uint32_t segment = offset + 4; + uint32_t moduleLength = + bufferLength < segment ? 0 : *(((uint32_t *)buffer) + offset / 4); + + reactInstance->loadScriptFromString( + std::make_unique( + std::string(buffer + segment, buffer + moduleLength + segment)), + sourceURL, + false); + + offset += ((moduleLength + 3) & ~3) + 4; + } + } else if (Instance::isIndexedRAMBundle(fileName.c_str())) { instance_->loadRAMBundleFromFile(fileName, sourceURL, loadSynchronously); } else { std::unique_ptr script; diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index dd9990ef090a00..c40a691232c6a2 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -37,7 +37,6 @@ class CatalystInstanceImpl : public jni::HybridClass { "Lcom/facebook/react/bridge/CatalystInstanceImpl;"; static jni::local_ref initHybrid(jni::alias_ref); - ~CatalystInstanceImpl() override; static void registerNatives(); diff --git a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp index 2af23e9d96cd46..d8000914175870 100644 --- a/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JReactMarker.cpp @@ -18,6 +18,8 @@ void JReactMarker::setLogPerfMarkerIfNeeded() { static std::once_flag flag{}; std::call_once(flag, []() { ReactMarker::logTaggedMarker = JReactMarker::logPerfMarker; + ReactMarker::logTaggedMarkerWithInstanceKey = + JReactMarker::logPerfMarkerWithInstanceKey; }); } @@ -36,15 +38,32 @@ void JReactMarker::logMarker( meth(cls, marker, tag); } +void JReactMarker::logMarker( + const std::string &marker, + const std::string &tag, + const int instanceKey) { + static auto cls = javaClassStatic(); + static auto meth = + cls->getStaticMethod("logMarker"); + meth(cls, marker, tag, instanceKey); +} + void JReactMarker::logPerfMarker( const ReactMarker::ReactMarkerId markerId, const char *tag) { + logPerfMarkerWithInstanceKey(markerId, tag, 0); +} + +void JReactMarker::logPerfMarkerWithInstanceKey( + const facebook::react::ReactMarker::ReactMarkerId markerId, + const char *tag, + const int instanceKey) { switch (markerId) { case ReactMarker::RUN_JS_BUNDLE_START: - JReactMarker::logMarker("RUN_JS_BUNDLE_START", tag); + JReactMarker::logMarker("RUN_JS_BUNDLE_START", tag, instanceKey); break; case ReactMarker::RUN_JS_BUNDLE_STOP: - JReactMarker::logMarker("RUN_JS_BUNDLE_END", tag); + JReactMarker::logMarker("RUN_JS_BUNDLE_END", tag, instanceKey); break; case ReactMarker::CREATE_REACT_CONTEXT_STOP: JReactMarker::logMarker("CREATE_REACT_CONTEXT_END"); @@ -56,19 +75,21 @@ void JReactMarker::logPerfMarker( JReactMarker::logMarker("loadApplicationScript_endStringConvert"); break; case ReactMarker::NATIVE_MODULE_SETUP_START: - JReactMarker::logMarker("NATIVE_MODULE_SETUP_START", tag); + JReactMarker::logMarker("NATIVE_MODULE_SETUP_START", tag, instanceKey); break; case ReactMarker::NATIVE_MODULE_SETUP_STOP: - JReactMarker::logMarker("NATIVE_MODULE_SETUP_END", tag); + JReactMarker::logMarker("NATIVE_MODULE_SETUP_END", tag, instanceKey); break; case ReactMarker::REGISTER_JS_SEGMENT_START: - JReactMarker::logMarker("REGISTER_JS_SEGMENT_START", tag); + JReactMarker::logMarker("REGISTER_JS_SEGMENT_START", tag, instanceKey); break; case ReactMarker::REGISTER_JS_SEGMENT_STOP: - JReactMarker::logMarker("REGISTER_JS_SEGMENT_STOP", tag); + JReactMarker::logMarker("REGISTER_JS_SEGMENT_STOP", tag, instanceKey); break; case ReactMarker::NATIVE_REQUIRE_START: case ReactMarker::NATIVE_REQUIRE_STOP: + case ReactMarker::REACT_INSTANCE_INIT_START: + case ReactMarker::REACT_INSTANCE_INIT_STOP: // These are not used on Android. break; } diff --git a/ReactAndroid/src/main/jni/react/jni/JReactMarker.h b/ReactAndroid/src/main/jni/react/jni/JReactMarker.h index 7b5e8e143f242b..d495daf9ec6c93 100644 --- a/ReactAndroid/src/main/jni/react/jni/JReactMarker.h +++ b/ReactAndroid/src/main/jni/react/jni/JReactMarker.h @@ -24,9 +24,17 @@ class JReactMarker : public facebook::jni::JavaClass { private: static void logMarker(const std::string &marker); static void logMarker(const std::string &marker, const std::string &tag); + static void logMarker( + const std::string &marker, + const std::string &tag, + const int instanceKey); static void logPerfMarker( const ReactMarker::ReactMarkerId markerId, const char *tag); + static void logPerfMarkerWithInstanceKey( + const ReactMarker::ReactMarkerId markerId, + const char *tag, + const int instanceKey); }; } // namespace react diff --git a/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp b/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp index c1ad15082bebf5..61f686c4404466 100644 --- a/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp @@ -64,14 +64,15 @@ local_ref> ReadableNativeMap::importKeys() { return JArrayClass::newArray(0); } auto pairs = map_.items(); - for (auto &pair : pairs) { - keys_.value().push_back(pair.first.asString()); - } - jint size = keys_.value().size(); + jint size = map_.size(); auto jarray = JArrayClass::newArray(size); - for (jint ii = 0; ii < size; ii++) { - (*jarray)[ii] = make_jstring(keys_.value()[ii].getString()); + jint i = 0; + for (auto &pair : pairs) { + auto value = pair.first.asString(); + keys_.value().push_back(value); + (*jarray)[i++] = make_jstring(value); } + return jarray; } diff --git a/ReactAndroid/src/main/libraries/fbcore/src/main/java/com/facebook/common/logging/BUCK b/ReactAndroid/src/main/libraries/fbcore/src/main/java/com/facebook/common/logging/BUCK index e8c4380c800a5f..e18c8ef06ee157 100644 --- a/ReactAndroid/src/main/libraries/fbcore/src/main/java/com/facebook/common/logging/BUCK +++ b/ReactAndroid/src/main/libraries/fbcore/src/main/java/com/facebook/common/logging/BUCK @@ -2,6 +2,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "logging", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ react_native_dep("libraries/fresco/fresco-react-native:fbcore"), diff --git a/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK b/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK index 830cfd9da3f4f4..b353e4cca824cf 100644 --- a/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK +++ b/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK @@ -9,8 +9,8 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "fresco-binary-aar", - sha1 = "d473020b37b7cdd3171154942b55021a55a9d990", - url = "mvn:com.facebook.fresco:fresco:aar:2.0.0", + sha1 = "fbc98413bb32eefe882a07cc556c7a1224dc9f24", + url = "mvn:com.facebook.fresco:fresco:aar:2.3.0", ) rn_android_prebuilt_aar( @@ -21,18 +21,25 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "drawee-binary-aar", - sha1 = "a85bfaeb87a9c8d1521c70edf6ded91ff9999475", - url = "mvn:com.facebook.fresco:drawee:aar:2.0.0", + sha1 = "1cff917b6f19efe7a21ca542c8b8bed18d0d9779", + url = "mvn:com.facebook.fresco:drawee:aar:2.3.0", ) rn_android_library( name = "imagepipeline", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":bolts", ":imagepipeline-base", ":imagepipeline-core", + ":imagepipeline-native", + ":memory-type-ashmem", + ":memory-type-java", + ":memory-type-native", ":native-filters", + ":native-transcoder", + ":ui-common", ], ) @@ -44,8 +51,8 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "imagepipeline-base-aar", - sha1 = "d27635390665d433f987177c548d25d0473eadbe", - url = "mvn:com.facebook.fresco:imagepipeline-base:aar:2.0.0", + sha1 = "ed3c290961f4c20fffa0ce35c098714c1934523d", + url = "mvn:com.facebook.fresco:imagepipeline-base:aar:2.3.0", ) rn_android_prebuilt_aar( @@ -56,8 +63,8 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "imagepipeline-aar", - sha1 = "7bc59327fb4895c465cbfeede700daf349ea56da", - url = "mvn:com.facebook.fresco:imagepipeline:aar:2.0.0", + sha1 = "579954628c8e1da96e1585741f5dae08f282ce3e", + url = "mvn:com.facebook.fresco:imagepipeline:aar:2.3.0", ) rn_android_prebuilt_aar( @@ -68,8 +75,20 @@ rn_android_prebuilt_aar( remote_file( name = "nativeimagefilters-aar", - sha1 = "f49525db580abc4d2fb0a74fac771fc6c69f2adb", - url = "mvn:com.facebook.fresco:nativeimagefilters:aar:2.0.0", + sha1 = "1f4d81f8f6e2706ae848124d454c99cadd85496c", + url = "mvn:com.facebook.fresco:nativeimagefilters:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "native-transcoder", + aar = ":nativeimagetranscoder-aar", + visibility = ["//ReactAndroid/..."], +) + +remote_file( + name = "nativeimagetranscoder-aar", + sha1 = "1b74432d16db744719dfe1d03d4d93850e061d08", + url = "mvn:com.facebook.fresco:nativeimagetranscoder:aar:2.3.0", ) rn_prebuilt_jar( @@ -92,8 +111,20 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "fbcore-aar", - sha1 = "8de91f71e8aa84a4d9be4dd88d1a0ac51600ad60", - url = "mvn:com.facebook.fresco:fbcore:aar:2.0.0", + sha1 = "6d568ce3e1a5377c390dbde6f150884fecd61bd0", + url = "mvn:com.facebook.fresco:fbcore:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "imagepipeline-native", + aar = ":imagepipeline-native-binary-aar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "imagepipeline-native-binary-aar", + sha1 = "705a3629cfba16ab8c9b2765058380276514342c", + url = "mvn:com.facebook.fresco:imagepipeline-native:aar:2.3.0", ) rn_android_prebuilt_aar( @@ -104,6 +135,54 @@ rn_android_prebuilt_aar( fb_native.remote_file( name = "imagepipeline-okhttp3-binary-aar", - sha1 = "bc1212ca66cd09678b416894ea8bd04102d26c5f", - url = "mvn:com.facebook.fresco:imagepipeline-okhttp3:aar:2.0.0", + sha1 = "1065513f02b97ee46601d92105151ae9e2111bfc", + url = "mvn:com.facebook.fresco:imagepipeline-okhttp3:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "memory-type-ashmem", + aar = ":memory-type-ashmem-aar", + visibility = ["//ReactAndroid/..."], +) + +remote_file( + name = "memory-type-ashmem-aar", + sha1 = "d0e2ab70d5d35d08de81d3917b0f5d7bbf4fa82c", + url = "mvn:com.facebook.fresco:memory-type-ashmem:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "memory-type-java", + aar = ":memory-type-java-aar", + visibility = ["//ReactAndroid/..."], +) + +remote_file( + name = "memory-type-java-aar", + sha1 = "5e8adc594bc9d8f4e8d794dff23c70882fb98e65", + url = "mvn:com.facebook.fresco:memory-type-java:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "memory-type-native", + aar = ":memory-type-native-aar", + visibility = ["//ReactAndroid/..."], +) + +remote_file( + name = "memory-type-native-aar", + sha1 = "72bb5626d508587cb9d96beb0e2b61ac36a2c63d", + url = "mvn:com.facebook.fresco:memory-type-native:aar:2.3.0", +) + +rn_android_prebuilt_aar( + name = "ui-common", + aar = ":ui-common-aar", + visibility = ["//ReactAndroid/..."], +) + +remote_file( + name = "ui-common-aar", + sha1 = "0ce37a495f0f37165e3ede1c4cb927b0b55856be", + url = "mvn:com.facebook.fresco:ui-common:aar:2.3.0", ) diff --git a/ReactAndroid/src/main/third-party/android/support/v4/BUCK b/ReactAndroid/src/main/third-party/android/support/v4/BUCK deleted file mode 100644 index 25a3662a1c4703..00000000000000 --- a/ReactAndroid/src/main/third-party/android/support/v4/BUCK +++ /dev/null @@ -1,685 +0,0 @@ -load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") - -fb_native.android_library( - name = "lib-support-v4", - visibility = ["PUBLIC"], - exported_deps = [ - ":appcompat", - ":asynclayoutinflater", - ":collection", - ":coordinatorlayout", - ":core", - ":core-common", - ":core-runtime", - ":cursoradapter", - ":customview", - ":documentfile", - ":drawerlayout", - ":fragment", - ":interpolator", - ":legacy-support-core-ui", - ":legacy-support-core-utils", - ":lifecycle-common", - ":lifecycle-livedata", - ":lifecycle-livedata-core", - ":lifecycle-runtime", - ":lifecycle-viewmodel", - ":loader", - ":localbroadcastmanager", - ":print", - ":slidingpanelayout", - ":swiperefreshlayout", - ":vectordrawable", - ":vectordrawable-animated", - ":versionedparcelable", - ":viewpager", - ], -) - -fb_native.prebuilt_jar( - name = "annotation", - binary_jar = ":annotation.jar", - visibility = ["PUBLIC"], -) - -fb_native.android_library( - name = "appcompat", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":collection", - ":core", - ":cursoradapter", - ":fragment", - ":legacy-support-core-utils", - ":vectordrawable", - ":vectordrawable-animated", - ], -) - -fb_native.android_library( - name = "asynclayoutinflater", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":asynclayoutinflater-binary", - ":core", - ], -) - -fb_native.android_library( - name = "collection", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":collection-binary", - ], -) - -fb_native.android_library( - name = "coordinatorlayout", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":coordinatorlayout-binary", - ":core", - ":customview", - ], -) - -fb_native.android_library( - name = "core", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":collection", - ":core-binary", - ":lifecycle-runtime", - ":versionedparcelable", - ], -) - -fb_native.android_library( - name = "core-common", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core-common-binary", - ], -) - -fb_native.android_library( - name = "core-runtime", - visibility = ["PUBLIC"], - exported_deps = [ - ":core-common", - ":core-runtime-binary", - ], -) - -fb_native.android_library( - name = "cursoradapter", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":cursoradapter-binary", - ], -) - -fb_native.android_library( - name = "customview", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":customview-binary", - ], -) - -fb_native.android_library( - name = "documentfile", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":documentfile-binary", - ], -) - -fb_native.android_library( - name = "drawerlayout", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":customview", - ":drawerlayout-binary", - ], -) - -fb_native.android_library( - name = "fragment", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":fragment-binary", - ":legacy-support-core-ui", - ":legacy-support-core-utils", - ":lifecycle-viewmodel", - ":loader", - ], -) - -fb_native.android_library( - name = "interpolator", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":interpolator-binary", - ], -) - -fb_native.android_library( - name = "legacy-support-core-ui", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":asynclayoutinflater", - ":coordinatorlayout", - ":core", - ":cursoradapter", - ":customview", - ":drawerlayout", - ":interpolator", - ":legacy-support-core-ui-binary", - ":legacy-support-core-utils", - ":slidingpanelayout", - ":swiperefreshlayout", - ":viewpager", - ], -) - -fb_native.android_library( - name = "legacy-support-core-utils", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":documentfile", - ":legacy-support-core-utils-binary", - ":loader", - ":localbroadcastmanager", - ":print", - ], -) - -fb_native.android_library( - name = "lifecycle-common", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":lifecycle-common-binary", - ], -) - -fb_native.android_library( - name = "lifecycle-livedata", - visibility = ["PUBLIC"], - exported_deps = [ - ":core-common", - ":core-runtime", - ":lifecycle-livedata-binary", - ":lifecycle-livedata-core", - ], -) - -fb_native.android_library( - name = "lifecycle-livedata-core", - visibility = ["PUBLIC"], - exported_deps = [ - ":core-common", - ":core-runtime", - ":lifecycle-common", - ":lifecycle-livedata-core-binary", - ], -) - -fb_native.android_library( - name = "lifecycle-runtime", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core-common", - ":lifecycle-common", - ":lifecycle-runtime-binary", - ], -) - -fb_native.android_library( - name = "lifecycle-viewmodel", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":lifecycle-viewmodel-binary", - ], -) - -fb_native.android_library( - name = "localbroadcastmanager", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":localbroadcastmanager-binary", - ], -) - -fb_native.android_library( - name = "loader", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":lifecycle-livedata", - ":lifecycle-viewmodel", - ":loader-binary", - ], -) - -fb_native.android_library( - name = "print", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":print-binary", - ], -) - -fb_native.android_library( - name = "slidingpanelayout", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":customview", - ":slidingpanelayout-binary", - ], -) - -fb_native.android_library( - name = "swiperefreshlayout", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":interpolator", - ":swiperefreshlayout-binary", - ], -) - -fb_native.android_library( - name = "vectordrawable", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":vectordrawable-binary", - ], -) - -fb_native.android_library( - name = "vectordrawable-animated", - visibility = ["PUBLIC"], - exported_deps = [ - ":legacy-support-core-ui", - ":vectordrawable", - ":vectordrawable-animated-binary", - ], -) - -fb_native.android_library( - name = "versionedparcelable", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":collection", - ":versionedparcelable-binary", - ], -) - -fb_native.android_library( - name = "viewpager", - visibility = ["PUBLIC"], - exported_deps = [ - ":annotation", - ":core", - ":customview", - ":viewpager-binary", - ], -) - -# Internal targets -fb_native.android_prebuilt_aar( - name = "appcompat-binary", - aar = ":appcompat-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "asynclayoutinflater-binary", - aar = ":asynclayoutinflater-binary-aar", -) - -fb_native.prebuilt_jar( - name = "collection-binary", - binary_jar = ":collection-binary.jar", -) - -fb_native.android_prebuilt_aar( - name = "coordinatorlayout-binary", - aar = ":coordinatorlayout-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "core-binary", - aar = ":core-binary-aar", -) - -fb_native.prebuilt_jar( - name = "core-common-binary", - binary_jar = ":core-common-binary.jar", -) - -fb_native.android_prebuilt_aar( - name = "core-runtime-binary", - aar = ":core-runtime-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "cursoradapter-binary", - aar = ":cursoradapter-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "customview-binary", - aar = ":customview-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "documentfile-binary", - aar = ":documentfile-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "drawerlayout-binary", - aar = ":drawerlayout-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "fragment-binary", - aar = ":fragment-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "interpolator-binary", - aar = ":interpolator-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "legacy-support-core-ui-binary", - aar = ":legacy-support-core-ui-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "legacy-support-core-utils-binary", - aar = ":legacy-support-core-utils-binary-aar", -) - -fb_native.prebuilt_jar( - name = "lifecycle-common-binary", - binary_jar = ":lifecycle-common-binary.jar", -) - -fb_native.android_prebuilt_aar( - name = "lifecycle-livedata-binary", - aar = ":lifecycle-livedata-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "lifecycle-livedata-core-binary", - aar = ":lifecycle-livedata-core-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "lifecycle-runtime-binary", - aar = ":lifecycle-runtime-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "lifecycle-viewmodel-binary", - aar = ":lifecycle-viewmodel-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "loader-binary", - aar = ":loader-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "localbroadcastmanager-binary", - aar = ":localbroadcastmanager-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "print-binary", - aar = ":print-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "slidingpanelayout-binary", - aar = ":slidingpanelayout-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "swiperefreshlayout-binary", - aar = ":swiperefreshlayout-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "vectordrawable-binary", - aar = ":vectordrawable-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "vectordrawable-animated-binary", - aar = ":vectordrawable-animated-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "versionedparcelable-binary", - aar = ":versionedparcelable-binary-aar", -) - -fb_native.android_prebuilt_aar( - name = "viewpager-binary", - aar = ":viewpager-binary-aar", -) - -# Remote files -fb_native.remote_file( - name = "annotation.jar", - sha1 = "2dfd8f6b2a8fc466a1ae4e329fb79cd580f6393f", - url = "mvn:androidx.annotation:annotation:jar:1.0.1", -) - -fb_native.remote_file( - name = "appcompat-binary-aar", - sha1 = "002533a36c928bb27a3cc6843a25f83754b3c3ae", - url = "mvn:androidx.appcompat:appcompat:aar:1.0.2", -) - -fb_native.remote_file( - name = "asynclayoutinflater-binary-aar", - sha1 = "5ffa788d19a6863799f25cb50d4fdfb0ec649037", - url = "mvn:androidx.asynclayoutinflater:asynclayoutinflater:aar:1.0.0", -) - -fb_native.remote_file( - name = "collection-binary.jar", - sha1 = "42858b26cafdaa69b6149f45dfc2894007bc2c7a", - url = "mvn:androidx.collection:collection:jar:1.0.0", -) - -fb_native.remote_file( - name = "core-binary-aar", - sha1 = "263deba7f9c24bd0cefb93c0aaaf402cc50828ee", - url = "mvn:androidx.core:core:aar:1.0.1", -) - -fb_native.remote_file( - name = "core-common-binary.jar", - sha1 = "bb21b9a11761451b51624ac428d1f1bb5deeac38", - url = "mvn:androidx.arch.core:core-common:jar:2.0.0", -) - -fb_native.remote_file( - name = "core-runtime-binary-aar", - sha1 = "c5be9edf9ca9135a465d23939f6e7d0e1cf90b41", - url = "mvn:androidx.arch.core:core-runtime:aar:2.0.0", -) - -fb_native.remote_file( - name = "coordinatorlayout-binary-aar", - sha1 = "7664385a7e39112b780baf8819ee880dcd3c4094", - url = "mvn:androidx.coordinatorlayout:coordinatorlayout:aar:1.0.0", -) - -fb_native.remote_file( - name = "cursoradapter-binary-aar", - sha1 = "74014983a86b83cbce534dec4e7aa9312f5f5d82", - url = "mvn:androidx.cursoradapter:cursoradapter:aar:1.0.0", -) - -fb_native.remote_file( - name = "customview-binary-aar", - sha1 = "30f5ff6075d112f8076e733b24410e68159735b6", - url = "mvn:androidx.customview:customview:aar:1.0.0", -) - -fb_native.remote_file( - name = "documentfile-binary-aar", - sha1 = "66104345c90cd8c2fd5ad2d3aad692b280e10c32", - url = "mvn:androidx.documentfile:documentfile:aar:1.0.0", -) - -fb_native.remote_file( - name = "drawerlayout-binary-aar", - sha1 = "dd02c7e207136e1272b33815cc61e57676ed13a2", - url = "mvn:androidx.drawerlayout:drawerlayout:aar:1.0.0", -) - -fb_native.remote_file( - name = "fragment-binary-aar", - sha1 = "0b40f6a2ae814f72d1e71a5df6dc1283c00cd52f", - url = "mvn:androidx.fragment:fragment:aar:1.0.0", -) - -fb_native.remote_file( - name = "interpolator-binary-aar", - sha1 = "8a01fa254a23b9388571eb6334b03707c7d122d7", - url = "mvn:androidx.interpolator:interpolator:aar:1.0.0", -) - -fb_native.remote_file( - name = "legacy-support-core-ui-binary-aar", - sha1 = "61a264f996046e059f889914050fae1e75d3b702", - url = "mvn:androidx.legacy:legacy-support-core-ui:aar:1.0.0", -) - -fb_native.remote_file( - name = "legacy-support-core-utils-binary-aar", - sha1 = "9b9570042115da8629519090dfeb71df75da59fc", - url = "mvn:androidx.legacy:legacy-support-core-utils:aar:1.0.0", -) - -fb_native.remote_file( - name = "lifecycle-common-binary.jar", - sha1 = "e070ffae07452331bc5684734fce6831d531785c", - url = "mvn:androidx.lifecycle:lifecycle-common:jar:2.0.0", -) - -fb_native.remote_file( - name = "lifecycle-livedata-binary-aar", - sha1 = "c17007cd0b21d6401910b0becdd16c438c68a9af", - url = "mvn:androidx.lifecycle:lifecycle-livedata:aar:2.0.0", -) - -fb_native.remote_file( - name = "lifecycle-livedata-core-binary-aar", - sha1 = "1a7cee84b43fa935231b016f0665cd56a72fa9db", - url = "mvn:androidx.lifecycle:lifecycle-livedata-core:aar:2.0.0", -) - -fb_native.remote_file( - name = "lifecycle-runtime-binary-aar", - sha1 = "ea27e9e79e9a0fbedfa4dbbef5ddccf0e1d9d73f", - url = "mvn:androidx.lifecycle:lifecycle-runtime:aar:2.0.0", -) - -fb_native.remote_file( - name = "lifecycle-viewmodel-binary-aar", - sha1 = "6417c576c458137456d996914c50591e7f4acc24", - url = "mvn:androidx.lifecycle:lifecycle-viewmodel:aar:2.0.0", -) - -fb_native.remote_file( - name = "loader-binary-aar", - sha1 = "8af8b6cec0da85c207d03e15840e0722cbc71e70", - url = "mvn:androidx.loader:loader:aar:1.0.0", -) - -fb_native.remote_file( - name = "localbroadcastmanager-binary-aar", - sha1 = "2734f31c8321e83ce6b60570d14777fc33cc2ece", - url = "mvn:androidx.localbroadcastmanager:localbroadcastmanager:aar:1.0.0", -) - -fb_native.remote_file( - name = "print-binary-aar", - sha1 = "7722094652c48ebe27acc94d74a55e759e4635ff", - url = "mvn:androidx.print:print:aar:1.0.0", -) - -fb_native.remote_file( - name = "slidingpanelayout-binary-aar", - sha1 = "37eba9ccbf09b75cc4aa78a5e182d5b8ba79ad6a", - url = "mvn:androidx.slidingpanelayout:slidingpanelayout:aar:1.0.0", -) - -fb_native.remote_file( - name = "swiperefreshlayout-binary-aar", - sha1 = "4fd265b80a2b0fbeb062ab2bc4b1487521507762", - url = "mvn:androidx.swiperefreshlayout:swiperefreshlayout:aar:1.0.0", -) - -fb_native.remote_file( - name = "vectordrawable-binary-aar", - sha1 = "33d1eb71849dffbad12add134a25eb63cad4a1eb", - url = "mvn:androidx.vectordrawable:vectordrawable:aar:1.0.1", -) - -fb_native.remote_file( - name = "vectordrawable-animated-binary-aar", - sha1 = "0a41681ac4e1747f87237e489699089ad46b7a5e", - url = "mvn:androidx.vectordrawable:vectordrawable-animated:aar:1.0.0", -) - -fb_native.remote_file( - name = "versionedparcelable-binary-aar", - sha1 = "52718baf7e51ccba173b468a1034caba8140752e", - url = "mvn:androidx.versionedparcelable:versionedparcelable:aar:1.0.0", -) - -fb_native.remote_file( - name = "viewpager-binary-aar", - sha1 = "1f90e13820f96c2fb868f9674079a551678d68b2", - url = "mvn:androidx.viewpager:viewpager:aar:1.0.0", -) diff --git a/ReactAndroid/src/main/third-party/android/support/v7/appcompat/BUCK b/ReactAndroid/src/main/third-party/android/support/v7/appcompat/BUCK deleted file mode 100644 index d2521c4d03ad40..00000000000000 --- a/ReactAndroid/src/main/third-party/android/support/v7/appcompat/BUCK +++ /dev/null @@ -1,62 +0,0 @@ -load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_android_resource", "rn_genrule", "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 -# While BUCK behaves properly and extracts them into androidx.appcompat package. -# We want to support both Gradle and BUCK builds so we hack a bit how BUCK extracts resources. -# Besides that we still need JAVA classes from appcompat-v7.aar, that is why rn_android_library -# extracts classes.jar but the trick is that we can't take full appcompat.aar because resources -# extracted from it by BUCK would conflict with resources we use under Gradelified package -# All this mumbo jumbo will go away after t10182713 - -rn_android_library( - name = "appcompat", - visibility = [ - "PUBLIC", - ], - deps = [ - ":res-for-appcompat", - ], - exported_deps = [ - ":classes-for-react-native", - ], -) - -# still used by appcompat library internally, so we need both during the build -rn_android_resource( - name = "res-for-appcompat", - package = "androidx.appcompat", - res = ":res-unpacker-cmd", - visibility = ["//ReactAndroid/..."], -) - -rn_prebuilt_jar( - name = "classes-for-react-native", - binary_jar = ":classes-unpacker-cmd", - visibility = ["//ReactAndroid/..."], -) - -rn_genrule( - name = "classes-unpacker-cmd", - out = "classes.jar", - cmd = "$(exe :aar-unpacker) $(location :appcompat-binary-aar) classes.jar $OUT", -) - -rn_genrule( - name = "res-unpacker-cmd", - out = "res", - cmd = "$(exe :aar-unpacker) $(location :appcompat-binary-aar) res/ $OUT", - visibility = ["//ReactAndroid/..."], -) - -fb_native.python_binary( - name = "aar-unpacker", - main = "aar-unpacker.py", -) - -fb_native.remote_file( - name = "appcompat-binary-aar", - sha1 = "002533a36c928bb27a3cc6843a25f83754b3c3ae", - url = "mvn:androidx.appcompat:appcompat:aar:1.0.2", -) diff --git a/ReactAndroid/src/main/third-party/android/support/v7/appcompat/aar-unpacker.py b/ReactAndroid/src/main/third-party/android/support/v7/appcompat/aar-unpacker.py deleted file mode 100644 index ddb65efb21927e..00000000000000 --- a/ReactAndroid/src/main/third-party/android/support/v7/appcompat/aar-unpacker.py +++ /dev/null @@ -1,20 +0,0 @@ -import contextlib -import os -import shutil -import sys -import tempfile -import zipfile - -# Helper that unpacks the contents of an .aar file -# into given destination. - -@contextlib.contextmanager -def cleanup(path): - yield path - shutil.rmtree(path) - -if __name__ == '__main__': - with zipfile.ZipFile(sys.argv[1], 'r') as z: - with cleanup(tempfile.mkdtemp()) as temp_path: - z.extractall(temp_path, filter(lambda n: n.startswith(sys.argv[2]), z.namelist())) - shutil.move(os.path.join(temp_path, sys.argv[2]), sys.argv[3]) diff --git a/ReactAndroid/src/main/third-party/java/asm/BUCK b/ReactAndroid/src/main/third-party/java/asm/BUCK index f344506a49ca34..5741e1c0ea7998 100644 --- a/ReactAndroid/src/main/third-party/java/asm/BUCK +++ b/ReactAndroid/src/main/third-party/java/asm/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "asm", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":asm-analysis", diff --git a/ReactAndroid/src/main/third-party/java/fest/BUCK b/ReactAndroid/src/main/third-party/java/fest/BUCK index 10f995f166d306..50285d715060a0 100644 --- a/ReactAndroid/src/main/third-party/java/fest/BUCK +++ b/ReactAndroid/src/main/third-party/java/fest/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "fest", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":fest-core", diff --git a/ReactAndroid/src/main/third-party/java/junit/BUCK b/ReactAndroid/src/main/third-party/java/junit/BUCK index 9f4cbec6221d28..555a01989f107f 100644 --- a/ReactAndroid/src/main/third-party/java/junit/BUCK +++ b/ReactAndroid/src/main/third-party/java/junit/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "junit", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":hamcrest", diff --git a/ReactAndroid/src/main/third-party/java/mockito/BUCK b/ReactAndroid/src/main/third-party/java/mockito/BUCK index a7f91609227a4c..9fda3bf174d9d6 100644 --- a/ReactAndroid/src/main/third-party/java/mockito/BUCK +++ b/ReactAndroid/src/main/third-party/java/mockito/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "mockito", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":mockito-core", diff --git a/ReactAndroid/src/main/third-party/java/mockito2/BUCK b/ReactAndroid/src/main/third-party/java/mockito2/BUCK index 4d2ea058b7713f..b5332e4f2ec559 100644 --- a/ReactAndroid/src/main/third-party/java/mockito2/BUCK +++ b/ReactAndroid/src/main/third-party/java/mockito2/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "mockito2", + autoglob = False, visibility = ["PUBLIC"], exported_deps = [ ":byte-buddy", diff --git a/ReactAndroid/src/main/third-party/java/okhttp/BUCK b/ReactAndroid/src/main/third-party/java/okhttp/BUCK index a19336522a9b90..90b3f3f9f84c07 100644 --- a/ReactAndroid/src/main/third-party/java/okhttp/BUCK +++ b/ReactAndroid/src/main/third-party/java/okhttp/BUCK @@ -9,8 +9,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "okhttp3-binary.jar", - sha1 = "d3e1ce1d2b3119adf270b2d00d947beb03fe3321", - url = "mvn:com.squareup.okhttp3:okhttp:jar:3.12.12", + sha1 = "3e6d101343c7ea687cd593e4990f73b25c878383", + url = "mvn:com.squareup.okhttp3:okhttp:jar:3.14.9", ) rn_prebuilt_jar( @@ -21,6 +21,6 @@ rn_prebuilt_jar( fb_native.remote_file( name = "okhttp3-urlconnection-binary.jar", - sha1 = "3cfbe11fb8c48d30600a70f90b3283fc858aea72", - url = "mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.12.12", + sha1 = "c9a3b45b815cf2982415ec8145339f5af58989c3", + url = "mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.14.9", ) diff --git a/ReactAndroid/src/main/third-party/java/okio/BUCK b/ReactAndroid/src/main/third-party/java/okio/BUCK index e244efaa9aca28..e62ba43e228b15 100644 --- a/ReactAndroid/src/main/third-party/java/okio/BUCK +++ b/ReactAndroid/src/main/third-party/java/okio/BUCK @@ -9,6 +9,6 @@ rn_prebuilt_jar( fb_native.remote_file( name = "okio-binary.jar", - sha1 = "bc28b5a964c8f5721eb58ee3f3c47a9bcbf4f4d8", - url = "mvn:com.squareup.okio:okio:jar:1.15.0", + sha1 = "34336f82f14dde1c0752fd5f0546dbf3c3225aba", + url = "mvn:com.squareup.okio:okio:jar:1.17.5", ) diff --git a/ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK b/ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK similarity index 74% rename from ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK rename to ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK index aeca8ed4f5bd3a..39db5c323fe735 100644 --- a/ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK +++ b/ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK @@ -3,9 +3,10 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "robolectric", + autoglob = False, visibility = ["PUBLIC"], exported_deps = [ - ":android-all-4.1.2_r1-robolectric-r1", + ":android-all-5.0.2_r3-robolectric-r0", ":bouncycastle", ":guava", ":javax-annotation-api", @@ -28,8 +29,9 @@ rn_android_library( ], ) +# This is based on the minimum SDK version for tests: 21. rn_prebuilt_jar( - name = "android-all-4.1.2_r1-robolectric-r1", # name defines filename used by robolectric in runtime + name = "android-all-5.0.2_r3-robolectric-r0", # name defines filename used by robolectric in runtime binary_jar = ":robolectric-android-all-binary.jar", visibility = ["//ReactAndroid/..."], ) @@ -39,13 +41,13 @@ rn_prebuilt_jar( fb_native.export_file( name = "robolectric-android-all-binary.jar", src = ":robolectric-android-all-binary-remote.jar", - out = "../android-all-4.1.2_r1-robolectric-r1.jar", # name defines filename used by robolectric in runtime + out = "../android-all-5.0.2_r3-robolectric-r0.jar", # name defines filename used by robolectric in runtime ) fb_native.remote_file( name = "robolectric-android-all-binary-remote.jar", - sha1 = "8355a2da59fe0233ca45070ca32f08da98d0b806", - url = "mvn:org.robolectric:android-all:jar:4.1.2_r1-robolectric-r1", + sha1 = "ae6e8f47f73ffe34054852d9c7f4f4ec489254f1", + url = "mvn:org.robolectric:android-all:jar:5.0.2_r3-robolectric-r0", ) rn_prebuilt_jar( @@ -56,8 +58,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "bouncycastle-binary.jar", - sha1 = "2507204241ab450456bdb8e8c0a8f986e418bd99", - url = "mvn:org.bouncycastle:bcprov-jdk15on:jar:1.59", + sha1 = "320b989112f00a63a3bcfa5a98f31a4f865a20fa", + url = "mvn:org.bouncycastle:bcprov-jdk15on:jar:1.65", ) rn_prebuilt_jar( @@ -79,8 +81,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4.jar", - sha1 = "66e4550b96285eadcb5a45a21ad6fbe8842fa960", - url = "mvn:org.robolectric:robolectric:jar:4.3", + sha1 = "418c5bfae392fdbf71cd463a42a3e8c3b839a924", + url = "mvn:org.robolectric:robolectric:jar:4.4", ) rn_prebuilt_jar( @@ -90,8 +92,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-annotations.jar", - sha1 = "3db63d633be908a18db18615b594f824c034ae6d", - url = "mvn:org.robolectric:annotations:jar:4.3", + sha1 = "70fc5b1699467dfd7de606fc6c02ff9fc1816d9f", + url = "mvn:org.robolectric:annotations:jar:4.4", ) rn_prebuilt_jar( @@ -101,8 +103,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-junit.jar", - sha1 = "fcafc9942e8748c8bab832b022672ca21808c492", - url = "mvn:org.robolectric:junit:jar:4.3", + sha1 = "fbcda51d8e6f3a3897ae5cedc7aa481815745290", + url = "mvn:org.robolectric:junit:jar:4.4", ) rn_prebuilt_jar( @@ -112,8 +114,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-pluginapi.jar", - sha1 = "128acea3aed3bbe36f8fde865f3a26b920237718", - url = "mvn:org.robolectric:pluginapi:jar:4.3", + sha1 = "1ee94260f8c51620a35eac33fc1efc01350c751f", + url = "mvn:org.robolectric:pluginapi:jar:4.4", ) rn_prebuilt_jar( @@ -123,8 +125,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-plugins-maven-dependency-resolver.jar", - sha1 = "b1ea126cb80dbba0c2947be9234bbe2877ce2a09", - url = "mvn:org.robolectric:plugins-maven-dependency-resolver:jar:4.3", + sha1 = "9241a3c4bd01627447c76d9b67614808c78ffdd9", + url = "mvn:org.robolectric:plugins-maven-dependency-resolver:jar:4.4", ) rn_prebuilt_jar( @@ -134,8 +136,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-resources.jar", - sha1 = "e40030b0f6808ca378bd2c803713157ee4287ea0", - url = "mvn:org.robolectric:resources:jar:4.3", + sha1 = "a2ee1324bcb62724e6cbfa655bdb5683948a554c", + url = "mvn:org.robolectric:resources:jar:4.4", ) rn_prebuilt_jar( @@ -145,8 +147,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-sandbox.jar", - sha1 = "2302e406aebab5f6843dbf6c2f21952fa86ec26f", - url = "mvn:org.robolectric:sandbox:jar:4.3", + sha1 = "03cedd73c5aedaf79fb9a593552816c9fb3282f2", + url = "mvn:org.robolectric:sandbox:jar:4.4", ) rn_prebuilt_jar( @@ -156,8 +158,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-shadowapi.jar", - sha1 = "81dfcf4a45b623b7744e46358d01c7ce054d0fff", - url = "mvn:org.robolectric:shadowapi:jar:4.3", + sha1 = "529649474b53cf8f6f4a483044ade43aebed8a4c", + url = "mvn:org.robolectric:shadowapi:jar:4.4", ) rn_prebuilt_jar( @@ -167,8 +169,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-shadows-framework.jar", - sha1 = "150103d5732c432906f6130b734e7452855dd67b", - url = "mvn:org.robolectric:shadows-framework:jar:4.3", + sha1 = "90028766e71353ad6f57d7bcb56ac0d861da18c3", + url = "mvn:org.robolectric:shadows-framework:jar:4.4", ) rn_prebuilt_jar( @@ -178,8 +180,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-utils.jar", - sha1 = "97b0331b67d0e1dc8bf50e570b6feb017f62aed1", - url = "mvn:org.robolectric:utils:jar:4.3", + sha1 = "c54b2638d64e7bd4e1e45c4fe8038305402bd711", + url = "mvn:org.robolectric:utils:jar:4.4", ) rn_prebuilt_jar( @@ -189,8 +191,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-utils-reflector.jar", - sha1 = "3428887d068b66e33026ac533ae4647355167658", - url = "mvn:org.robolectric:utils-reflector:jar:4.3", + sha1 = "44c40ac0d2ef1e7c8b0f6c4e224ef26d356170f1", + url = "mvn:org.robolectric:utils-reflector:jar:4.4", ) rn_prebuilt_jar( diff --git a/ReactAndroid/src/main/third-party/java/sqlite/BUCK b/ReactAndroid/src/main/third-party/java/sqlite/BUCK index 7fd47e8a19d975..f93cb4833b10b5 100644 --- a/ReactAndroid/src/main/third-party/java/sqlite/BUCK +++ b/ReactAndroid/src/main/third-party/java/sqlite/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "sqlite", + autoglob = False, visibility = ["//ReactAndroid/..."], exported_deps = [ ":sqlite4java", diff --git a/ReactAndroid/src/test/java/com/facebook/common/logging/BUCK b/ReactAndroid/src/test/java/com/facebook/common/logging/BUCK index b315429ee1af2a..71326c7077e3b6 100644 --- a/ReactAndroid/src/test/java/com/facebook/common/logging/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/common/logging/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_libra rn_android_library( name = "logging", srcs = glob(["**/*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK index 2721f9cb923f4a..5e38c0242eb624 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK @@ -10,12 +10,13 @@ rn_android_library( ["*.java"], exclude = STANDARD_TEST_SRCS, ), + autoglob = False, visibility = [ "PUBLIC", ], deps = [ react_native_android_toplevel_dep("third-party/java/mockito2:mockito2"), - react_native_dep("third-party/java/robolectric/4.3.1:robolectric"), + react_native_dep("third-party/java/robolectric/4.4:robolectric"), react_native_target("java/com/facebook/react/bridge:bridge"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_tests_target("java/org/mockito/configuration:configuration"), diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/SimpleViewPropertyTest.java b/ReactAndroid/src/test/java/com/facebook/react/uimanager/SimpleViewPropertyTest.java index ed1d23990e437b..91be74945d9c9b 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/SimpleViewPropertyTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/SimpleViewPropertyTest.java @@ -36,6 +36,8 @@ public class SimpleViewPropertyTest { @Rule public PowerMockRule rule = new PowerMockRule(); + private static int sViewTag = 2; + private static class ConcreteViewManager extends SimpleViewManager { @ReactProp(name = "foo") @@ -75,7 +77,9 @@ public ReactStylesDiffMap buildStyles(Object... keysAndValues) { @Test public void testOpacity() { - View view = mManager.createView(mThemedContext, buildStyles(), null, new JSResponderHandler()); + View view = + mManager.createView( + sViewTag, mThemedContext, buildStyles(), null, new JSResponderHandler()); mManager.updateProperties(view, buildStyles()); assertThat(view.getAlpha()).isEqualTo(1.0f); @@ -89,7 +93,9 @@ public void testOpacity() { @Test public void testBackgroundColor() { - View view = mManager.createView(mThemedContext, buildStyles(), null, new JSResponderHandler()); + View view = + mManager.createView( + sViewTag, mThemedContext, buildStyles(), null, new JSResponderHandler()); mManager.updateProperties(view, buildStyles()); assertThat(view.getBackground()).isEqualTo(null); diff --git a/ReactAndroid/src/test/java/org/mockito/configuration/BUCK b/ReactAndroid/src/test/java/org/mockito/configuration/BUCK index a29174b85a037e..ed96ae2d0653cf 100644 --- a/ReactAndroid/src/test/java/org/mockito/configuration/BUCK +++ b/ReactAndroid/src/test/java/org/mockito/configuration/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "react_native_android_toplevel_dep", rn_android_library( name = "configuration", srcs = glob(["**/*.java"]), + autoglob = False, visibility = [ "PUBLIC", ], diff --git a/ReactAndroid/src/test/resources/BUCK b/ReactAndroid/src/test/resources/BUCK new file mode 100644 index 00000000000000..af94e7bada4fd2 --- /dev/null +++ b/ReactAndroid/src/test/resources/BUCK @@ -0,0 +1,17 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +java_library( + name = "robolectric", + srcs = [], + labels = [ + "supermodule:xplat/default/public.react_native.infra", + ], + resources = [ + "robolectric.properties", + ], + resources_root = ".", + visibility = ["PUBLIC"], +) diff --git a/ReactAndroid/src/test/resources/robolectric.properties b/ReactAndroid/src/test/resources/robolectric.properties new file mode 100644 index 00000000000000..b0d79302d02b6a --- /dev/null +++ b/ReactAndroid/src/test/resources/robolectric.properties @@ -0,0 +1,2 @@ +# Set this to minimum supported API level for React Native. +sdk=21 diff --git a/ReactCommon/React-Fabric.podspec b/ReactCommon/React-Fabric.podspec index 1937e45d71b0b6..808158d0a3c0cb 100644 --- a/ReactCommon/React-Fabric.podspec +++ b/ReactCommon/React-Fabric.podspec @@ -18,7 +18,7 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2020.01.13.00' -folly_dep_name = 'Folly/Fabric' +folly_dep_name = 'RCT-Folly/Fabric' boost_compiler_flags = '-Wno-documentation' Pod::Spec.new do |s| @@ -28,9 +28,8 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source - s.prepare_command = File.read("../scripts/generate-rncore.sh") s.source_files = "dummyFile.cpp" s.library = "stdc++" s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", @@ -44,12 +43,21 @@ Pod::Spec.new do |s| s.dependency "ReactCommon/turbomodule/core", version s.dependency "React-jsi", version + s.subspec "animations" do |ss| + ss.dependency folly_dep_name, folly_version + ss.compiler_flags = folly_compiler_flags + ss.source_files = "react/renderer/animations/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/animations/tests" + ss.header_dir = "react/renderer/animations" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + s.subspec "attributedstring" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/attributedstring/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*" - ss.header_dir = "react/attributedstring" + ss.source_files = "react/renderer/attributedstring/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/attributedstring/tests" + ss.header_dir = "react/renderer/attributedstring" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end @@ -57,13 +65,13 @@ Pod::Spec.new do |s| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags ss.source_files = "better/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*" + ss.exclude_files = "better/tests" ss.header_dir = "better" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "config" do |ss| - ss.source_files = "config/*.{m,mm,cpp,h}" + ss.source_files = "react/config/*.{m,mm,cpp,h}" ss.header_dir = "react/config" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"" } end @@ -71,121 +79,145 @@ Pod::Spec.new do |s| s.subspec "core" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - ss.source_files = "fabric/core/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/**/*" - ss.header_dir = "react/core" + ss.source_files = "react/renderer/core/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/core/tests" + ss.header_dir = "react/renderer/core" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end + s.subspec "componentregistry" do |ss| + ss.dependency folly_dep_name, folly_version + ss.compiler_flags = folly_compiler_flags + ss.source_files = "react/renderer/componentregistry/**/*.{m,mm,cpp,h}" + ss.header_dir = "react/renderer/componentregistry" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + s.subspec "components" do |ss| ss.subspec "activityindicator" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/activityindicator/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/activityindicator" + sss.source_files = "react/renderer/components/activityindicator/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/activityindicator/tests" + sss.header_dir = "react/renderer/components/activityindicator" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "image" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/image/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/image" + sss.source_files = "react/renderer/components/image/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/image/tests" + sss.header_dir = "react/renderer/components/image" + sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + + ss.subspec "inputaccessory" do |sss| + sss.dependency folly_dep_name, folly_version + sss.compiler_flags = folly_compiler_flags + sss.source_files = "react/renderer/components/inputaccessory/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/inputaccessory/tests" + sss.header_dir = "react/renderer/components/inputaccessory" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "legacyviewmanagerinterop" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/legacyviewmanagerinterop/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/legacyviewmanagerinterop" + sss.source_files = "react/renderer/components/legacyviewmanagerinterop/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/legacyviewmanagerinterop/tests" + sss.header_dir = "react/renderer/components/legacyviewmanagerinterop" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/Headers/Private/React-Core\"" } end ss.subspec "modal" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/modal/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/modal" + sss.source_files = "react/renderer/components/modal/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/modal/tests" + sss.header_dir = "react/renderer/components/modal" + sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + + ss.subspec "picker" do |sss| + sss.dependency folly_dep_name, folly_version + sss.compiler_flags = folly_compiler_flags + sss.source_files = "react/renderer/components/picker/iospicker/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/picker/iospicker/tests" + sss.header_dir = "react/renderer/components/iospicker" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "rncore" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/rncore/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*", "fabric/components/rncore/*Tests.{h,cpp}", - # TODO: These should be re-enabled later when Codegen Native Module support is needed. - "fabric/components/rncore/rncore-generated.mm", "fabric/components/rncore/NativeModules.{h,cpp}" - sss.header_dir = "react/components/rncore" + sss.source_files = "react/renderer/components/rncore/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/rncore/tests" + sss.header_dir = "react/renderer/components/rncore" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "root" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/root/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/root" + sss.source_files = "react/renderer/components/root/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/root/tests" + sss.header_dir = "react/renderer/components/root" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "safeareaview" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/safeareaview/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/safeareaview" + sss.source_files = "react/renderer/components/safeareaview/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/safeareaview/tests" + sss.header_dir = "react/renderer/components/safeareaview" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "scrollview" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/scrollview/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/scrollview" + sss.source_files = "react/renderer/components/scrollview/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/scrollview/tests" + sss.header_dir = "react/renderer/components/scrollview" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "slider" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/slider/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*", - "**/android/*" - sss.header_dir = "react/components/slider" + sss.source_files = "react/renderer/components/slider/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/slider/tests/**/*", + "react/renderer/components/slider/platform/android" + sss.header_dir = "react/renderer/components/slider" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "text" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/text/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/text" + sss.source_files = "react/renderer/components/text/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/text/tests" + sss.header_dir = "react/renderer/components/text" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "textinput" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/textinput/iostextinput/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/iostextinput" + sss.source_files = "react/renderer/components/textinput/iostextinput/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/textinput/iostextinput/tests" + sss.header_dir = "react/renderer/components/iostextinput" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "unimplementedview" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/unimplementedview/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/unimplementedview" + sss.source_files = "react/renderer/components/unimplementedview/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/unimplementedview/tests" + sss.header_dir = "react/renderer/components/unimplementedview" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end @@ -193,9 +225,9 @@ Pod::Spec.new do |s| sss.dependency folly_dep_name, folly_version sss.dependency "Yoga" sss.compiler_flags = folly_compiler_flags - sss.source_files = "fabric/components/view/**/*.{m,mm,cpp,h}" - sss.exclude_files = "**/tests/*" - sss.header_dir = "react/components/view" + sss.source_files = "react/renderer/components/view/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/view/tests" + sss.header_dir = "react/renderer/components/view" sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end end @@ -203,9 +235,9 @@ Pod::Spec.new do |s| s.subspec "debug" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/debug/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*" - ss.header_dir = "react/debug" + ss.source_files = "react/renderer/debug/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/debug/tests" + ss.header_dir = "react/renderer/debug" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end @@ -213,45 +245,64 @@ Pod::Spec.new do |s| ss.dependency "React-RCTImage", version ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/imagemanager/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*", - "**/android/*", - "**/cxx/*" - ss.header_dir = "react/imagemanager" + ss.source_files = "react/renderer/imagemanager/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/imagemanager/tests", + "react/renderer/imagemanager/platform/android", + "react/renderer/imagemanager/platform/cxx" + ss.header_dir = "react/renderer/imagemanager" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "mounting" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/mounting/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*" - ss.header_dir = "react/mounting" + ss.source_files = "react/renderer/mounting/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/mounting/tests" + ss.header_dir = "react/renderer/mounting" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + + s.subspec "scheduler" do |ss| + ss.dependency folly_dep_name, folly_version + ss.compiler_flags = folly_compiler_flags + ss.source_files = "react/renderer/scheduler/**/*.{m,mm,cpp,h}" + ss.header_dir = "react/renderer/scheduler" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end + + s.subspec "templateprocessor" do |ss| + ss.dependency folly_dep_name, folly_version + ss.compiler_flags = folly_compiler_flags + ss.source_files = "react/renderer/templateprocessor/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/templateprocessor/tests" + ss.header_dir = "react/renderer/templateprocessor" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "textlayoutmanager" do |ss| ss.dependency folly_dep_name, folly_version + ss.dependency "React-Fabric/uimanager" ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/textlayoutmanager/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*", - "**/android/*", - "**/cxx/*" - ss.header_dir = "react/textlayoutmanager" + ss.source_files = "react/renderer/textlayoutmanager/platform/ios/**/*.{m,mm,cpp,h}", + "react/renderer/textlayoutmanager/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/textlayoutmanager/tests", + "react/renderer/textlayoutmanager/platform/android", + "react/renderer/textlayoutmanager/platform/cxx" + ss.header_dir = "react/renderer/textlayoutmanager" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "uimanager" do |ss| ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "fabric/uimanager/**/*.{m,mm,cpp,h}" - ss.exclude_files = "**/tests/*", - ss.header_dir = "react/uimanager" + ss.source_files = "react/renderer/uimanager/**/*.{m,mm,cpp,h}" + ss.exclude_files = "react/renderer/uimanager/tests" + ss.header_dir = "react/renderer/uimanager" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "utils" do |ss| - ss.source_files = "utils/*.{m,mm,cpp,h}" + ss.source_files = "react/utils/*.{m,mm,cpp,h}" ss.header_dir = "react/utils" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index bad800f338c274..e4b34411605933 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -28,7 +28,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.header_dir = "ReactCommon" # Use global header_dir for all subspecs for use_frameworks! compatibility s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags @@ -36,6 +36,8 @@ Pod::Spec.new do |s| "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++14" } + # TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..." + # Note: Update this only when ready to minimize breaking changes. s.subspec "turbomodule" do |ss| ss.dependency "React-callinvoker", version ss.dependency "React-perflogger", version @@ -47,13 +49,13 @@ Pod::Spec.new do |s| ss.dependency "glog" ss.subspec "core" do |sss| - sss.source_files = "turbomodule/core/*.{cpp,h}", - "turbomodule/core/platform/ios/*.{mm,cpp,h}" + sss.source_files = "react/nativemodule/core/ReactCommon/**/*.{cpp,h}", + "react/nativemodule/core/platform/ios/**/*.{mm,cpp,h}" end ss.subspec "samples" do |sss| - sss.source_files = "turbomodule/samples/*.{cpp,h}", - "turbomodule/samples/platform/ios/*.{mm,cpp,h}" + sss.source_files = "react/nativemodule/samples/ReactCommon/**/*.{cpp,h}", + "react/nativemodule/samples/platform/ios/**/*.{mm,cpp,h}" sss.dependency "ReactCommon/turbomodule/core", version end end diff --git a/ReactCommon/callinvoker/React-callinvoker.podspec b/ReactCommon/callinvoker/React-callinvoker.podspec index e2a90d30943353..76aec146d61cdb 100644 --- a/ReactCommon/callinvoker/React-callinvoker.podspec +++ b/ReactCommon/callinvoker/React-callinvoker.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "10.0" } s.source = source s.source_files = "**/*.{cpp,h}" s.header_dir = "ReactCommon" diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 2f2dc5d448d168..d809a87c737734 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -108,6 +108,18 @@ void Instance::loadScriptFromString( } } +bool Instance::isHBCBundle(const char *sourcePath) { + std::ifstream bundle_stream(sourcePath, std::ios_base::in); + BundleHeader header; + + if (!bundle_stream || + !bundle_stream.read(reinterpret_cast(&header), sizeof(header))) { + return false; + } + + return parseTypeFromHeader(header) == ScriptTag::HBCBundle; +} + bool Instance::isIndexedRAMBundle(const char *sourcePath) { std::ifstream bundle_stream(sourcePath, std::ios_base::in); BundleHeader header; diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index f475bf8a7fa72c..7cd11f9bdf50b4 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -56,6 +56,7 @@ class RN_EXPORT Instance { std::unique_ptr string, std::string sourceURL, bool loadSynchronously); + static bool isHBCBundle(const char *sourcePath); static bool isIndexedRAMBundle(const char *sourcePath); static bool isIndexedRAMBundle(std::unique_ptr *string); void loadRAMBundleFromString( diff --git a/ReactCommon/cxxreact/JSBundleType.cpp b/ReactCommon/cxxreact/JSBundleType.cpp index 05bacb4107c7b7..f76610d461a98e 100644 --- a/ReactCommon/cxxreact/JSBundleType.cpp +++ b/ReactCommon/cxxreact/JSBundleType.cpp @@ -13,11 +13,14 @@ namespace facebook { namespace react { static uint32_t constexpr RAMBundleMagicNumber = 0xFB0BD1E5; +static uint32_t constexpr HBCBundleMagicNumber = 0xffe7c3c3; ScriptTag parseTypeFromHeader(const BundleHeader &header) { switch (folly::Endian::little(header.magic)) { case RAMBundleMagicNumber: return ScriptTag::RAMBundle; + case HBCBundleMagicNumber: + return ScriptTag::HBCBundle; default: return ScriptTag::String; } @@ -29,6 +32,8 @@ const char *stringForScriptTag(const ScriptTag &tag) { return "String"; case ScriptTag::RAMBundle: return "RAM Bundle"; + case ScriptTag::HBCBundle: + return "HBC Bundle"; } return ""; } diff --git a/ReactCommon/cxxreact/JSBundleType.h b/ReactCommon/cxxreact/JSBundleType.h index 45a9045818897c..be39711dd8d630 100644 --- a/ReactCommon/cxxreact/JSBundleType.h +++ b/ReactCommon/cxxreact/JSBundleType.h @@ -27,6 +27,7 @@ namespace react { enum struct ScriptTag { String = 0, RAMBundle, + HBCBundle, }; /** diff --git a/ReactCommon/cxxreact/JsArgumentHelpers-inl.h b/ReactCommon/cxxreact/JsArgumentHelpers-inl.h index 72c2d0d2f6b44b..fa76074d0712e5 100644 --- a/ReactCommon/cxxreact/JsArgumentHelpers-inl.h +++ b/ReactCommon/cxxreact/JsArgumentHelpers-inl.h @@ -14,7 +14,7 @@ namespace xplat { namespace detail { template -R jsArg1(const folly::dynamic &arg, M asFoo, const T &... desc) { +R jsArg1(const folly::dynamic &arg, M asFoo, const T &...desc) { try { return (arg.*asFoo)(); } catch (const folly::TypeError &ex) { @@ -35,7 +35,7 @@ template R jsArg( const folly::dynamic &arg, R (folly::dynamic::*asFoo)() const, - const T &... desc) { + const T &...desc) { return detail::jsArg1(arg, asFoo, desc...); } @@ -43,7 +43,7 @@ template R jsArg( const folly::dynamic &arg, R (folly::dynamic::*asFoo)() const &, - const T &... desc) { + const T &...desc) { return detail::jsArg1(arg, asFoo, desc...); } diff --git a/ReactCommon/cxxreact/JsArgumentHelpers.h b/ReactCommon/cxxreact/JsArgumentHelpers.h index 7e9f13934f6a15..25702ba845e5ac 100644 --- a/ReactCommon/cxxreact/JsArgumentHelpers.h +++ b/ReactCommon/cxxreact/JsArgumentHelpers.h @@ -39,12 +39,12 @@ template R jsArg( const folly::dynamic &arg, R (folly::dynamic::*asFoo)() const, - const T &... desc); + const T &...desc); template R jsArg( const folly::dynamic &arg, R (folly::dynamic::*asFoo)() const &, - const T &... desc); + const T &...desc); // This is like jsArg, but a operates on a dynamic representing an array of // arguments. The argument n is used both to index the array and build the diff --git a/ReactCommon/cxxreact/React-cxxreact.podspec b/ReactCommon/cxxreact/React-cxxreact.podspec index b31dfe6359fd7f..b43ff38be4ebcb 100644 --- a/ReactCommon/cxxreact/React-cxxreact.podspec +++ b/ReactCommon/cxxreact/React-cxxreact.podspec @@ -28,7 +28,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0", :tvos => "11.0" } s.source = source s.source_files = "*.{cpp,h}" s.exclude_files = "SampleCxxModule.*" diff --git a/ReactCommon/cxxreact/ReactMarker.cpp b/ReactCommon/cxxreact/ReactMarker.cpp index 52da94e7d08175..1f9ce2bb5f9a87 100644 --- a/ReactCommon/cxxreact/ReactMarker.cpp +++ b/ReactCommon/cxxreact/ReactMarker.cpp @@ -17,6 +17,7 @@ namespace ReactMarker { #endif LogTaggedMarker logTaggedMarker = nullptr; +LogTaggedMarkerWithInstanceKey logTaggedMarkerWithInstanceKey = nullptr; #if __clang__ #pragma clang diagnostic pop diff --git a/ReactCommon/cxxreact/ReactMarker.h b/ReactCommon/cxxreact/ReactMarker.h index cc55b9ac77695a..875f7b29d3984a 100644 --- a/ReactCommon/cxxreact/ReactMarker.h +++ b/ReactCommon/cxxreact/ReactMarker.h @@ -26,14 +26,22 @@ enum ReactMarkerId { NATIVE_MODULE_SETUP_START, NATIVE_MODULE_SETUP_STOP, REGISTER_JS_SEGMENT_START, - REGISTER_JS_SEGMENT_STOP + REGISTER_JS_SEGMENT_STOP, + REACT_INSTANCE_INIT_START, + REACT_INSTANCE_INIT_STOP }; #ifdef __APPLE__ using LogTaggedMarker = std::function; +using LogTaggedMarkerWithInstanceKey = std::function< + void(const ReactMarkerId, const char *tag, const int instanceKey)>; #else typedef void (*LogTaggedMarker)(const ReactMarkerId, const char *tag); +typedef void (*LogTaggedMarkerWithInstanceKey)( + const ReactMarkerId, + const char *tag, + const int instanceKey); #endif #ifndef RN_EXPORT @@ -41,6 +49,7 @@ typedef void (*LogTaggedMarker)(const ReactMarkerId, const char *tag); #endif extern RN_EXPORT LogTaggedMarker logTaggedMarker; +extern RN_EXPORT LogTaggedMarkerWithInstanceKey logTaggedMarkerWithInstanceKey; extern RN_EXPORT void logMarker(const ReactMarkerId markerId); diff --git a/ReactCommon/cxxreact/SystraceSection.h b/ReactCommon/cxxreact/SystraceSection.h index 97f93af0b60b91..3a59f0ed6118e0 100644 --- a/ReactCommon/cxxreact/SystraceSection.h +++ b/ReactCommon/cxxreact/SystraceSection.h @@ -29,7 +29,7 @@ struct ConcreteSystraceSection { template explicit ConcreteSystraceSection( const char *name, - ConvertsToStringPiece &&... args) + ConvertsToStringPiece &&...args) : m_section(TRACE_TAG_REACT_CXX_BRIDGE, name, args...) {} private: @@ -42,7 +42,7 @@ struct DummySystraceSection { template explicit DummySystraceSection( __unused const char *name, - __unused ConvertsToStringPiece &&... args) {} + __unused ConvertsToStringPiece &&...args) {} }; using SystraceSection = DummySystraceSection; #endif diff --git a/ReactCommon/hermes/React-hermes.podspec b/ReactCommon/hermes/React-hermes.podspec new file mode 100644 index 00000000000000..5a01efb3c070cc --- /dev/null +++ b/ReactCommon/hermes/React-hermes.podspec @@ -0,0 +1,53 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) +version = package['version'] + +source = { :git => 'https://github.com/facebook/react-native.git' } +if version == '1000.0.0' + # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. + source[:commit] = `git rev-parse HEAD`.strip +else + source[:tag] = "v#{version}" +end + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2020.01.13.00' +boost_compiler_flags = '-Wno-documentation' + +Pod::Spec.new do |s| + s.name = "React-hermes" + s.version = version + s.summary = "-" # TODO + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Facebook, Inc. and its affiliates" + s.platforms = { :osx => "10.14", :ios => "11.0" } + s.source = source + s.source_files = "executor/*.{cpp,h}", + "inspector/*.{cpp,h}", + "inspector/chrome/*.{cpp,h}", + "inspector/detail/*.{cpp,h}" + s.public_header_files = "executor/HermesExecutorFactory.h" + s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/..\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\"", + "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1", + } + s.header_dir = "reacthermes" + s.dependency "React-cxxreact", version + s.dependency "React-jsi", version + s.dependency "React-jsiexecutor", version + s.dependency "React-jsinspector", version + s.dependency "React-perflogger", version + s.dependency "RCT-Folly", folly_version + s.dependency "RCT-Folly/Futures", folly_version + s.dependency "DoubleConversion" + s.dependency "glog" + s.dependency "hermes-engine" +end diff --git a/ReactCommon/hermes/inspector/Inspector.cpp b/ReactCommon/hermes/inspector/Inspector.cpp index 21b7bd2108de11..1b5a09d356355f 100644 --- a/ReactCommon/hermes/inspector/Inspector.cpp +++ b/ReactCommon/hermes/inspector/Inspector.cpp @@ -85,7 +85,7 @@ namespace debugger = ::facebook::hermes::debugger; */ // TODO: read this out of an env variable or config -static constexpr bool kShouldLog = true; +static constexpr bool kShouldLog = false; // Logging state transitions is done outside of transition() in a macro so that // function and line numbers in the log will be accurate. @@ -132,7 +132,6 @@ Inspector::Inspector( } Inspector::~Inspector() { - // TODO: think about expected detach flow debugger_.setEventObserver(nullptr); } @@ -186,7 +185,7 @@ void Inspector::installConsoleFunction( auto obj = val.getObject(runtime); if (obj.isFunction(runtime)) { auto func = obj.getFunction(runtime); - func.call(runtime, args, count); + func.callWithThis(runtime, *originalConsole, args, count); } } } diff --git a/ReactCommon/hermes/inspector/Inspector.h b/ReactCommon/hermes/inspector/Inspector.h index 3e4612530ea869..a55f1c45b9cfb0 100644 --- a/ReactCommon/hermes/inspector/Inspector.h +++ b/ReactCommon/hermes/inspector/Inspector.h @@ -319,11 +319,6 @@ class Inspector : public facebook::hermes::debugger::EventObserver, facebook::hermes::debugger::Debugger &debugger_; InspectorObserver &observer_; - // All client methods (e.g. enable, setBreakpoint, resume, etc.) are executed - // on executor_ to prevent deadlocking on mutex_. See the implementation for - // more comments on the threading invariants used in this class. - std::unique_ptr executor_; - // All of the following member variables are guarded by mutex_. std::mutex mutex_; std::unique_ptr state_; @@ -360,6 +355,12 @@ class Inspector : public facebook::hermes::debugger::EventObserver, // Are we currently waiting for a debugger to attach, because we // requested 'pauseOnFirstStatement'? bool awaitingDebuggerOnStart_; + + // All client methods (e.g. enable, setBreakpoint, resume, etc.) are executed + // on executor_ to prevent deadlocking on mutex_. See the implementation for + // more comments on the threading invariants used in this class. + // NOTE: This needs to be declared LAST because it should be destroyed FIRST. + std::unique_ptr executor_; }; } // namespace inspector diff --git a/ReactCommon/hermes/inspector/InspectorState.cpp b/ReactCommon/hermes/inspector/InspectorState.cpp index 07e005ede5b497..a52e2ac25f0bbc 100644 --- a/ReactCommon/hermes/inspector/InspectorState.cpp +++ b/ReactCommon/hermes/inspector/InspectorState.cpp @@ -299,9 +299,10 @@ void InspectorState::Running::pushPendingEval( std::shared_ptr> promise, folly::Function resultTransformer) { - PendingEval pendingEval{debugger::Command::eval(src, frameIndex), - promise, - std::move(resultTransformer)}; + PendingEval pendingEval{ + debugger::Command::eval(src, frameIndex), + promise, + std::move(resultTransformer)}; pendingEvals_.emplace(std::move(pendingEval)); @@ -476,9 +477,10 @@ void InspectorState::Paused::pushPendingEval( return; } - PendingEval pendingEval{debugger::Command::eval(src, frameIndex), - promise, - std::move(resultTransformer)}; + PendingEval pendingEval{ + debugger::Command::eval(src, frameIndex), + promise, + std::move(resultTransformer)}; pendingEvals_.emplace(std::move(pendingEval)); hasPendingWork_.notify_one(); } diff --git a/ReactCommon/hermes/inspector/chrome/Connection.cpp b/ReactCommon/hermes/inspector/chrome/Connection.cpp index 980f355c9f4c7a..8af32ff530f1cb 100644 --- a/ReactCommon/hermes/inspector/chrome/Connection.cpp +++ b/ReactCommon/hermes/inspector/chrome/Connection.cpp @@ -93,6 +93,7 @@ class Connection::Impl : public inspector::InspectorObserver, const m::heapProfiler::StartTrackingHeapObjectsRequest &req) override; void handle( const m::heapProfiler::StopTrackingHeapObjectsRequest &req) override; + void handle(const m::heapProfiler::CollectGarbageRequest &req) override; void handle(const m::runtime::EvaluateRequest &req) override; void handle(const m::runtime::GetPropertiesRequest &req) override; void handle(const m::runtime::RunIfWaitingForDebuggerRequest &req) override; @@ -469,6 +470,13 @@ void Connection::Impl::sendSnapshot( message, [this, reportProgress, stopStackTraceCapture]( const debugger::ProgramState &) { + // Stop taking any new traces before sending out the heap snapshot. + if (stopStackTraceCapture) { + getRuntime() + .instrumentation() + .stopTrackingHeapObjectStackTraces(); + } + if (reportProgress) { // A progress notification with finished = true indicates the // snapshot has been captured and is ready to be sent. Our @@ -492,11 +500,6 @@ void Connection::Impl::sendSnapshot( }); getRuntime().instrumentation().createSnapshotToStream(cos); - if (stopStackTraceCapture) { - getRuntime() - .instrumentation() - .stopTrackingHeapObjectStackTraces(); - } }) .via(executor_.get()) .thenValue([this, reqId](auto &&) { @@ -522,7 +525,45 @@ void Connection::Impl::handle( ->executeIfEnabled( "HeapProfiler.startTrackingHeapObjects", [this](const debugger::ProgramState &) { - getRuntime().instrumentation().startTrackingHeapObjectStackTraces(); + getRuntime().instrumentation().startTrackingHeapObjectStackTraces( + [this]( + uint64_t lastSeenObjectId, + std::chrono::microseconds timestamp, + std::vector stats) { + // Send the last object ID notification first. + m::heapProfiler::LastSeenObjectIdNotification note; + note.lastSeenObjectId = lastSeenObjectId; + // The protocol uses milliseconds with a fraction for + // microseconds. + note.timestamp = + static_cast(timestamp.count()) / 1000; + sendNotificationToClient(note); + + m::heapProfiler::HeapStatsUpdateNotification heapStatsNote; + // Flatten the HeapStatsUpdate list. + heapStatsNote.statsUpdate.reserve(stats.size() * 3); + for (const jsi::Instrumentation::HeapStatsUpdate &fragment : + stats) { + // Each triplet is the fragment number, the total count of + // objects for the fragment, and the total size of objects + // for the fragment. + heapStatsNote.statsUpdate.push_back( + static_cast(std::get<0>(fragment))); + heapStatsNote.statsUpdate.push_back( + static_cast(std::get<1>(fragment))); + heapStatsNote.statsUpdate.push_back( + static_cast(std::get<2>(fragment))); + } + assert( + heapStatsNote.statsUpdate.size() == stats.size() * 3 && + "Should be exactly 3x the stats vector"); + // TODO: Chunk this if there are too many fragments to update. + // Unlikely to be a problem in practice unless there's a huge + // amount of allocation and freeing. + sendNotificationToClient(heapStatsNote); + }); + // At this point we need the equivalent of a setInterval, where each + // interval samples the existing }) .via(executor_.get()) .thenValue( @@ -539,6 +580,22 @@ void Connection::Impl::handle( /* stopStackTraceCapture */ true); } +void Connection::Impl::handle( + const m::heapProfiler::CollectGarbageRequest &req) { + const auto id = req.id; + + inspector_ + ->executeIfEnabled( + "HeapProfiler.collectGarbage", + [this](const debugger::ProgramState &) { + getRuntime().instrumentation().collectGarbage("inspector"); + }) + .via(executor_.get()) + .thenValue( + [this, id](auto &&) { sendResponseToClient(m::makeOkResponse(id)); }) + .thenError(sendErrorToClient(req.id)); +} + void Connection::Impl::handle(const m::runtime::EvaluateRequest &req) { auto remoteObjPtr = std::make_shared(); diff --git a/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp b/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp index fa97e98ed87f76..2a71a05640d4c4 100644 --- a/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp +++ b/ReactCommon/hermes/inspector/chrome/MessageTypes.cpp @@ -1,5 +1,5 @@ // Copyright 2004-present Facebook. All Rights Reserved. -// @generated SignedSource<> +// @generated SignedSource<> #include "MessageTypes.h" @@ -44,6 +44,8 @@ std::unique_ptr Request::fromJsonThrowOnError(const std::string &str) { {"Debugger.stepInto", makeUnique}, {"Debugger.stepOut", makeUnique}, {"Debugger.stepOver", makeUnique}, + {"HeapProfiler.collectGarbage", + makeUnique}, {"HeapProfiler.startTrackingHeapObjects", makeUnique}, {"HeapProfiler.stopTrackingHeapObjects", @@ -656,6 +658,27 @@ void debugger::StepOverRequest::accept(RequestHandler &handler) const { handler.handle(*this); } +heapProfiler::CollectGarbageRequest::CollectGarbageRequest() + : Request("HeapProfiler.collectGarbage") {} + +heapProfiler::CollectGarbageRequest::CollectGarbageRequest(const dynamic &obj) + : Request("HeapProfiler.collectGarbage") { + assign(id, obj, "id"); + assign(method, obj, "method"); +} + +dynamic heapProfiler::CollectGarbageRequest::toDynamic() const { + dynamic obj = dynamic::object; + put(obj, "id", id); + put(obj, "method", method); + return obj; +} + +void heapProfiler::CollectGarbageRequest::accept( + RequestHandler &handler) const { + handler.handle(*this); +} + heapProfiler::StartTrackingHeapObjectsRequest::StartTrackingHeapObjectsRequest() : Request("HeapProfiler.startTrackingHeapObjects") {} @@ -1126,6 +1149,52 @@ dynamic heapProfiler::AddHeapSnapshotChunkNotification::toDynamic() const { return obj; } +heapProfiler::HeapStatsUpdateNotification::HeapStatsUpdateNotification() + : Notification("HeapProfiler.heapStatsUpdate") {} + +heapProfiler::HeapStatsUpdateNotification::HeapStatsUpdateNotification( + const dynamic &obj) + : Notification("HeapProfiler.heapStatsUpdate") { + assign(method, obj, "method"); + + dynamic params = obj.at("params"); + assign(statsUpdate, params, "statsUpdate"); +} + +dynamic heapProfiler::HeapStatsUpdateNotification::toDynamic() const { + dynamic params = dynamic::object; + put(params, "statsUpdate", statsUpdate); + + dynamic obj = dynamic::object; + put(obj, "method", method); + put(obj, "params", std::move(params)); + return obj; +} + +heapProfiler::LastSeenObjectIdNotification::LastSeenObjectIdNotification() + : Notification("HeapProfiler.lastSeenObjectId") {} + +heapProfiler::LastSeenObjectIdNotification::LastSeenObjectIdNotification( + const dynamic &obj) + : Notification("HeapProfiler.lastSeenObjectId") { + assign(method, obj, "method"); + + dynamic params = obj.at("params"); + assign(lastSeenObjectId, params, "lastSeenObjectId"); + assign(timestamp, params, "timestamp"); +} + +dynamic heapProfiler::LastSeenObjectIdNotification::toDynamic() const { + dynamic params = dynamic::object; + put(params, "lastSeenObjectId", lastSeenObjectId); + put(params, "timestamp", timestamp); + + dynamic obj = dynamic::object; + put(obj, "method", method); + put(obj, "params", std::move(params)); + return obj; +} + heapProfiler::ReportHeapSnapshotProgressNotification:: ReportHeapSnapshotProgressNotification() : Notification("HeapProfiler.reportHeapSnapshotProgress") {} diff --git a/ReactCommon/hermes/inspector/chrome/MessageTypes.h b/ReactCommon/hermes/inspector/chrome/MessageTypes.h index fdb6270f11a7c4..7778d88dc365d4 100644 --- a/ReactCommon/hermes/inspector/chrome/MessageTypes.h +++ b/ReactCommon/hermes/inspector/chrome/MessageTypes.h @@ -1,5 +1,5 @@ // Copyright 2004-present Facebook. All Rights Reserved. -// @generated SignedSource<<0563169b47d73a70d7540528f28d1d13>> +// @generated SignedSource<> #pragma once @@ -71,6 +71,9 @@ using UnserializableValue = std::string; namespace heapProfiler { struct AddHeapSnapshotChunkNotification; +struct CollectGarbageRequest; +struct HeapStatsUpdateNotification; +struct LastSeenObjectIdNotification; struct ReportHeapSnapshotProgressNotification; struct StartTrackingHeapObjectsRequest; struct StopTrackingHeapObjectsRequest; @@ -97,6 +100,7 @@ struct RequestHandler { virtual void handle(const debugger::StepIntoRequest &req) = 0; virtual void handle(const debugger::StepOutRequest &req) = 0; virtual void handle(const debugger::StepOverRequest &req) = 0; + virtual void handle(const heapProfiler::CollectGarbageRequest &req) = 0; virtual void handle( const heapProfiler::StartTrackingHeapObjectsRequest &req) = 0; virtual void handle( @@ -125,6 +129,7 @@ struct NoopRequestHandler : public RequestHandler { void handle(const debugger::StepIntoRequest &req) override {} void handle(const debugger::StepOutRequest &req) override {} void handle(const debugger::StepOverRequest &req) override {} + void handle(const heapProfiler::CollectGarbageRequest &req) override {} void handle( const heapProfiler::StartTrackingHeapObjectsRequest &req) override {} void handle( @@ -411,6 +416,14 @@ struct debugger::StepOverRequest : public Request { void accept(RequestHandler &handler) const override; }; +struct heapProfiler::CollectGarbageRequest : public Request { + CollectGarbageRequest(); + explicit CollectGarbageRequest(const folly::dynamic &obj); + + folly::dynamic toDynamic() const override; + void accept(RequestHandler &handler) const override; +}; + struct heapProfiler::StartTrackingHeapObjectsRequest : public Request { StartTrackingHeapObjectsRequest(); explicit StartTrackingHeapObjectsRequest(const folly::dynamic &obj); @@ -607,6 +620,23 @@ struct heapProfiler::AddHeapSnapshotChunkNotification : public Notification { std::string chunk; }; +struct heapProfiler::HeapStatsUpdateNotification : public Notification { + HeapStatsUpdateNotification(); + explicit HeapStatsUpdateNotification(const folly::dynamic &obj); + folly::dynamic toDynamic() const override; + + std::vector statsUpdate; +}; + +struct heapProfiler::LastSeenObjectIdNotification : public Notification { + LastSeenObjectIdNotification(); + explicit LastSeenObjectIdNotification(const folly::dynamic &obj); + folly::dynamic toDynamic() const override; + + int lastSeenObjectId{}; + double timestamp{}; +}; + struct heapProfiler::ReportHeapSnapshotProgressNotification : public Notification { ReportHeapSnapshotProgressNotification(); diff --git a/ReactCommon/hermes/inspector/chrome/cli/main.cpp b/ReactCommon/hermes/inspector/chrome/cli/main.cpp index 8a019b8baca5de..3e687be4f36172 100644 --- a/ReactCommon/hermes/inspector/chrome/cli/main.cpp +++ b/ReactCommon/hermes/inspector/chrome/cli/main.cpp @@ -156,8 +156,8 @@ static void sendResponse(const std::string &str) { static std::string readScriptSource(const char *path) { std::ifstream stream(path); - return std::string{std::istreambuf_iterator(stream), - std::istreambuf_iterator()}; + return std::string{ + std::istreambuf_iterator(stream), std::istreambuf_iterator()}; } static std::string getUrl(const char *path) { @@ -228,9 +228,10 @@ static void runScript(const std::string &scriptSource, const std::string &url) { int main(int argc, char **argv) { const char *shortOpts = "l:h"; - const option longOpts[] = {{"log", 1, nullptr, 'l'}, - {"help", 0, nullptr, 'h'}, - {nullptr, 0, nullptr, 0}}; + const option longOpts[] = { + {"log", 1, nullptr, 'l'}, + {"help", 0, nullptr, 'h'}, + {nullptr, 0, nullptr, 0}}; while (true) { int opt = getopt_long(argc, argv, shortOpts, longOpts, nullptr); diff --git a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp index 5f9f96b9bc48b7..c19a5336582447 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.cpp @@ -20,12 +20,17 @@ namespace chrome { namespace detail = facebook::hermes::inspector::detail; -AsyncHermesRuntime::AsyncHermesRuntime() - : runtime_(facebook::hermes::makeHermesRuntime()), - executor_( +AsyncHermesRuntime::AsyncHermesRuntime(bool veryLazy) + : executor_( std::make_unique("async-hermes-runtime")) { using namespace std::placeholders; + auto builder = ::hermes::vm::RuntimeConfig::Builder(); + if (veryLazy) { + builder.withCompilationMode(::hermes::vm::ForceLazyCompilation); + } + runtime_ = facebook::hermes::makeHermesRuntime(builder.build()); + runtime_->global().setProperty( *runtime_, "shouldStop", diff --git a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h index b249746c407622..60a63147fc38b9 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h +++ b/ReactCommon/hermes/inspector/chrome/tests/AsyncHermesRuntime.h @@ -27,7 +27,9 @@ namespace chrome { */ class AsyncHermesRuntime { public: - AsyncHermesRuntime(); + // Create a runtime. If veryLazy, configure the runtime to use completely + // lazy compilation. + AsyncHermesRuntime(bool veryLazy = false); ~AsyncHermesRuntime(); std::shared_ptr runtime() { diff --git a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp index b97bf2cccd414d..e4d857aac3f2b1 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp @@ -44,8 +44,8 @@ namespace { // the already-deallocated connection. class TestContext { public: - TestContext(bool waitForDebugger = false) - : conn_(runtime_.runtime(), waitForDebugger) {} + TestContext(bool waitForDebugger = false, bool veryLazy = false) + : runtime_(veryLazy), conn_(runtime_.runtime(), waitForDebugger) {} ~TestContext() { runtime_.wait(); } @@ -860,9 +860,6 @@ TEST(ConnectionTests, testSetLazyBreakpoint) { SyncConnection &conn = context.conn(); int msgId = 1; - facebook::hermes::HermesRuntime::DebugFlags flags{}; - flags.lazy = true; - asyncRuntime.executeScriptAsync( R"( var a = 1 + 2; @@ -879,8 +876,7 @@ TEST(ConnectionTests, testSetLazyBreakpoint) { foo(); )", - "url", - flags); + "url"); send(conn, msgId++); expectExecutionContextCreated(conn); diff --git a/ReactCommon/hermes/inspector/tools/message_types.txt b/ReactCommon/hermes/inspector/tools/message_types.txt index 7807ac5b01799a..5f009532a9f9d6 100644 --- a/ReactCommon/hermes/inspector/tools/message_types.txt +++ b/ReactCommon/hermes/inspector/tools/message_types.txt @@ -17,10 +17,13 @@ Debugger.stepInto Debugger.stepOut Debugger.stepOver HeapProfiler.addHeapSnapshotChunk +HeapProfiler.collectGarbage HeapProfiler.reportHeapSnapshotProgress HeapProfiler.takeHeapSnapshot HeapProfiler.startTrackingHeapObjects HeapProfiler.stopTrackingHeapObjects +HeapProfiler.heapStatsUpdate +HeapProfiler.lastSeenObjectId Runtime.consoleAPICalled Runtime.evaluate Runtime.executionContextCreated diff --git a/ReactCommon/hermes/inspector/tools/msggen/.babelrc b/ReactCommon/hermes/inspector/tools/msggen/.babelrc index b96eb4c692e218..8ad6d5109ddf39 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/.babelrc +++ b/ReactCommon/hermes/inspector/tools/msggen/.babelrc @@ -5,5 +5,4 @@ } }] ], - "plugins": ["idx"] } diff --git a/ReactCommon/hermes/inspector/tools/msggen/package.json b/ReactCommon/hermes/inspector/tools/msggen/package.json index 8ee113ea68d624..bcd465c61e42eb 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/package.json +++ b/ReactCommon/hermes/inspector/tools/msggen/package.json @@ -33,7 +33,6 @@ }, "dependencies": { "devtools-protocol": "0.0.730699", - "idx": "^2.1.0", "yargs": "^14.2.0" } } diff --git a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock index cf4d9eaa94aa58..47b1dacda9373d 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +++ b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock @@ -2519,11 +2519,6 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -idx@^2.1.0: - version "2.5.6" - resolved "https://registry.yarnpkg.com/idx/-/idx-2.5.6.tgz#1f824595070100ae9ad585c86db08dc74f83a59d" - integrity sha512-WFXLF7JgPytbMgelpRY46nHz5tyDcedJ76pLV+RJWdb8h33bxFq4bdZau38DhNSzk5eVniBf1K3jwfK+Lb5nYA== - ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" diff --git a/ReactCommon/jsi/Android.mk b/ReactCommon/jsi/Android.mk index d6a547cc413a6e..6bc98f1b35fcc9 100644 --- a/ReactCommon/jsi/Android.mk +++ b/ReactCommon/jsi/Android.mk @@ -32,4 +32,8 @@ LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) LOCAL_CFLAGS := -fexceptions -frtti -O3 LOCAL_SHARED_LIBRARIES := libfolly_json libjsc glog +# TODO: Remove this flag when ready. +# Android has this enabled by default, but the flag is still needed for iOS. +LOCAL_CFLAGS += -DRN_FABRIC_ENABLED + include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/jsi/BUCK b/ReactCommon/jsi/BUCK index d4d1e6704575d1..0b732248506f64 100644 --- a/ReactCommon/jsi/BUCK +++ b/ReactCommon/jsi/BUCK @@ -1,7 +1,6 @@ # BUILD FILE SYNTAX: SKYLARK -load("@fbsource//tools/build_defs:default_platform_defs.bzl", "APPLE", "IOS", "MACOSX") -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_xplat_dep", "rn_xplat_cxx_library") +load("//tools/build_defs/oss:rn_defs.bzl", "APPLE", "IOS", "MACOSX", "react_native_xplat_dep", "rn_xplat_cxx_library") rn_xplat_cxx_library( name = "jsi", @@ -80,8 +79,6 @@ rn_xplat_cxx_library( fbobjc_frameworks = [ "$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework", ], - # TODO (T55502220): Remove when iOS 9.0 deprecation is complete everywhere. - fbobjc_target_sdk_version = "9.0", labels = ["supermodule:xplat/default/public.react_native.infra"], platforms = APPLE, visibility = ["PUBLIC"], diff --git a/ReactCommon/jsi/React-jsi.podspec b/ReactCommon/jsi/React-jsi.podspec index 01035d5667e3e4..936188ed90bbc7 100644 --- a/ReactCommon/jsi/React-jsi.podspec +++ b/ReactCommon/jsi/React-jsi.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "**/*.{cpp,h}" s.exclude_files = "**/test/*" diff --git a/ReactCommon/jsi/jsi/CMakeLists.txt b/ReactCommon/jsi/jsi/CMakeLists.txt index d04af0006af915..121d697fd8e76e 100644 --- a/ReactCommon/jsi/jsi/CMakeLists.txt +++ b/ReactCommon/jsi/jsi/CMakeLists.txt @@ -21,6 +21,9 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") # when they go out of scope due to exceptions. list(APPEND jsi_compile_flags "/EHsc") endif() +if (HERMES_ENABLE_BITCODE) + list(APPEND jsi_compile_flags "-fembed-bitcode") +endif () target_compile_options(jsi PUBLIC ${jsi_compile_flags}) install(DIRECTORY "${PROJECT_SOURCE_DIR}/API/jsi/" DESTINATION include diff --git a/ReactCommon/jsi/jsi/JSIDynamic.cpp b/ReactCommon/jsi/jsi/JSIDynamic.cpp index 89dfeb24876853..acac7a3a04729d 100644 --- a/ReactCommon/jsi/jsi/JSIDynamic.cpp +++ b/ReactCommon/jsi/jsi/JSIDynamic.cpp @@ -17,72 +17,163 @@ using namespace facebook::jsi; namespace facebook { namespace jsi { -Value valueFromDynamic(Runtime& runtime, const folly::dynamic& dyn) { +namespace { + +struct FromDynamic { + FromDynamic(const folly::dynamic* dynArg, Object objArg) + : dyn(dynArg), obj(std::move(objArg)) {} + + const folly::dynamic* dyn; + Object obj; +}; + +// This converts one element. If it's a collection, it gets pushed onto +// the stack for later processing. +Value valueFromDynamicShallow( + Runtime& runtime, + std::vector& stack, + const folly::dynamic& dyn) { switch (dyn.type()) { case folly::dynamic::NULLT: return Value::null(); case folly::dynamic::ARRAY: { - Array ret = Array(runtime, dyn.size()); - for (size_t i = 0; i < dyn.size(); ++i) { - ret.setValueAtIndex(runtime, i, valueFromDynamic(runtime, dyn[i])); - } - return std::move(ret); + Object arr = Array(runtime, dyn.size()); + Value ret = Value(runtime, arr); + stack.emplace_back(&dyn, std::move(arr)); + return ret; } case folly::dynamic::BOOL: - return dyn.getBool(); + return Value(dyn.getBool()); case folly::dynamic::DOUBLE: return dyn.getDouble(); case folly::dynamic::INT64: - // Can't use asDouble() here. If the int64 value is too bit to be - // represented precisely as a double, folly will throw an - // exception. - return (double)dyn.getInt(); + return Value((double)dyn.getInt()); case folly::dynamic::OBJECT: { - Object ret(runtime); - for (const auto& element : dyn.items()) { - Value value = valueFromDynamic(runtime, element.second); - if (element.first.isNumber() || element.first.isString()) { - ret.setProperty( + auto obj = Object(runtime); + Value ret = Value(runtime, obj); + stack.emplace_back(&dyn, std::move(obj)); + return ret; + } + case folly::dynamic::STRING: + return Value(String::createFromUtf8(runtime, dyn.getString())); + } + CHECK(false); +} + +} // namespace + +Value valueFromDynamic(Runtime& runtime, const folly::dynamic& dynInput) { + std::vector stack; + + Value ret = valueFromDynamicShallow(runtime, stack, dynInput); + + while (!stack.empty()) { + auto top = std::move(stack.back()); + stack.pop_back(); + + switch (top.dyn->type()) { + case folly::dynamic::ARRAY: { + Array arr = std::move(top.obj).getArray(runtime); + for (size_t i = 0; i < top.dyn->size(); ++i) { + arr.setValueAtIndex( runtime, - PropNameID::forUtf8(runtime, element.first.asString()), - value); + i, + valueFromDynamicShallow(runtime, stack, (*top.dyn)[i])); + } + break; + } + case folly::dynamic::OBJECT: { + Object obj = std::move(top.obj); + for (const auto& element : top.dyn->items()) { + if (element.first.isNumber() || element.first.isString()) { + obj.setProperty( + runtime, + PropNameID::forUtf8(runtime, element.first.asString()), + valueFromDynamicShallow(runtime, stack, element.second)); + } } + break; } - return std::move(ret); + default: + CHECK(false); } - case folly::dynamic::STRING: - return String::createFromUtf8(runtime, dyn.getString()); } - CHECK(false); + + return ret; } -folly::dynamic dynamicFromValue(Runtime& runtime, const Value& value) { +namespace { + +struct FromValue { + FromValue(folly::dynamic* dynArg, Object objArg) + : dyn(dynArg), obj(std::move(objArg)) {} + + folly::dynamic* dyn; + Object obj; +}; + +// This converts one element. If it's a collection, it gets pushed +// onto the stack for later processing. The output is created by +// mutating the output argument, because we need its actual pointer to +// push onto the stack. +void dynamicFromValueShallow( + Runtime& runtime, + std::vector& stack, + const jsi::Value& value, + folly::dynamic& output) { if (value.isUndefined() || value.isNull()) { - return nullptr; + output = nullptr; } else if (value.isBool()) { - return value.getBool(); + output = value.getBool(); } else if (value.isNumber()) { - return value.getNumber(); + output = value.getNumber(); } else if (value.isString()) { - return value.getString(runtime).utf8(runtime); + output = value.getString(runtime).utf8(runtime); } else { + CHECK(value.isObject()); Object obj = value.getObject(runtime); if (obj.isArray(runtime)) { - Array array = obj.getArray(runtime); - folly::dynamic ret = folly::dynamic::array(); - for (size_t i = 0; i < array.size(runtime); ++i) { - ret.push_back( - dynamicFromValue(runtime, array.getValueAtIndex(runtime, i))); - } - return ret; + output = folly::dynamic::array(); } else if (obj.isFunction(runtime)) { throw JSError(runtime, "JS Functions are not convertible to dynamic"); } else { - folly::dynamic ret = folly::dynamic::object(); - Array names = obj.getPropertyNames(runtime); + output = folly::dynamic::object(); + } + stack.emplace_back(&output, std::move(obj)); + } +} + +} // namespace + +folly::dynamic dynamicFromValue(Runtime& runtime, const Value& valueInput) { + std::vector stack; + folly::dynamic ret; + + dynamicFromValueShallow(runtime, stack, valueInput, ret); + + while (!stack.empty()) { + auto top = std::move(stack.back()); + stack.pop_back(); + + if (top.obj.isArray(runtime)) { + // Inserting into a dyn can invalidate references into it, so we + // need to insert new elements up front, then push stuff onto + // the stack. + Array array = top.obj.getArray(runtime); + size_t arraySize = array.size(runtime); + for (size_t i = 0; i < arraySize; ++i) { + top.dyn->push_back(nullptr); + } + for (size_t i = 0; i < arraySize; ++i) { + dynamicFromValueShallow( + runtime, stack, array.getValueAtIndex(runtime, i), top.dyn->at(i)); + } + } else { + Array names = top.obj.getPropertyNames(runtime); + std::vector> props; for (size_t i = 0; i < names.size(runtime); ++i) { String name = names.getValueAtIndex(runtime, i).getString(runtime); - Value prop = obj.getProperty(runtime, name); + Value prop = top.obj.getProperty(runtime, name); if (prop.isUndefined()) { continue; } @@ -92,12 +183,17 @@ folly::dynamic dynamicFromValue(Runtime& runtime, const Value& value) { if (prop.isObject() && prop.getObject(runtime).isFunction(runtime)) { prop = Value::null(); } - ret.insert( - name.utf8(runtime), dynamicFromValue(runtime, std::move(prop))); + props.emplace_back(name.utf8(runtime), std::move(prop)); + top.dyn->insert(props.back().first, nullptr); + } + for (const auto& prop : props) { + dynamicFromValueShallow( + runtime, stack, prop.second, (*top.dyn)[prop.first]); } - return ret; } } + + return ret; } } // namespace jsi diff --git a/ReactCommon/jsi/jsi/decorator.h b/ReactCommon/jsi/jsi/decorator.h index 46e7414abbecb1..9110145e17788f 100644 --- a/ReactCommon/jsi/jsi/decorator.h +++ b/ReactCommon/jsi/jsi/decorator.h @@ -331,12 +331,17 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { return plain().instrumentation().getHeapInfo(includeExpensive); } - void collectGarbage() override { - plain().instrumentation().collectGarbage(); + void collectGarbage(std::string cause) override { + plain().instrumentation().collectGarbage(std::move(cause)); } - void startTrackingHeapObjectStackTraces() override { - plain().instrumentation().startTrackingHeapObjectStackTraces(); + void startTrackingHeapObjectStackTraces( + std::function)> callback) override { + plain().instrumentation().startTrackingHeapObjectStackTraces( + std::move(callback)); } void stopTrackingHeapObjectStackTraces() override { diff --git a/ReactCommon/jsi/jsi/instrumentation.h b/ReactCommon/jsi/jsi/instrumentation.h index 04c76ce2594d62..0a9f48abb52b13 100644 --- a/ReactCommon/jsi/jsi/instrumentation.h +++ b/ReactCommon/jsi/jsi/instrumentation.h @@ -7,8 +7,10 @@ #pragma once +#include #include #include +#include #include #include @@ -49,12 +51,27 @@ class JSI_EXPORT Instrumentation { virtual std::unordered_map getHeapInfo( bool includeExpensive) = 0; - /// perform a full garbage collection - virtual void collectGarbage() = 0; + /// Perform a full garbage collection. + /// \param cause The cause of this collection, as it should be reported in + /// logs. + virtual void collectGarbage(std::string cause) = 0; + + /// A HeapStatsUpdate is a tuple of the fragment index, the number of objects + /// in that fragment, and the number of bytes used by those objects. + /// A "fragment" is a view of all objects allocated within a time slice. + using HeapStatsUpdate = std::tuple; /// Start capturing JS stack-traces for all JS heap allocated objects. These /// can be accessed via \c ::createSnapshotToFile(). - virtual void startTrackingHeapObjectStackTraces() = 0; + /// \param fragmentCallback If present, invoke this callback every so often + /// with the most recently seen object ID, and a list of fragments that have + /// been updated. This callback will be invoked on the same thread that the + /// runtime is using. + virtual void startTrackingHeapObjectStackTraces( + std::function stats)> fragmentCallback) = 0; /// Stop capture JS stack-traces for JS heap allocated objects. virtual void stopTrackingHeapObjectStackTraces() = 0; diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index e4a7e431fca00d..1054057e1fdab5 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -97,9 +97,13 @@ Instrumentation& Runtime::instrumentation() { return std::unordered_map{}; } - void collectGarbage() override {} + void collectGarbage(std::string) override {} - void startTrackingHeapObjectStackTraces() override {} + void startTrackingHeapObjectStackTraces( + std::function)>) override {} void stopTrackingHeapObjectStackTraces() override {} void createSnapshotToFile(const std::string&) override { diff --git a/ReactCommon/jsi/jsi/jsi.h b/ReactCommon/jsi/jsi/jsi.h index 25c152227e6d57..f6c17e5bb670e0 100644 --- a/ReactCommon/jsi/jsi/jsi.h +++ b/ReactCommon/jsi/jsi/jsi.h @@ -122,7 +122,7 @@ class JSI_EXPORT HostObject { virtual void set(Runtime&, const PropNameID& name, const Value& value); // When JS wants a list of property names for the HostObject, it will - // call this method. If it throws an exception, the call will thow a + // call this method. If it throws an exception, the call will throw a // JS \c Error object. The default implementation returns empty vector. virtual std::vector getPropertyNames(Runtime& rt); }; diff --git a/ReactCommon/jsi/jsi/test/testlib.cpp b/ReactCommon/jsi/jsi/test/testlib.cpp index 8cf831d34f7b84..e605b6acead953 100644 --- a/ReactCommon/jsi/jsi/test/testlib.cpp +++ b/ReactCommon/jsi/jsi/test/testlib.cpp @@ -6,6 +6,7 @@ */ #include + #include #include #include diff --git a/ReactCommon/jsiexecutor/React-jsiexecutor.podspec b/ReactCommon/jsiexecutor/React-jsiexecutor.podspec index f67143d1b0c91d..adb62a5789945a 100644 --- a/ReactCommon/jsiexecutor/React-jsiexecutor.podspec +++ b/ReactCommon/jsiexecutor/React-jsiexecutor.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "jsireact/*.{cpp,h}" s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags diff --git a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp index 0d91ca7778e0b0..f490891446060f 100644 --- a/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp +++ b/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp @@ -344,7 +344,7 @@ void JSIExecutor::handleMemoryPressure(int pressureLevel) { // collections. LOG(INFO) << "Memory warning (pressure level: " << levelName << ") received by JS VM, running a GC"; - runtime_->instrumentation().collectGarbage(); + runtime_->instrumentation().collectGarbage(levelName); break; default: // Use the raw number instead of the name here since the name is diff --git a/ReactCommon/jsinspector/React-jsinspector.podspec b/ReactCommon/jsinspector/React-jsinspector.podspec index 600480fe8e20cd..9548daa306e20a 100644 --- a/ReactCommon/jsinspector/React-jsinspector.podspec +++ b/ReactCommon/jsinspector/React-jsinspector.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "*.{cpp,h}" s.header_dir = 'jsinspector' diff --git a/ReactCommon/libraries/fbcore/src/test/java/com/facebook/powermock/BUCK b/ReactCommon/libraries/fbcore/src/test/java/com/facebook/powermock/BUCK index 2a86bc6af780b5..2a9f6a05bb329b 100644 --- a/ReactCommon/libraries/fbcore/src/test/java/com/facebook/powermock/BUCK +++ b/ReactCommon/libraries/fbcore/src/test/java/com/facebook/powermock/BUCK @@ -3,6 +3,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_ja rn_android_library( name = "powermock2", + autoglob = False, visibility = ["PUBLIC"], exported_deps = [ ":javassist-prebuilt", @@ -20,6 +21,7 @@ rn_android_library( rn_android_library( name = "powermock-reflect", + autoglob = False, visibility = ["PUBLIC"], exported_deps = [ ":byte-buddy", diff --git a/ReactCommon/turbomodule/.clang-tidy b/ReactCommon/react/nativemodule/.clang-tidy similarity index 100% rename from ReactCommon/turbomodule/.clang-tidy rename to ReactCommon/react/nativemodule/.clang-tidy diff --git a/ReactCommon/react/nativemodule/core/Android.mk b/ReactCommon/react/nativemodule/core/Android.mk new file mode 100644 index 00000000000000..70f7651b4831f4 --- /dev/null +++ b/ReactCommon/react/nativemodule/core/Android.mk @@ -0,0 +1,31 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_nativemodule_core + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../ $(LOCAL_PATH)/ReactCommon $(LOCAL_PATH)/platform/android/ReactCommon + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) $(wildcard $(LOCAL_PATH)/platform/android/ReactCommon/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/platform/android/ + +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libreactnativejni + +LOCAL_STATIC_LIBRARIES := libjsi libreactperflogger + +LOCAL_CFLAGS := \ + -DLOG_TAG=\"ReactNative\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,folly) +$(call import-module,jsi) +$(call import-module,reactperflogger) diff --git a/ReactCommon/turbomodule/core/BUCK b/ReactCommon/react/nativemodule/core/BUCK similarity index 76% rename from ReactCommon/turbomodule/core/BUCK rename to ReactCommon/react/nativemodule/core/BUCK index 549ddef0a9e243..523e359bf9ffa6 100644 --- a/ReactCommon/turbomodule/core/BUCK +++ b/ReactCommon/react/nativemodule/core/BUCK @@ -1,15 +1,15 @@ -load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_objc_arc_preprocessor_flags") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags", "react_native_target", "react_native_xplat_shared_library_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") rn_xplat_cxx_library( name = "core", srcs = glob( - ["*.cpp"], + ["ReactCommon/**/*.cpp"], ), header_namespace = "", exported_headers = subdir_glob( [ - ("", "*.h"), + ("ReactCommon", "*.h"), ], prefix = "ReactCommon", ), @@ -26,13 +26,13 @@ rn_xplat_cxx_library( ], fbandroid_exported_headers = subdir_glob( [ - ("platform/android", "*.h"), + ("platform/android/ReactCommon", "*.h"), ], prefix = "ReactCommon", ), fbandroid_srcs = glob( [ - "platform/android/**/*.cpp", + "platform/android/ReactCommon/*.cpp", ], ), fbobjc_compiler_flags = [ @@ -40,7 +40,7 @@ rn_xplat_cxx_library( "-fobjc-arc-exceptions", ], fbobjc_inherited_buck_flags = get_static_library_ios_flags(), - fbobjc_preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode(), + fbobjc_preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), ios_deps = [ "//xplat/FBBaseLite:FBBaseLite", "//xplat/js/react-native-github:RCTCxxModule", @@ -83,6 +83,6 @@ rn_xplat_cxx_library( react_native_xplat_target("reactperflogger:reactperflogger"), ], exported_deps = [ - "//xplat/jsi:jsi", + react_native_xplat_shared_library_target("jsi:jsi"), ], ) diff --git a/ReactCommon/turbomodule/core/LongLivedObject.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.cpp similarity index 100% rename from ReactCommon/turbomodule/core/LongLivedObject.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.cpp diff --git a/ReactCommon/turbomodule/core/LongLivedObject.h b/ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h similarity index 100% rename from ReactCommon/turbomodule/core/LongLivedObject.h rename to ReactCommon/react/nativemodule/core/ReactCommon/LongLivedObject.h diff --git a/ReactCommon/turbomodule/core/TurboCxxModule.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp similarity index 100% rename from ReactCommon/turbomodule/core/TurboCxxModule.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp diff --git a/ReactCommon/turbomodule/core/TurboCxxModule.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.h similarity index 100% rename from ReactCommon/turbomodule/core/TurboCxxModule.h rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.h diff --git a/ReactCommon/turbomodule/core/TurboModule.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp similarity index 100% rename from ReactCommon/turbomodule/core/TurboModule.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp diff --git a/ReactCommon/turbomodule/core/TurboModule.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h similarity index 91% rename from ReactCommon/turbomodule/core/TurboModule.h rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index 8bc8362730ccf0..0772986a76ab66 100644 --- a/ReactCommon/turbomodule/core/TurboModule.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -64,8 +64,8 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { * An app/platform-specific provider function to get an instance of a module * given a name. */ -using TurboModuleProviderFunctionType = std::function(const std::string &name, const jsi::Value *schema)>; +using TurboModuleProviderFunctionType = + std::function(const std::string &name)>; } // namespace react } // namespace facebook diff --git a/ReactCommon/turbomodule/core/TurboModuleBinding.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp similarity index 89% rename from ReactCommon/turbomodule/core/TurboModuleBinding.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp index 0b04ac69b10d66..81614cf2b04925 100644 --- a/ReactCommon/turbomodule/core/TurboModuleBinding.cpp +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -50,12 +50,11 @@ TurboModuleBinding::~TurboModuleBinding() { } std::shared_ptr TurboModuleBinding::getModule( - const std::string &name, - const jsi::Value *schema) { + const std::string &name) { std::shared_ptr module = nullptr; { SystraceSection s("TurboModuleBinding::getModule", "module", name); - module = moduleProvider_(name, schema); + module = moduleProvider_(name); } return module; } @@ -72,10 +71,7 @@ jsi::Value TurboModuleBinding::jsProxy( std::string moduleName = args[0].getString(runtime).utf8(runtime); jsi::Value nullSchema = jsi::Value::undefined(); - std::shared_ptr module = - (count >= 2 ? getModule(moduleName, &args[1]) - : getModule(moduleName, &nullSchema)); - + std::shared_ptr module = getModule(moduleName); if (module == nullptr) { return jsi::Value::null(); } diff --git a/ReactCommon/turbomodule/core/TurboModuleBinding.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h similarity index 92% rename from ReactCommon/turbomodule/core/TurboModuleBinding.h rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h index 2546730959fc12..96de89bed470e8 100644 --- a/ReactCommon/turbomodule/core/TurboModuleBinding.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h @@ -36,9 +36,7 @@ class TurboModuleBinding { /** * Get an TurboModule instance for the given module name. */ - std::shared_ptr getModule( - const std::string &name, - const jsi::Value *schema); + std::shared_ptr getModule(const std::string &name); private: /** diff --git a/ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.cpp similarity index 99% rename from ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.cpp index f69701a26c0d85..a55e632ffca787 100644 --- a/ReactCommon/turbomodule/core/TurboModulePerfLogger.cpp +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.cpp @@ -17,6 +17,10 @@ void enableLogging(std::unique_ptr &&newPerfLogger) { g_perfLogger = std::move(newPerfLogger); } +void disableLogging() { + g_perfLogger = nullptr; +} + void moduleDataCreateStart(const char *moduleName, int32_t id) { NativeModulePerfLogger *logger = g_perfLogger.get(); if (logger != nullptr) { diff --git a/ReactCommon/turbomodule/core/TurboModulePerfLogger.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.h similarity index 99% rename from ReactCommon/turbomodule/core/TurboModulePerfLogger.h rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.h index 56abad502f5c92..2f7fcf8c8b2dd3 100644 --- a/ReactCommon/turbomodule/core/TurboModulePerfLogger.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModulePerfLogger.h @@ -14,6 +14,7 @@ namespace facebook { namespace react { namespace TurboModulePerfLogger { void enableLogging(std::unique_ptr &&logger); +void disableLogging(); void moduleDataCreateStart(const char *moduleName, int32_t id); void moduleDataCreateEnd(const char *moduleName, int32_t id); diff --git a/ReactCommon/turbomodule/core/TurboModuleUtils.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp similarity index 100% rename from ReactCommon/turbomodule/core/TurboModuleUtils.cpp rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp diff --git a/ReactCommon/turbomodule/core/TurboModuleUtils.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h similarity index 98% rename from ReactCommon/turbomodule/core/TurboModuleUtils.h rename to ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h index 030d3fac9783de..30add1d265baae 100644 --- a/ReactCommon/turbomodule/core/TurboModuleUtils.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h @@ -10,7 +10,6 @@ #include #include -#include #include #include diff --git a/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.cpp b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp similarity index 89% rename from ReactCommon/turbomodule/core/platform/android/JavaTurboModule.cpp rename to ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp index 4b5d8d6e9538b6..511907588f1131 100644 --- a/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.cpp +++ b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp @@ -31,9 +31,24 @@ JavaTurboModule::JavaTurboModule(const InitParams ¶ms) instance_(jni::make_global(params.instance)), nativeInvoker_(params.nativeInvoker) {} -bool JavaTurboModule::isPromiseAsyncDispatchEnabled_ = false; -void JavaTurboModule::enablePromiseAsyncDispatch(bool enable) { - isPromiseAsyncDispatchEnabled_ = enable; +JavaTurboModule::~JavaTurboModule() { + /** + * TODO(T75896241): In E2E tests, instance_ is null. Investigate why. Can we + * get rid of this null check? + */ + if (!instance_) { + return; + } + + nativeInvoker_->invokeAsync([instance = std::move(instance_)]() mutable { + /** + * Reset the global NativeModule ref on the NativeModules thread. Why: + * - ~JavaTurboModule() can be called on a non-JVM thread. If we reset the + * global ref in ~JavaTurboModule(), we might access the JVM from a + * non-JVM thread, which will crash the app. + */ + instance.reset(); + }); } namespace { @@ -240,8 +255,7 @@ JNIArgs JavaTurboModule::convertJSIArgsToJNIArgs( auto makeGlobalIfNecessary = [&globalRefs, env, valueKind](jobject obj) -> jobject { - if (valueKind == VoidKind || - (valueKind == PromiseKind && isPromiseAsyncDispatchEnabled_)) { + if (valueKind == VoidKind || valueKind == PromiseKind) { jobject globalObj = env->NewGlobalRef(obj); globalRefs.push_back(globalObj); env->DeleteLocalRef(obj); @@ -409,9 +423,7 @@ jsi::Value JavaTurboModule::invokeJavaMethod( const char *methodName = methodNameStr.c_str(); const char *moduleName = name_.c_str(); - bool isMethodSync = - !(valueKind == VoidKind || - (valueKind == PromiseKind && isPromiseAsyncDispatchEnabled_)); + bool isMethodSync = !(valueKind == VoidKind || valueKind == PromiseKind); if (isMethodSync) { TMPL::syncMethodCallStart(moduleName, methodName); @@ -713,7 +725,6 @@ jsi::Value JavaTurboModule::invokeJavaMethod( &jargs, &globalRefs, argCount, - instance_ = instance_, methodID, moduleNameStr = name_, methodNameStr, @@ -753,60 +764,48 @@ jsi::Value JavaTurboModule::invokeJavaMethod( const char *moduleName = moduleNameStr.c_str(); const char *methodName = methodNameStr.c_str(); - if (isPromiseAsyncDispatchEnabled_) { - jobject globalPromise = env->NewGlobalRef(promise); - - globalRefs.push_back(globalPromise); - env->DeleteLocalRef(promise); - - jargs[argCount].l = globalPromise; - TMPL::asyncMethodCallArgConversionEnd(moduleName, methodName); - TMPL::asyncMethodCallDispatch(moduleName, methodName); - - nativeInvoker_->invokeAsync( - [jargs, - globalRefs, - methodID, - instance_ = instance_, - moduleNameStr, - methodNameStr, - id = getUniqueId()]() mutable -> void { - /** - * TODO(ramanpreet): Why do we have to require the - * environment again? Why does JNI crash when we use the env - * from the upper scope? - */ - JNIEnv *env = jni::Environment::current(); - const char *moduleName = moduleNameStr.c_str(); - const char *methodName = methodNameStr.c_str(); - - TMPL::asyncMethodCallExecutionStart( - moduleName, methodName, id); - env->CallVoidMethodA( - instance_.get(), methodID, jargs.data()); - try { - FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); - } catch (...) { - TMPL::asyncMethodCallExecutionFail( - moduleName, methodName, id); - throw; - } - - for (auto globalRef : globalRefs) { - env->DeleteGlobalRef(globalRef); - } - TMPL::asyncMethodCallExecutionEnd( + jobject globalPromise = env->NewGlobalRef(promise); + + globalRefs.push_back(globalPromise); + env->DeleteLocalRef(promise); + + jargs[argCount].l = globalPromise; + TMPL::asyncMethodCallArgConversionEnd(moduleName, methodName); + TMPL::asyncMethodCallDispatch(moduleName, methodName); + + nativeInvoker_->invokeAsync( + [jargs, + globalRefs, + methodID, + instance_ = instance_, + moduleNameStr, + methodNameStr, + id = getUniqueId()]() mutable -> void { + /** + * TODO(ramanpreet): Why do we have to require the + * environment again? Why does JNI crash when we use the env + * from the upper scope? + */ + JNIEnv *env = jni::Environment::current(); + const char *moduleName = moduleNameStr.c_str(); + const char *methodName = methodNameStr.c_str(); + + TMPL::asyncMethodCallExecutionStart( + moduleName, methodName, id); + env->CallVoidMethodA(instance_.get(), methodID, jargs.data()); + try { + FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); + } catch (...) { + TMPL::asyncMethodCallExecutionFail( moduleName, methodName, id); - }); - - } else { - jargs[argCount].l = promise; - TMPL::syncMethodCallArgConversionEnd(moduleName, methodName); - TMPL::syncMethodCallExecutionStart(moduleName, methodName); - env->CallVoidMethodA(instance_.get(), methodID, jargs.data()); - TMPL::syncMethodCallExecutionEnd(moduleName, methodName); - TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); - } + throw; + } + + for (auto globalRef : globalRefs) { + env->DeleteGlobalRef(globalRef); + } + TMPL::asyncMethodCallExecutionEnd(moduleName, methodName, id); + }); return jsi::Value::undefined(); }); @@ -815,12 +814,8 @@ jsi::Value JavaTurboModule::invokeJavaMethod( Promise.callAsConstructor(runtime, promiseConstructorArg); checkJNIErrorForMethodCall(); - if (isPromiseAsyncDispatchEnabled_) { - TMPL::asyncMethodCallEnd(moduleName, methodName); - } else { - TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); - TMPL::syncMethodCallEnd(moduleName, methodName); - } + TMPL::asyncMethodCallEnd(moduleName, methodName); + return promise; } default: diff --git a/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.h b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h similarity index 93% rename from ReactCommon/turbomodule/core/platform/android/JavaTurboModule.h rename to ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h index 642cacb194a85b..77a067701fc1e4 100644 --- a/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.h +++ b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h @@ -41,6 +41,8 @@ class JSI_EXPORT JavaTurboModule : public TurboModule { }; JavaTurboModule(const InitParams ¶ms); + virtual ~JavaTurboModule(); + jsi::Value invokeJavaMethod( jsi::Runtime &runtime, TurboModuleMethodValueKind valueKind, @@ -49,17 +51,10 @@ class JSI_EXPORT JavaTurboModule : public TurboModule { const jsi::Value *args, size_t argCount); - static void enablePromiseAsyncDispatch(bool enable); - private: jni::global_ref instance_; std::shared_ptr nativeInvoker_; - /** - * Experiments - */ - static bool isPromiseAsyncDispatchEnabled_; - JNIArgs convertJSIArgsToJNIArgs( JNIEnv *env, jsi::Runtime &rt, diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.h similarity index 95% rename from ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h rename to ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.h index bdd94494689284..7e16a5a40dac48 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h +++ b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.h @@ -90,8 +90,11 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { NSMutableArray *retainedObjectsForInvocation); using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper); - jsi::Value - createPromise(jsi::Runtime &runtime, std::shared_ptr jsInvoker, PromiseInvocationBlock invoke); + jsi::Value createPromise( + jsi::Runtime &runtime, + std::shared_ptr jsInvoker, + std::string methodName, + PromiseInvocationBlock invoke); }; } // namespace react @@ -108,8 +111,6 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { */ @property (nonatomic, weak) id turboModuleRegistry; -@optional -// This should be required, after migration is done. - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params; diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm similarity index 93% rename from ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm rename to ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm index 4e5cdc8a4ee3c6..de1bed23f8ea50 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm +++ b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm @@ -171,7 +171,7 @@ static int32_t getUniqueId() { auto weakWrapper = CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker); BOOL __block wrapperWasCalled = NO; - return ^(NSArray *responses) { + RCTResponseSenderBlock callback = ^(NSArray *responses) { if (wrapperWasCalled) { throw std::runtime_error("callback arg cannot be called more than once"); } @@ -194,6 +194,8 @@ static int32_t getUniqueId() wrapperWasCalled = YES; }; + + return [callback copy]; } namespace facebook { @@ -202,6 +204,7 @@ static int32_t getUniqueId() jsi::Value ObjCTurboModule::createPromise( jsi::Runtime &runtime, std::shared_ptr jsInvoker, + std::string methodName, PromiseInvocationBlock invoke) { if (!invoke) { @@ -209,6 +212,7 @@ static int32_t getUniqueId() } jsi::Function Promise = runtime.global().getPropertyAsFunction(runtime, "Promise"); + std::string moduleName = name_; // Note: the passed invoke() block is not retained by default, so let's retain it here to help keep it longer. // Otherwise, there's a risk of it getting released before the promise function below executes. @@ -217,10 +221,14 @@ static int32_t getUniqueId() runtime, jsi::PropNameID::forAscii(runtime, "fn"), 2, - [invokeCopy, jsInvoker](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) { + [invokeCopy, jsInvoker, moduleName, methodName]( + jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) { + std::string moduleMethod = moduleName + "." + methodName + "()"; + if (count != 2) { throw std::invalid_argument( - "Promise must pass constructor function two args. Passed " + std::to_string(count) + " args."); + moduleMethod + ": Promise must pass constructor function two args. Passed " + std::to_string(count) + + " args."); } if (!invokeCopy) { return jsi::Value::undefined(); @@ -234,11 +242,13 @@ static int32_t getUniqueId() RCTPromiseResolveBlock resolveBlock = ^(id result) { if (rejectWasCalled) { - throw std::runtime_error("Tried to resolve a promise after it's already been rejected."); + RCTLogError(@"%s: Tried to resolve a promise after it's already been rejected.", moduleMethod.c_str()); + return; } if (resolveWasCalled) { - throw std::runtime_error("Tried to resolve a promise more than once."); + RCTLogError(@"%s: Tried to resolve a promise more than once.", moduleMethod.c_str()); + return; } auto strongResolveWrapper = weakResolveWrapper.lock(); @@ -267,11 +277,13 @@ static int32_t getUniqueId() RCTPromiseRejectBlock rejectBlock = ^(NSString *code, NSString *message, NSError *error) { if (resolveWasCalled) { - throw std::runtime_error("Tried to reject a promise after it's already been resolved."); + RCTLogError(@"%s: Tried to reject a promise after it's already been resolved.", moduleMethod.c_str()); + return; } if (rejectWasCalled) { - throw std::runtime_error("Tried to reject a promise more than once."); + RCTLogError(@"%s: Tried to reject a promise more than once.", moduleMethod.c_str()); + return; } auto strongResolveWrapper = weakResolveWrapper.lock(); @@ -331,12 +343,11 @@ static int32_t getUniqueId() bool wasMethodSync = isMethodSync(returnType); void (^block)() = ^{ - if (!weakModule) { + id strongModule = weakModule; + if (!strongModule) { return; } - id strongModule = weakModule; - if (wasMethodSync) { TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str()); } else { @@ -634,11 +645,15 @@ static int32_t getUniqueId() ? createPromise( runtime, jsInvoker_, + methodNameStr, ^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) { - [inv setArgument:(void *)&resolveBlock atIndex:count + 2]; - [inv setArgument:(void *)&rejectBlock atIndex:count + 3]; - [retainedObjectsForInvocation addObject:resolveBlock]; - [retainedObjectsForInvocation addObject:rejectBlock]; + RCTPromiseResolveBlock resolveCopy = [resolveBlock copy]; + RCTPromiseRejectBlock rejectCopy = [rejectBlock copy]; + + [inv setArgument:(void *)&resolveCopy atIndex:count + 2]; + [inv setArgument:(void *)&rejectCopy atIndex:count + 3]; + [retainedObjectsForInvocation addObject:resolveCopy]; + [retainedObjectsForInvocation addObject:rejectCopy]; // The return type becomes void in the ObjC side. performMethodInvocation(runtime, VoidKind, methodName, inv, retainedObjectsForInvocation); }) diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.h similarity index 94% rename from ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h rename to ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.h index 8ee2eaeefe582e..18756624d42797 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h +++ b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.h @@ -51,6 +51,7 @@ jsInvoker:(std::shared_ptr)jsInvoker; - (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor)runtimeExecutor; +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)bridgelessComponentViewProvider; - (void)invalidate; diff --git a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm similarity index 91% rename from ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm rename to ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm index 223522eb684f4b..797a0747b679ef 100644 --- a/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +++ b/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm @@ -172,6 +172,9 @@ @implementation RCTTurboModuleManager { std::shared_timed_mutex _turboModuleHoldersSharedMutex; std::mutex _turboModuleHoldersMutex; std::atomic _invalidating; + + RCTModuleRegistry *_moduleRegistry; + RCTViewRegistry *_viewRegistry_DEPRECATED; } - (instancetype)initWithBridge:(RCTBridge *)bridge @@ -183,6 +186,12 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _delegate = delegate; _bridge = bridge; _invalidating = false; + _moduleRegistry = [RCTModuleRegistry new]; + [_moduleRegistry setBridge:bridge]; + [_moduleRegistry setTurboModuleRegistry:self]; + + _viewRegistry_DEPRECATED = [RCTViewRegistry new]; + [_viewRegistry_DEPRECATED setBridge:bridge]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bridgeWillInvalidateModules:) @@ -196,6 +205,11 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge return self; } +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)viewProvider +{ + [_viewRegistry_DEPRECATED setBridgelessComponentViewProvider:viewProvider]; +} + - (void)notifyAboutTurboModuleSetup:(const char *)name { NSString *moduleName = [[NSString alloc] initWithUTF8String:name]; @@ -353,6 +367,10 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName */ - (id)provideRCTTurboModule:(const char *)moduleName { + if (strncmp("RCT", moduleName, 3) == 0) { + moduleName = [[[NSString stringWithUTF8String:moduleName] substringFromIndex:3] UTF8String]; + } + TurboModuleHolder *moduleHolder = [self _getOrCreateTurboModuleHolder:moduleName]; if (!moduleHolder) { @@ -535,6 +553,44 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName } } + /** + * Attach the RCTModuleRegistry to this TurboModule, which allows this TurboModule + * To load other NativeModules & TurboModules. + * + * Usage: In the NativeModule @implementation, include: + * `@synthesize moduleRegistry = _moduleRegistry` + */ + if ([module respondsToSelector:@selector(moduleRegistry)] && _moduleRegistry) { + @try { + [(id)module setValue:_moduleRegistry forKey:@"moduleRegistry"]; + } @catch (NSException *exception) { + RCTLogError( + @"%@ has no setter or ivar for its module registry, which is not " + "permitted. You must either @synthesize the moduleRegistry property, " + "or provide your own setter method.", + RCTBridgeModuleNameForClass([module class])); + } + } + + /** + * Attach the RCTViewRegistry to this TurboModule, which allows this TurboModule + * To query a React component's UIView, given its reactTag. + * + * Usage: In the NativeModule @implementation, include: + * `@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED` + */ + if ([module respondsToSelector:@selector(viewRegistry_DEPRECATED)] && _viewRegistry_DEPRECATED) { + @try { + [(id)module setValue:_viewRegistry_DEPRECATED forKey:@"viewRegistry_DEPRECATED"]; + } @catch (NSException *exception) { + RCTLogError( + @"%@ has no setter or ivar for its module registry, which is not " + "permitted. You must either @synthesize the viewRegistry_DEPRECATED property, " + "or provide your own setter method.", + RCTBridgeModuleNameForClass([module class])); + } + } + /** * Some modules need their own queues, but don't provide any, so we need to create it for them. * These modules typically have the following: @@ -595,7 +651,10 @@ - (TurboModuleHolder *)_getOrCreateTurboModuleHolder:(const char *)moduleName * rollout. */ if (_bridge) { - RCTModuleData *data = [[RCTModuleData alloc] initWithModuleInstance:(id)module bridge:_bridge]; + RCTModuleData *data = [[RCTModuleData alloc] initWithModuleInstance:(id)module + bridge:_bridge + moduleRegistry:_moduleRegistry + viewRegistry_DEPRECATED:_viewRegistry_DEPRECATED]; [_bridge registerModuleForFrameUpdates:(id)module withModuleData:data]; } @@ -686,8 +745,7 @@ - (void)installJSBindingWithRuntimeExecutor:(facebook::react::RuntimeExecutor)ru * aren't any strong references to it in ObjC. Hence, we give * __turboModuleProxy a strong reference to TurboModuleManager. */ - auto turboModuleProvider = - [self](const std::string &name, const jsi::Value *schema) -> std::shared_ptr { + auto turboModuleProvider = [self](const std::string &name) -> std::shared_ptr { auto moduleName = name.c_str(); TurboModulePerfLogger::moduleJSRequireBeginningStart(moduleName); @@ -731,6 +789,12 @@ - (id)moduleForName:(const char *)moduleName - (id)moduleForName:(const char *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure { + // When the bridge is invalidating, TurboModules will be nil. + // Therefore, don't (1) do the lookup, and (2) warn on lookup. + if (_invalidating) { + return nil; + } + id module = [self provideRCTTurboModule:moduleName]; if (warnOnLookupFailure && !module) { diff --git a/ReactCommon/turbomodule/samples/BUCK b/ReactCommon/react/nativemodule/samples/BUCK similarity index 56% rename from ReactCommon/turbomodule/samples/BUCK rename to ReactCommon/react/nativemodule/samples/BUCK index ae15f4706b606f..1d6db27fd64816 100644 --- a/ReactCommon/turbomodule/samples/BUCK +++ b/ReactCommon/react/nativemodule/samples/BUCK @@ -1,13 +1,15 @@ -load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "react_native_dep", "react_native_target", "react_native_xplat_target", "rn_android_library", "rn_xplat_cxx_library", "subdir_glob") rn_xplat_cxx_library( name = "samples", - srcs = glob(["*.cpp"]), + srcs = glob( + ["ReactCommon/**/*.cpp"], + ), header_namespace = "", exported_headers = subdir_glob( [ - ("", "*.h"), + ("ReactCommon", "*.h"), ], prefix = "ReactCommon", ), @@ -19,10 +21,11 @@ rn_xplat_cxx_library( ], fbandroid_deps = [ react_native_target("jni/react/jni:jni"), + FBJNI_TARGET, ], fbandroid_exported_headers = subdir_glob( [ - ("platform/android", "*.h"), + ("platform/android/ReactCommon", "*.h"), ], prefix = "ReactCommon", ), @@ -36,7 +39,7 @@ rn_xplat_cxx_library( "-fobjc-arc-exceptions", ], fbobjc_inherited_buck_flags = get_static_library_ios_flags(), - fbobjc_preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode(), + fbobjc_preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), force_static = True, ios_deps = [ "//xplat/FBBaseLite:FBBaseLite", @@ -75,6 +78,28 @@ rn_xplat_cxx_library( ], exported_deps = [ "//xplat/jsi:jsi", - react_native_xplat_target("turbomodule/core:core"), + react_native_xplat_target("react/nativemodule/core:core"), + ], +) + +rn_android_library( + name = "impl", + srcs = glob(["platform/android/*.java"]), + autoglob = False, + required_for_source_only_abi = True, + visibility = [ + "PUBLIC", + ], + deps = [ + "//fbandroid/java/com/facebook/debug/log:log", + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_dep("third-party/java/jsr-330:jsr-330"), + react_native_target("java/com/facebook/react/bridge:bridge"), + react_native_target("java/com/facebook/react/common:common"), + react_native_target("java/com/facebook/react/module/annotations:annotations"), + ":samples", + ], + exported_deps = [ + react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), ], ) diff --git a/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp b/ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.cpp similarity index 100% rename from ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp rename to ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.cpp diff --git a/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.h b/ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.h similarity index 100% rename from ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.h rename to ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.h diff --git a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp b/ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.cpp similarity index 100% rename from ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp rename to ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.cpp diff --git a/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h b/ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.h similarity index 100% rename from ReactCommon/turbomodule/samples/SampleTurboCxxModule.h rename to ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.h diff --git a/ReactCommon/react/nativemodule/samples/platform/android/Android.mk b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk new file mode 100644 index 00000000000000..46dfd7623ae029 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := sampleturbomodule +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SHARED_LIBRARIES := libfbjni libreact_nativemodule_core +LOCAL_CFLAGS := \ + -DLOG_TAG=\"ReactNative\" +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java b/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java new file mode 100644 index 00000000000000..f992e5d6ae1c67 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +package com.facebook.fbreact.specs; + +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactModuleWithSpec; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.build.ReactBuildConfig; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule + implements ReactModuleWithSpec, TurboModule { + public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract double getNumber(double arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableMap getValue(double x, String y, ReadableMap z); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableMap getObject(ReadableMap arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableMap getUnsafeObject(ReadableMap arg); + + @ReactMethod + public abstract void voidFunc(); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableArray getArray(ReadableArray arg); + + @ReactMethod + public abstract void getValueWithPromise(boolean error, Promise promise); + + @ReactMethod + public abstract void getValueWithCallback(Callback callback); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract String getString(String arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract double getRootTag(double arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract boolean getBool(boolean arg); + + protected abstract Map getTypedExportedConstants(); + + @Override + public final @Nullable Map getConstants() { + Map constants = getTypedExportedConstants(); + if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { + Set obligatoryFlowConstants = + new HashSet<>(Arrays.asList("const2", "const1", "const3")); + Set optionalFlowConstants = new HashSet<>(); + Set undeclaredConstants = new HashSet<>(constants.keySet()); + undeclaredConstants.removeAll(obligatoryFlowConstants); + undeclaredConstants.removeAll(optionalFlowConstants); + if (!undeclaredConstants.isEmpty()) { + throw new IllegalStateException( + String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); + } + undeclaredConstants = obligatoryFlowConstants; + undeclaredConstants.removeAll(constants.keySet()); + if (!undeclaredConstants.isEmpty()) { + throw new IllegalStateException( + String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); + } + } + return constants; + } +} diff --git a/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp new file mode 100644 index 00000000000000..676a79ee5e76c0 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +#include + +namespace facebook { +namespace react { + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, VoidKind, "voidFunc", "()V", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getBool( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, BooleanKind, "getBool", "(Z)Z", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getNumber( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, NumberKind, "getNumber", "(D)D", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getString( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + StringKind, + "getString", + "(Ljava/lang/String;)Ljava/lang/String;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getArray( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ArrayKind, + "getArray", + "(Lcom/facebook/react/bridge/ReadableArray;)Lcom/facebook/react/bridge/WritableArray;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getObject( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ObjectKind, + "getObject", + "(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, NumberKind, "getRootTag", "(D)D", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValue( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ObjectKind, + "getValue", + "(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + VoidKind, + "getValueWithCallback", + "(Lcom/facebook/react/bridge/Callback;)V", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + PromiseKind, + "getValueWithPromise", + "(ZLcom/facebook/react/bridge/Promise;)V", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getConstants( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); +} + +NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI( + const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + methodMap_["voidFunc"] = + MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + methodMap_["getBool"] = + MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + methodMap_["getNumber"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + methodMap_["getString"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + methodMap_["getArray"] = + MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + methodMap_["getObject"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + methodMap_["getRootTag"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + methodMap_["getValue"] = + MethodMetadata{3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + methodMap_["getValueWithCallback"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + methodMap_["getValueWithPromise"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + methodMap_["getConstants"] = MethodMetadata{ + 0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; +} + +std::shared_ptr SampleTurboModuleSpec_ModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) { + if (moduleName == "SampleTurboModule") { + return std::make_shared(params); + } + return nullptr; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h new file mode 100644 index 00000000000000..6baefae6d890d9 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/** + * C++ class for module 'SampleTurboModule' + */ +class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); +}; + +std::shared_ptr SampleTurboModuleSpec_ModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java b/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java new file mode 100644 index 00000000000000..f919eb5bd2dd07 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.fbreact.specs; + +import android.app.Activity; +import android.util.DisplayMetrics; +import android.widget.Toast; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.module.annotations.ReactModule; +import java.util.HashMap; +import java.util.Map; + +@ReactModule(name = SampleTurboModule.NAME) +public class SampleTurboModule extends NativeSampleTurboModuleSpec { + + public static final String NAME = "SampleTurboModule"; + + private static final String TAG = SampleTurboModule.class.getName(); + private final ReactApplicationContext mContext; + private Toast mToast; + + public SampleTurboModule(ReactApplicationContext context) { + super(context); + mContext = context; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public boolean getBool(boolean arg) { + log("getBool", arg, arg); + return arg; + } + + @Override + protected Map getTypedExportedConstants() { + Map result = new HashMap<>(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + Activity activity = mContext.getCurrentActivity(); + if (activity != null) { + activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + result.put("const2", displayMetrics.widthPixels); + } + result.put("const1", true); + result.put("const3", "something"); + log("constantsToExport", "", result); + return result; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public double getNumber(double arg) { + log("getNumber", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public String getString(String arg) { + log("getString", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public double getRootTag(double arg) { + log("getRootTag", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public void voidFunc() { + log("voidFunc", "", ""); + return; + } + + // This function returns {@link WritableMap} instead of {@link Map} for backward compat with + // existing native modules that use this Writable* as return types or in events. {@link + // WritableMap} is modified in the Java side, and read (or consumed) on the C++ side. + // In the future, all native modules should ideally return an immutable Map + @DoNotStrip + @Override + @SuppressWarnings("unused") + public WritableMap getObject(ReadableMap arg) { + WritableNativeMap map = new WritableNativeMap(); + map.merge(arg); + log("getObject", arg, map); + return map; + } + + @DoNotStrip + @Override + @SuppressWarnings("unused") + public WritableMap getUnsafeObject(ReadableMap arg) { + WritableNativeMap map = new WritableNativeMap(); + map.merge(arg); + log("getUnsafeObject", arg, map); + return map; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public WritableMap getValue(double numberArg, String stringArg, ReadableMap mapArg) { + WritableMap map = new WritableNativeMap(); + map.putDouble("x", numberArg); + map.putString("y", stringArg); + WritableMap zMap = new WritableNativeMap(); + zMap.merge(mapArg); + map.putMap("z", zMap); + log( + "getValue", + MapBuilder.of("1-numberArg", numberArg, "2-stringArg", stringArg, "3-mapArg", mapArg), + map); + return map; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public void getValueWithCallback(final Callback callback) { + String result = "Value From Callback"; + log("Callback", "Return Time", result); + callback.invoke(result); + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public WritableArray getArray(ReadableArray arg) { + if (arg == null || Arguments.toList(arg) == null) { + // Returning an empty array, since the super class always returns non-null + return new WritableNativeArray(); + } + WritableArray result = Arguments.makeNativeArray(Arguments.toList(arg)); + log("getArray", arg, result); + return result; + } + + @Override + @DoNotStrip + @SuppressWarnings("unused") + public void getValueWithPromise(boolean error, Promise promise) { + if (error) { + promise.reject( + "code 1", + "intentional promise rejection", + new Throwable("promise intentionally rejected")); + } else { + promise.resolve("result"); + } + } + + private void log(String method, Object input, Object output) { + if (mToast != null) { + mToast.cancel(); + } + StringBuilder message = new StringBuilder("Method :"); + message + .append(method) + .append("\nInputs: ") + .append(input.toString()) + .append("\nOutputs: ") + .append(output.toString()); + mToast = Toast.makeText(mContext, message.toString(), Toast.LENGTH_LONG); + mToast.show(); + } + + public void invalidate() {} + + @Override + public String getName() { + return NAME; + } +} diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h b/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h similarity index 96% rename from ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h index 4738cff8d10ad5..b14289e1cd1baa 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h +++ b/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h @@ -26,6 +26,7 @@ - (NSString *)getString:(NSString *)arg; - (NSArray> *)getArray:(NSArray *)arg; - (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSDictionary *)getUnsafeObject:(NSDictionary *)arg; - (NSNumber *)getRootTag:(double)arg; - (NSDictionary *)getValue:(double)x y:(NSString *)y z:(NSDictionary *)z; - (void)getValueWithCallback:(RCTResponseSenderBlock)callback; diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm b/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm similarity index 92% rename from ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm index 70f69b107babb3..7337f63d51814f 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm +++ b/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm @@ -70,6 +70,16 @@ .invokeObjCMethod(rt, ObjectKind, "getObject", @selector(getObject:), args, count); } +static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getUnsafeObject( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) +{ + return static_cast(turboModule) + .invokeObjCMethod(rt, ObjectKind, "getUnsafeObject", @selector(getUnsafeObject:), args, count); +} + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag( facebook::jsi::Runtime &rt, TurboModule &turboModule, @@ -130,6 +140,7 @@ methodMap_["getString"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; methodMap_["getArray"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; methodMap_["getObject"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + methodMap_["getUnsafeObject"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnsafeObject}; methodMap_["getRootTag"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; methodMap_["getValue"] = MethodMetadata{3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; methodMap_["getValueWithCallback"] = diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.h b/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.h similarity index 100% rename from ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.h rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.h diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.mm b/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.mm similarity index 100% rename from ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.mm diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.h b/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.h similarity index 100% rename from ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.h rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.h diff --git a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm b/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.mm similarity index 96% rename from ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.mm index 526dc433a165f2..ac1d236ed7dc2d 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm +++ b/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.mm @@ -17,7 +17,6 @@ @implementation RCTSampleTurboModule // Backward-compatible export RCT_EXPORT_MODULE() -@synthesize bridge = _bridge; @synthesize turboModuleRegistry = _turboModuleRegistry; // Backward-compatible queue configuration @@ -97,6 +96,11 @@ - (NSDictionary *)constantsToExport return arg; } +RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, getUnsafeObject : (NSDictionary *)arg) +{ + return arg; +} + RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, getRootTag : (double)arg) { return @(arg); diff --git a/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp b/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp similarity index 93% rename from ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp rename to ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp index 5eea42c3d8058a..a66b01ef2c16b2 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp +++ b/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp @@ -69,6 +69,12 @@ std::vector SampleTurboCxxModuleLegacyImpl::getMethods() { return getObject(xplat::jsArgAsObject(args, 0)); }, CxxModule::SyncTag), + CxxModule::Method( + "getUnsafeObject", + [this](folly::dynamic args) { + return getUnsafeObject(xplat::jsArgAsObject(args, 0)); + }, + CxxModule::SyncTag), CxxModule::Method( "getRootTag", [this](folly::dynamic args) { @@ -126,6 +132,11 @@ folly::dynamic SampleTurboCxxModuleLegacyImpl::getObject( return arg; } +folly::dynamic SampleTurboCxxModuleLegacyImpl::getUnsafeObject( + const folly::dynamic &arg) { + return arg; +} + double SampleTurboCxxModuleLegacyImpl::getRootTag(double arg) { return arg; } diff --git a/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h b/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h similarity index 95% rename from ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h rename to ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h index 72d0e3b4adbf49..a3aa44062f5728 100644 --- a/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h +++ b/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h @@ -31,6 +31,7 @@ class SampleTurboCxxModuleLegacyImpl std::string getString(const std::string &arg); folly::dynamic getArray(const folly::dynamic &arg); folly::dynamic getObject(const folly::dynamic &arg); + folly::dynamic getUnsafeObject(const folly::dynamic &arg); double getRootTag(double arg); folly::dynamic getValue(double x, const std::string &y, const folly::dynamic &z); diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp index 583176fefac4dd..7acf7a028268e2 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp @@ -29,96 +29,6 @@ namespace facebook { namespace react { -static double -getProgressFromValues(double start, double end, double currentValue) { - auto opacityMinmax = std::minmax({start, end}); - auto min = opacityMinmax.first; - auto max = opacityMinmax.second; - return ( - currentValue < min - ? 0 - : (currentValue > max ? 0 : ((max - currentValue) / (max - min)))); -} - -/** - * Given an animation and a ShadowView with properties set on it, detect how - * far through the animation the ShadowView has progressed. - * - * @param mutationsList - * @param now - */ -double LayoutAnimationDriver::getProgressThroughAnimation( - AnimationKeyFrame const &keyFrame, - LayoutAnimation const *layoutAnimation, - ShadowView const &animationStateView) const { - auto layoutAnimationConfig = layoutAnimation->layoutAnimationConfig; - auto const mutationConfig = - *(keyFrame.type == AnimationConfigurationType::Delete - ? layoutAnimationConfig.deleteConfig - : (keyFrame.type == AnimationConfigurationType::Create - ? layoutAnimationConfig.createConfig - : layoutAnimationConfig.updateConfig)); - - auto initialProps = keyFrame.viewStart.props; - auto finalProps = keyFrame.viewEnd.props; - - if (mutationConfig.animationProperty == AnimationProperty::Opacity) { - // Detect progress through opacity animation. - const auto &oldViewProps = - dynamic_cast(initialProps.get()); - const auto &newViewProps = - dynamic_cast(finalProps.get()); - const auto &animationStateViewProps = - dynamic_cast(animationStateView.props.get()); - if (oldViewProps != nullptr && newViewProps != nullptr && - animationStateViewProps != nullptr) { - return getProgressFromValues( - oldViewProps->opacity, - newViewProps->opacity, - animationStateViewProps->opacity); - } - } else if ( - mutationConfig.animationProperty != AnimationProperty::NotApplicable) { - // Detect progress through layout animation. - LayoutMetrics const &finalLayoutMetrics = keyFrame.viewEnd.layoutMetrics; - LayoutMetrics const &baselineLayoutMetrics = - keyFrame.viewStart.layoutMetrics; - LayoutMetrics const &animationStateLayoutMetrics = - animationStateView.layoutMetrics; - - if (baselineLayoutMetrics.frame.size.height != - finalLayoutMetrics.frame.size.height) { - return getProgressFromValues( - baselineLayoutMetrics.frame.size.height, - finalLayoutMetrics.frame.size.height, - animationStateLayoutMetrics.frame.size.height); - } - if (baselineLayoutMetrics.frame.size.width != - finalLayoutMetrics.frame.size.width) { - return getProgressFromValues( - baselineLayoutMetrics.frame.size.width, - finalLayoutMetrics.frame.size.width, - animationStateLayoutMetrics.frame.size.width); - } - if (baselineLayoutMetrics.frame.origin.x != - finalLayoutMetrics.frame.origin.x) { - return getProgressFromValues( - baselineLayoutMetrics.frame.origin.x, - finalLayoutMetrics.frame.origin.x, - animationStateLayoutMetrics.frame.origin.x); - } - if (baselineLayoutMetrics.frame.origin.y != - finalLayoutMetrics.frame.origin.y) { - return getProgressFromValues( - baselineLayoutMetrics.frame.origin.y, - finalLayoutMetrics.frame.origin.y, - animationStateLayoutMetrics.frame.origin.y); - } - } - - return 0; -} - void LayoutAnimationDriver::animationMutationsForFrame( SurfaceId surfaceId, ShadowViewMutation::List &mutationsList, @@ -132,7 +42,7 @@ void LayoutAnimationDriver::animationMutationsForFrame( } int incompleteAnimations = 0; - for (const auto &keyframe : animation.keyFrames) { + for (auto &keyframe : animation.keyFrames) { if (keyframe.type == AnimationConfigurationType::Noop) { continue; } @@ -146,7 +56,7 @@ void LayoutAnimationDriver::animationMutationsForFrame( // The contract with the "keyframes generation" phase is that any animated // node will have a valid configuration. auto const layoutAnimationConfig = animation.layoutAnimationConfig; - auto const mutationConfig = + auto const &mutationConfig = (keyframe.type == AnimationConfigurationType::Delete ? layoutAnimationConfig.deleteConfig : (keyframe.type == AnimationConfigurationType::Create @@ -155,22 +65,28 @@ void LayoutAnimationDriver::animationMutationsForFrame( // Interpolate std::pair progress = - calculateAnimationProgress(now, animation, *mutationConfig); + calculateAnimationProgress(now, animation, mutationConfig); double animationTimeProgressLinear = progress.first; double animationInterpolationFactor = progress.second; auto mutatedShadowView = createInterpolatedShadowView( - animationInterpolationFactor, - *mutationConfig, - baselineShadowView, - finalShadowView); + animationInterpolationFactor, baselineShadowView, finalShadowView); // Create the mutation instruction auto updateMutation = ShadowViewMutation::UpdateMutation( - keyframe.parentView, baselineShadowView, mutatedShadowView, -1); + keyframe.viewPrev, mutatedShadowView); + + // All generated Update mutations must have an "old" and "new" + // ShadowView. Checking for nonzero tag doesn't guarantee that the views + // are valid/correct, just that something is there. + assert(updateMutation.oldChildShadowView.tag != 0); + assert(updateMutation.newChildShadowView.tag != 0); + mutationsList.push_back(updateMutation); PrintMutationInstruction("Animation Progress:", updateMutation); + keyframe.viewPrev = mutatedShadowView; + if (animationTimeProgressLinear < 1) { incompleteAnimations++; } @@ -191,8 +107,10 @@ void LayoutAnimationDriver::animationMutationsForFrame( // Queue up "final" mutations for all keyframes in the completed animation for (auto const &keyframe : animation.keyFrames) { - if (!keyframe.invalidated && - keyframe.finalMutationForKeyFrame.hasValue()) { + if (keyframe.invalidated) { + continue; + } + if (keyframe.finalMutationForKeyFrame.hasValue()) { auto const &finalMutationForKeyFrame = *keyframe.finalMutationForKeyFrame; PrintMutationInstruction( @@ -201,12 +119,32 @@ void LayoutAnimationDriver::animationMutationsForFrame( // Copy so that if something else mutates the inflight animations, it // won't change this mutation after this point. - mutationsList.push_back( - ShadowViewMutation{finalMutationForKeyFrame.type, - finalMutationForKeyFrame.parentShadowView, - finalMutationForKeyFrame.oldChildShadowView, - finalMutationForKeyFrame.newChildShadowView, - finalMutationForKeyFrame.index}); + auto mutation = ShadowViewMutation{ + finalMutationForKeyFrame.type, + finalMutationForKeyFrame.parentShadowView, + keyframe.viewPrev, + finalMutationForKeyFrame.newChildShadowView, + finalMutationForKeyFrame.index}; + assert(mutation.oldChildShadowView.tag != 0); + assert( + mutation.newChildShadowView.tag != 0 || + finalMutationForKeyFrame.type == ShadowViewMutation::Remove || + finalMutationForKeyFrame.type == ShadowViewMutation::Delete); + mutationsList.push_back(mutation); + } else { + // Issue a final UPDATE so that the final props object sent to the + // mounting layer is the same as the one on the ShadowTree. This is + // mostly to make the MountingCoordinator StubViewTree assertions + // pass. + auto mutation = ShadowViewMutation{ + ShadowViewMutation::Type::Update, + keyframe.parentView, + keyframe.viewPrev, + keyframe.viewEnd, + -1}; + assert(mutation.oldChildShadowView.tag != 0); + assert(mutation.newChildShadowView.tag != 0); + mutationsList.push_back(mutation); } } diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h index 59033afca14463..b0d0dabab851a6 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h @@ -35,10 +35,6 @@ class LayoutAnimationDriver : public LayoutAnimationKeyFrameManager { SurfaceId surfaceId, ShadowViewMutation::List &mutationsList, uint64_t now) const override; - virtual double getProgressThroughAnimation( - AnimationKeyFrame const &keyFrame, - LayoutAnimation const *layoutAnimation, - ShadowView const &animationStateView) const override; }; } // namespace react diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 66bcab91d50292..4ee37947cda4e1 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,8 @@ namespace facebook { namespace react { #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING -std::string GetMutationInstructionString(ShadowViewMutation const &mutation) { +static std::string GetMutationInstructionString( + ShadowViewMutation const &mutation) { bool mutationIsRemove = mutation.type == ShadowViewMutation::Type::Remove; bool mutationIsInsert = mutation.type == ShadowViewMutation::Type::Insert; bool mutationIsDelete = mutation.type == ShadowViewMutation::Type::Delete; @@ -71,22 +73,22 @@ void PrintMutationInstructionRelative( static better::optional parseAnimationType(std::string param) { if (param == "spring") { - return better::optional(AnimationType::Spring); + return AnimationType::Spring; } if (param == "linear") { - return better::optional(AnimationType::Linear); + return AnimationType::Linear; } if (param == "easeInEaseOut") { - return better::optional(AnimationType::EaseInEaseOut); + return AnimationType::EaseInEaseOut; } if (param == "easeIn") { - return better::optional(AnimationType::EaseIn); + return AnimationType::EaseIn; } if (param == "easeOut") { - return better::optional(AnimationType::EaseOut); + return AnimationType::EaseOut; } if (param == "keyboard") { - return better::optional(AnimationType::Keyboard); + return AnimationType::Keyboard; } LOG(ERROR) << "Error parsing animation type: " << param; @@ -96,16 +98,16 @@ static better::optional parseAnimationType(std::string param) { static better::optional parseAnimationProperty( std::string param) { if (param == "opacity") { - return better::optional(AnimationProperty::Opacity); + return AnimationProperty::Opacity; } if (param == "scaleX") { - return better::optional(AnimationProperty::ScaleX); + return AnimationProperty::ScaleX; } if (param == "scaleY") { - return better::optional(AnimationProperty::ScaleY); + return AnimationProperty::ScaleY; } if (param == "scaleXY") { - return better::optional(AnimationProperty::ScaleXY); + return AnimationProperty::ScaleXY; } LOG(ERROR) << "Error parsing animation property: " << param; @@ -117,13 +119,13 @@ static better::optional parseAnimationConfig( double defaultDuration, bool parsePropertyType) { if (config.empty() || !config.isObject()) { - return better::optional( - AnimationConfig{AnimationType::Linear, - AnimationProperty::NotApplicable, - defaultDuration, - 0, - 0, - 0}); + return AnimationConfig{ + AnimationType::Linear, + AnimationProperty::NotApplicable, + defaultDuration, + 0, + 0, + 0}; } auto const typeIt = config.find("type"); @@ -218,12 +220,13 @@ static better::optional parseAnimationConfig( } } - return better::optional(AnimationConfig{*animationType, - animationProperty, - duration, - delay, - springDamping, - initialVelocity}); + return better::optional(AnimationConfig{ + *animationType, + animationProperty, + duration, + delay, + springDamping, + initialVelocity}); } // Parse animation config from JS @@ -290,14 +293,14 @@ void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation( if (layoutAnimationConfig) { std::lock_guard lock(currentAnimationMutex_); - currentAnimation_ = better::optional{ - LayoutAnimation{-1, - 0, - false, - *layoutAnimationConfig, - successCallback, - failureCallback, - {}}}; + currentAnimation_ = better::optional{LayoutAnimation{ + -1, + 0, + false, + *layoutAnimationConfig, + successCallback, + failureCallback, + {}}}; } else { LOG(ERROR) << "Parsing LayoutAnimationConfig failed: " << (folly::dynamic)config; @@ -322,9 +325,7 @@ void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) { } bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const { - // There is potentially a race here between getting and setting - // `currentMutation_`. We don't want to lock around this because then we're - // creating contention between pullTransaction and the JS thread. + std::lock_guard lock(currentAnimationMutex_); return currentAnimation_ || !inflightAnimations_.empty(); } @@ -373,8 +374,9 @@ LayoutAnimationKeyFrameManager::calculateAnimationProgress( } else if (mutationConfig.animationType == AnimationType::EaseInEaseOut) { // This is a combination of accelerate+decelerate. // The animation starts and ends slowly, and speeds up in the middle. - return {linearTimeProgression, - cos((linearTimeProgression + 1.0) * PI) / 2 + 0.5}; + return { + linearTimeProgression, + cos((linearTimeProgression + 1.0) * PI) / 2 + 0.5}; } else if (mutationConfig.animationType == AnimationType::Spring) { // Using mSpringDamping in this equation is not really the exact // mathematical springDamping, but a good approximation We need to replace @@ -395,7 +397,8 @@ void LayoutAnimationKeyFrameManager:: adjustImmediateMutationIndicesForDelayedMutations( SurfaceId surfaceId, ShadowViewMutation &mutation, - ShadowViewMutationList *auxiliaryMutations) const { + bool skipLastAnimation, + bool lastAnimationOnly) const { bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove; assert(isRemoveMutation || mutation.type == ShadowViewMutation::Type::Insert); @@ -415,32 +418,11 @@ void LayoutAnimationKeyFrameManager:: // mutation. std::vector candidateMutations{}; - if (auxiliaryMutations != nullptr) { - for (auto &auxMutation : *auxiliaryMutations) { - if (auxMutation.parentShadowView.tag != mutation.parentShadowView.tag) { - continue; - } - if (auxMutation.type != ShadowViewMutation::Type::Remove) { - continue; - } - if (mutatedViewIsVirtual(auxMutation)) { - continue; - } - if (auxMutation.oldChildShadowView.tag == - (isRemoveMutation ? mutation.oldChildShadowView.tag - : mutation.newChildShadowView.tag)) { - continue; - } - - PrintMutationInstructionRelative( - "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations auxiliary CANDIDATE for:", - mutation, - auxMutation); - candidateMutations.push_back(&auxMutation); - } - } - - for (auto &inflightAnimation : inflightAnimations_) { + for (auto inflightAnimationIt = + inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0); + inflightAnimationIt != inflightAnimations_.rend(); + inflightAnimationIt++) { + auto &inflightAnimation = *inflightAnimationIt; if (inflightAnimation.surfaceId != surfaceId) { continue; } @@ -463,9 +445,6 @@ void LayoutAnimationKeyFrameManager:: continue; } - if (animatedKeyFrame.type != AnimationConfigurationType::Noop) { - continue; - } if (!animatedKeyFrame.finalMutationForKeyFrame.has_value()) { continue; } @@ -490,21 +469,32 @@ void LayoutAnimationKeyFrameManager:: delayedMutation); candidateMutations.push_back(&delayedMutation); } + + if (lastAnimationOnly) { + break; + } } // While the mutation keeps being affected, keep checking. We use the vector // so we only perform one adjustment per delayed mutation. See comments at // bottom of adjustDelayedMutationIndicesForMutation for further explanation. bool changed = true; + int adjustedDelta = 0; while (changed) { changed = false; candidateMutations.erase( std::remove_if( candidateMutations.begin(), candidateMutations.end(), - [&mutation, &changed](ShadowViewMutation *candidateMutation) { - if (candidateMutation->index <= mutation.index) { + [&changed, &mutation, &adjustedDelta, &isRemoveMutation]( + ShadowViewMutation *candidateMutation) { + bool indexConflicts = + (candidateMutation->index < mutation.index || + (isRemoveMutation && + candidateMutation->index == mutation.index)); + if (indexConflicts) { mutation.index++; + adjustedDelta++; changed = true; PrintMutationInstructionRelative( "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations: Adjusting mutation UPWARD", @@ -518,17 +508,10 @@ void LayoutAnimationKeyFrameManager:: } } -void LayoutAnimationKeyFrameManager:: - adjustLastAnimationDelayedMutationIndicesForMutation( - SurfaceId surfaceId, - ShadowViewMutation const &mutation) const { - adjustDelayedMutationIndicesForMutation(surfaceId, mutation, true); -} - void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation( SurfaceId surfaceId, ShadowViewMutation const &mutation, - bool lastAnimationOnly) const { + bool skipLastAnimation) const { bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove; bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert; assert(isRemoveMutation || isInsertMutation); @@ -544,7 +527,8 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation( // mutation. std::vector candidateMutations{}; - for (auto inflightAnimationIt = inflightAnimations_.rbegin(); + for (auto inflightAnimationIt = + inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0); inflightAnimationIt != inflightAnimations_.rend(); inflightAnimationIt++) { auto &inflightAnimation = *inflightAnimationIt; @@ -571,9 +555,6 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation( continue; } - if (animatedKeyFrame.type != AnimationConfigurationType::Noop) { - continue; - } if (!animatedKeyFrame.finalMutationForKeyFrame.has_value()) { continue; } @@ -586,19 +567,19 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation( continue; } - if (!mutatedViewIsVirtual(*animatedKeyFrame.finalMutationForKeyFrame) && - finalAnimationMutation.type == ShadowViewMutation::Type::Remove) { - PrintMutationInstructionRelative( - "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:", - mutation, - *animatedKeyFrame.finalMutationForKeyFrame); - candidateMutations.push_back( - animatedKeyFrame.finalMutationForKeyFrame.get_pointer()); + if (finalAnimationMutation.type != ShadowViewMutation::Type::Remove) { + continue; + } + if (mutatedViewIsVirtual(*animatedKeyFrame.finalMutationForKeyFrame)) { + continue; } - } - if (lastAnimationOnly) { - break; + PrintMutationInstructionRelative( + "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:", + mutation, + *animatedKeyFrame.finalMutationForKeyFrame); + candidateMutations.push_back( + animatedKeyFrame.finalMutationForKeyFrame.get_pointer()); } } @@ -648,19 +629,17 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation( } } -std::vector> +std::vector LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations( SurfaceId surfaceId, - ShadowViewMutationList &mutations, + ShadowViewMutationList const &mutations, bool deletesOnly) const { - std::vector> - conflictingAnimations{}; + std::vector conflictingAnimations{}; - for (auto &mutation : mutations) { + for (auto const &mutation : mutations) { if (deletesOnly && mutation.type != ShadowViewMutation::Type::Delete) { continue; } - PrintMutationInstruction("getAndEraseConflictingAnimations of: ", mutation); auto const &baselineShadowView = (mutation.type == ShadowViewMutation::Type::Insert || @@ -684,59 +663,25 @@ LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations( continue; } - // bool hasFinalMutation = - // animatedKeyFrame.finalMutationForKeyFrame.hasValue(); - // int finalMutationTag = hasFinalMutation - // ? (((*animatedKeyFrame.finalMutationForKeyFrame).type == - // ShadowViewMutation::Create || - // (*animatedKeyFrame.finalMutationForKeyFrame).type == - // ShadowViewMutation::Insert) - // ? (*animatedKeyFrame.finalMutationForKeyFrame) - // .newChildShadowView.tag - // : (*animatedKeyFrame.finalMutationForKeyFrame) - // .oldChildShadowView.tag) - // : -1; bool conflicting = animatedKeyFrame.tag == baselineShadowView.tag || ((mutation.type == ShadowViewMutation::Type::Delete || mutation.type == ShadowViewMutation::Type::Create) && - animatedKeyFrame.parentView.tag == baselineShadowView.tag) /* || - finalMutationTag == baselineShadowView.tag*/ - ; - - // In some bizarre situations, there can be an ongoing Delete - // animation, and then a conflicting mutation to create and/or delete - // the same tag. In actuality this "bizarre" situation is just the - // animation of repeatedly flattening and unflattening a view; but - // it's not clear how to gracefully recover from this, so we just - // ensure that the Deletion is never executed in those cases. In these - // cases, the ongoing animation will stop; the view still exists; and - // then either a "Create" or "delete" animation will be recreated and - // executed for that tag. - bool shouldExecuteFinalMutation = - !(animatedKeyFrame.finalMutationForKeyFrame.hasValue() && - (*animatedKeyFrame.finalMutationForKeyFrame).type == - ShadowViewMutation::Delete); + animatedKeyFrame.parentView.tag == baselineShadowView.tag); // Conflicting animation detected: if we're mutating a tag under // animation, or deleting the parent of a tag under animation, or // reparenting. if (conflicting) { - auto const layoutAnimationConfig = - inflightAnimation.layoutAnimationConfig; - - auto const mutationConfig = - (animatedKeyFrame.type == AnimationConfigurationType::Delete - ? layoutAnimationConfig.deleteConfig - : (animatedKeyFrame.type == - AnimationConfigurationType::Create - ? layoutAnimationConfig.createConfig - : layoutAnimationConfig.updateConfig)); - animatedKeyFrame.invalidated = true; - if (shouldExecuteFinalMutation) { - conflictingAnimations.push_back(std::make_tuple( - animatedKeyFrame, *mutationConfig, &inflightAnimation)); + // We construct a list of all conflicting animations, whether or not + // they have a "final mutation" to execute. This is important with, + // for example, "insert" mutations where the final update needs to set + // opacity to "1", even if there's no final ShadowNode update. + if (!(animatedKeyFrame.finalMutationForKeyFrame.has_value() && + mutatedViewIsVirtual( + *animatedKeyFrame.finalMutationForKeyFrame))) { + conflictingAnimations.push_back(animatedKeyFrame); } #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING @@ -747,7 +692,7 @@ LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations( *animatedKeyFrame.finalMutationForKeyFrame); } else { PrintMutationInstruction( - "Found mutation that conflicts with existing in-flight animation:", + "Found mutation that conflicts with existing in-flight animation (no final mutation):", mutation); } #endif @@ -755,13 +700,6 @@ LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations( // Delete from existing animation it = inflightAnimation.keyFrames.erase(it); } else { - //#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING - // if (hasFinalMutation) { - // PrintMutationInstructionRelative("getAndEraseConflictingAnimations, - // NOT erasing non-conflicting mutation of ", mutation, - // *animatedKeyFrame.finalMutationForKeyFrame); - // } - //#endif it++; } } @@ -832,7 +770,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( LOG(ERROR) << "BEGINNING DISPLAYING ONGOING inflightAnimations_!"; int i = 0; int j = 0; - for (auto &inflightAnimation : inflightAnimations_) { + for (auto const &inflightAnimation : inflightAnimations_) { i++; j = 0; if (inflightAnimation.completed) { @@ -843,7 +781,8 @@ LayoutAnimationKeyFrameManager::pullTransaction( if (keyframe.invalidated) { continue; } - if (keyframe.finalMutationForKeyFrame) { + if (keyframe.finalMutationForKeyFrame && + !mutatedViewIsVirtual(*keyframe.finalMutationForKeyFrame)) { std::string msg = "Animation " + std::to_string(i) + " keyframe " + std::to_string(j) + ": Final Animation"; PrintMutationInstruction(msg, *keyframe.finalMutationForKeyFrame); @@ -869,10 +808,8 @@ LayoutAnimationKeyFrameManager::pullTransaction( // current mutations then these deleted mutations will serve as the baseline // for the next animation. If not, the current mutations are executed // immediately without issues. - std::vector< - std::tuple> - conflictingAnimations = - getAndEraseConflictingAnimations(surfaceId, mutations); + auto conflictingAnimations = + getAndEraseConflictingAnimations(surfaceId, mutations); // Are we animating this list of mutations? better::optional currentAnimation{}; @@ -898,15 +835,23 @@ LayoutAnimationKeyFrameManager::pullTransaction( // being moves on the Differ level, since we know that there? We could use // TinyMap here, but it's not exposed by Differentiator (yet). std::vector insertedTags; - std::vector createdTags; + std::vector deletedTags; + std::vector reparentedTags; // tags that are deleted and recreated std::unordered_map movedTags; - std::vector reparentedTags; for (const auto &mutation : mutations) { if (mutation.type == ShadowViewMutation::Type::Insert) { insertedTags.push_back(mutation.newChildShadowView.tag); } + if (mutation.type == ShadowViewMutation::Type::Delete) { + deletedTags.push_back(mutation.oldChildShadowView.tag); + } if (mutation.type == ShadowViewMutation::Type::Create) { - createdTags.push_back(mutation.newChildShadowView.tag); + if (std::find( + deletedTags.begin(), + deletedTags.end(), + mutation.newChildShadowView.tag) != deletedTags.end()) { + reparentedTags.push_back(mutation.newChildShadowView.tag); + } } } @@ -923,10 +868,11 @@ LayoutAnimationKeyFrameManager::pullTransaction( std::vector keyFramesToAnimate; std::vector movesToAnimate; auto const layoutAnimationConfig = animation.layoutAnimationConfig; - for (auto &mutation : mutations) { + for (auto const &mutation : mutations) { ShadowView baselineShadowView = (mutation.type == ShadowViewMutation::Type::Delete || - mutation.type == ShadowViewMutation::Type::Remove + mutation.type == ShadowViewMutation::Type::Remove || + mutation.type == ShadowViewMutation::Type::Update ? mutation.oldChildShadowView : mutation.newChildShadowView); bool haveComponentDescriptor = @@ -934,13 +880,6 @@ LayoutAnimationKeyFrameManager::pullTransaction( bool executeMutationImmediately = false; - auto mutationConfig = - (mutation.type == ShadowViewMutation::Type::Delete - ? layoutAnimationConfig.deleteConfig - : (mutation.type == ShadowViewMutation::Type::Insert - ? layoutAnimationConfig.createConfig - : layoutAnimationConfig.updateConfig)); - bool isRemoveReinserted = mutation.type == ShadowViewMutation::Type::Remove && std::find( @@ -953,30 +892,19 @@ LayoutAnimationKeyFrameManager::pullTransaction( // This should eventually be optimized out of the diffing algorithm, but // for now we detect reparenting and prevent the corresponding // Delete/Create instructions from being animated. - bool isReparented = - (mutation.type == ShadowViewMutation::Delete && - std::find( - createdTags.begin(), - createdTags.end(), - mutation.oldChildShadowView.tag) != createdTags.end()) || - (mutation.type == ShadowViewMutation::Create && - std::find( - reparentedTags.begin(), - reparentedTags.end(), - mutation.newChildShadowView.tag) != reparentedTags.end()); + bool isReparented = std::find( + reparentedTags.begin(), + reparentedTags.end(), + baselineShadowView.tag) != reparentedTags.end(); if (isRemoveReinserted) { movedTags.insert({mutation.oldChildShadowView.tag, mutation}); } - if (isReparented && mutation.type == ShadowViewMutation::Delete) { - reparentedTags.push_back(mutation.oldChildShadowView.tag); - } - // Inserts that follow a "remove" of the same tag should be treated as // an update (move) animation. bool wasInsertedTagRemoved = false; - bool haveConfiguration = mutationConfig.has_value(); + auto movedIt = movedTags.end(); if (mutation.type == ShadowViewMutation::Type::Insert) { // If this is a move, we actually don't want to copy this insert // instruction to animated instructions - we want to @@ -984,22 +912,30 @@ LayoutAnimationKeyFrameManager::pullTransaction( // the layout. // The corresponding Remove and Insert instructions will instead // be treated as "immediate" instructions. - auto movedIt = movedTags.find(mutation.newChildShadowView.tag); + movedIt = movedTags.find(mutation.newChildShadowView.tag); wasInsertedTagRemoved = movedIt != movedTags.end(); - if (wasInsertedTagRemoved) { - mutationConfig = layoutAnimationConfig.updateConfig; - } - haveConfiguration = mutationConfig.has_value(); - - if (wasInsertedTagRemoved && haveConfiguration) { - movesToAnimate.push_back( - AnimationKeyFrame{{}, - AnimationConfigurationType::Update, - mutation.newChildShadowView.tag, - mutation.parentShadowView, - movedIt->second.oldChildShadowView, - mutation.newChildShadowView}); - } + } + + auto const &mutationConfig = + (mutation.type == ShadowViewMutation::Type::Delete || + (mutation.type == ShadowViewMutation::Type::Remove && + !wasInsertedTagRemoved) + ? layoutAnimationConfig.deleteConfig + : (mutation.type == ShadowViewMutation::Type::Insert && + !wasInsertedTagRemoved + ? layoutAnimationConfig.createConfig + : layoutAnimationConfig.updateConfig)); + bool haveConfiguration = + mutationConfig.animationType != AnimationType::None; + + if (wasInsertedTagRemoved && haveConfiguration) { + movesToAnimate.push_back(AnimationKeyFrame{ + {}, + AnimationConfigurationType::Update, + mutation.newChildShadowView.tag, + mutation.parentShadowView, + movedIt->second.oldChildShadowView, + mutation.newChildShadowView}); } // Creates and inserts should also be executed immediately. @@ -1009,6 +945,32 @@ LayoutAnimationKeyFrameManager::pullTransaction( mutation.type == ShadowViewMutation::Type::Create || mutation.type == ShadowViewMutation::Type::Insert) { executeMutationImmediately = true; + + // It is possible, especially in the case of "moves", that we have a + // sequence of operations like: + // UPDATE X + // REMOVE X + // INSERT X + // In these cases, we will have queued up an animation for the UPDATE + // and delayed its execution; the REMOVE and INSERT will be executed + // first; and then the UPDATE will be animating to/from ShadowViews + // that are out-of-sync with what's on the mounting layer. Thus, for + // any UPDATE animations already queued up for this tag, we adjust the + // "previous" ShadowView. + if (mutation.type == ShadowViewMutation::Type::Insert) { + for (auto &keyframe : keyFramesToAnimate) { + if (keyframe.tag == baselineShadowView.tag) { + // If there's already an animation queued up, followed by this + // Insert, it *must* be an Update mutation animation. Other + // sequences should not be possible. + assert(keyframe.type == AnimationConfigurationType::Update); + + keyframe.viewPrev = mutation.newChildShadowView.tag != 0 + ? mutation.newChildShadowView + : mutation.oldChildShadowView; + } + } + } } // Deletes, non-move inserts, updates get animated @@ -1028,7 +990,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( AnimationKeyFrame keyFrame{}; if (mutation.type == ShadowViewMutation::Type::Insert) { - if (mutationConfig->animationProperty == + if (mutationConfig.animationProperty == AnimationProperty::Opacity && haveComponentDescriptor) { auto props = @@ -1041,12 +1003,12 @@ LayoutAnimationKeyFrameManager::pullTransaction( } viewStart.props = props; } - bool isScaleX = mutationConfig->animationProperty == - AnimationProperty::ScaleX || - mutationConfig->animationProperty == AnimationProperty::ScaleXY; - bool isScaleY = mutationConfig->animationProperty == - AnimationProperty::ScaleY || - mutationConfig->animationProperty == AnimationProperty::ScaleXY; + bool isScaleX = + mutationConfig.animationProperty == AnimationProperty::ScaleX || + mutationConfig.animationProperty == AnimationProperty::ScaleXY; + bool isScaleY = + mutationConfig.animationProperty == AnimationProperty::ScaleY || + mutationConfig.animationProperty == AnimationProperty::ScaleXY; if ((isScaleX || isScaleY) && haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) @@ -1060,15 +1022,17 @@ LayoutAnimationKeyFrameManager::pullTransaction( viewStart.props = props; } - keyFrame = AnimationKeyFrame{{}, - AnimationConfigurationType::Create, - tag, - parent, - viewStart, - viewFinal, - 0}; + keyFrame = AnimationKeyFrame{ + {}, + AnimationConfigurationType::Create, + tag, + parent, + viewStart, + viewFinal, + baselineShadowView, + 0}; } else if (mutation.type == ShadowViewMutation::Type::Delete) { - if (mutationConfig->animationProperty == + if (mutationConfig.animationProperty == AnimationProperty::Opacity && haveComponentDescriptor) { auto props = @@ -1081,12 +1045,12 @@ LayoutAnimationKeyFrameManager::pullTransaction( } viewFinal.props = props; } - bool isScaleX = mutationConfig->animationProperty == - AnimationProperty::ScaleX || - mutationConfig->animationProperty == AnimationProperty::ScaleXY; - bool isScaleY = mutationConfig->animationProperty == - AnimationProperty::ScaleY || - mutationConfig->animationProperty == AnimationProperty::ScaleXY; + bool isScaleX = + mutationConfig.animationProperty == AnimationProperty::ScaleX || + mutationConfig.animationProperty == AnimationProperty::ScaleXY; + bool isScaleY = + mutationConfig.animationProperty == AnimationProperty::ScaleY || + mutationConfig.animationProperty == AnimationProperty::ScaleXY; if ((isScaleX || isScaleY) && haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) @@ -1107,6 +1071,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( parent, viewStart, viewFinal, + baselineShadowView, 0}; } else if (mutation.type == ShadowViewMutation::Type::Update) { viewFinal = ShadowView(mutation.newChildShadowView); @@ -1118,6 +1083,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( parent, viewStart, viewFinal, + baselineShadowView, 0}; } else { // This should just be "Remove" instructions that are not animated @@ -1141,8 +1107,9 @@ LayoutAnimationKeyFrameManager::pullTransaction( AnimationConfigurationType::Noop, tag, parent, - {}, - {}, + mutation.oldChildShadowView, + mutation.oldChildShadowView, + mutation.oldChildShadowView, 0}; } else { PrintMutationInstruction( @@ -1154,38 +1121,19 @@ LayoutAnimationKeyFrameManager::pullTransaction( } // Handle conflicting animations - for (auto &conflictingKeyframeTuple : conflictingAnimations) { - auto &conflictingKeyFrame = std::get<0>(conflictingKeyframeTuple); + for (auto &conflictingKeyFrame : conflictingAnimations) { auto const &conflictingMutationBaselineShadowView = conflictingKeyFrame.viewStart; // We've found a conflict. if (conflictingMutationBaselineShadowView.tag == tag) { - // What's the progress of this ongoing animation? - double conflictingAnimationProgress = - calculateAnimationProgress( - now, - *std::get<2>(conflictingKeyframeTuple), - std::get<1>(conflictingKeyframeTuple)) - .first; - - // Get a baseline ShadowView at the current progress of the - // inflight animation. TODO: handle multiple properties being - // animated separately? - auto interpolatedInflightShadowView = - createInterpolatedShadowView( - conflictingAnimationProgress, - std::get<1>(conflictingKeyframeTuple), - conflictingKeyFrame.viewStart, - conflictingKeyFrame.viewEnd); - // Pick a Prop or layout property, depending on the current // animation configuration. Figure out how much progress we've // already made in the current animation, and start the animation // from this point. - keyFrame.viewStart = interpolatedInflightShadowView; - keyFrame.initialProgress = getProgressThroughAnimation( - keyFrame, &animation, interpolatedInflightShadowView); + keyFrame.viewStart = conflictingKeyFrame.viewPrev; + assert(keyFrame.viewStart.tag != 0); + keyFrame.initialProgress = 0; // We're guaranteed that a tag only has one animation associated // with it, so we can break here. If we support multiple @@ -1195,47 +1143,135 @@ LayoutAnimationKeyFrameManager::pullTransaction( } } + assert(keyFrame.viewStart.tag != 0); + assert(keyFrame.viewEnd.tag != 0); + assert(keyFrame.viewPrev.tag != 0); keyFramesToAnimate.push_back(keyFrame); } if (executeMutationImmediately) { + PrintMutationInstruction( + "Queue Up Animation For Immediate Execution", mutation); immediateMutations.push_back(mutation); } } #ifdef RN_SHADOW_TREE_INTROSPECTION +#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING { - std::stringstream ss(getDebugDescription(immediateMutations, {})); - std::string to; - while (std::getline(ss, to, '\n')) { - LOG(ERROR) - << "LayoutAnimationKeyFrameManager.cpp: got IMMEDIATE list: Line: " - << to; + int idx = 0; + for (auto &mutation : immediateMutations) { + PrintMutationInstruction( + std::string("IMMEDIATE list: ") + std::to_string(idx) + "/" + + std::to_string(immediateMutations.size()), + mutation); + idx++; } } { + int idx = 0; for (const auto &keyframe : keyFramesToAnimate) { - if (keyframe.finalMutationForKeyFrame) { - std::stringstream ss( - getDebugDescription(*keyframe.finalMutationForKeyFrame, {})); - std::string to; - while (std::getline(ss, to, '\n')) { - LOG(ERROR) - << "LayoutAnimationKeyFrameManager.cpp: got FINAL list: Line: " - << to; - } + if (keyframe.finalMutationForKeyFrame.has_value()) { + PrintMutationInstruction( + std::string("FINAL list: ") + std::to_string(idx) + "/" + + std::to_string(keyFramesToAnimate.size()), + *keyframe.finalMutationForKeyFrame); } + idx++; } } +#endif #endif auto finalConflictingMutations = ShadowViewMutationList{}; - for (auto &conflictingKeyframeTuple : conflictingAnimations) { - auto &keyFrame = std::get<0>(conflictingKeyframeTuple); + for (auto &keyFrame : conflictingAnimations) { + // Special-case: if we have some (1) ongoing UPDATE animation, + // (2) it conflicted with a new MOVE operation (REMOVE+INSERT) + // without another corresponding UPDATE, we should re-queue the + // keyframe so that its position/props don't suddenly "jump". + if (keyFrame.type == AnimationConfigurationType::Update) { + auto movedIt = movedTags.find(keyFrame.tag); + if (movedIt != movedTags.end()) { + auto newKeyFrameForUpdate = std::find_if( + keyFramesToAnimate.begin(), + keyFramesToAnimate.end(), + [&](auto const &newKeyFrame) { + return newKeyFrame.type == + AnimationConfigurationType::Update && + newKeyFrame.tag == keyFrame.tag; + }); + if (newKeyFrameForUpdate == keyFramesToAnimate.end()) { + keyFrame.invalidated = false; + + // The animation will continue from the current position - we + // restart viewStart to make sure there are no sudden jumps + keyFrame.viewStart = keyFrame.viewPrev; + + // Find the insert mutation that conflicted with this update + for (auto &mutation : immediateMutations) { + if (mutation.newChildShadowView.tag == keyFrame.tag && + (mutation.type == ShadowViewMutation::Insert || + mutation.type == ShadowViewMutation::Create)) { + keyFrame.viewPrev = mutation.newChildShadowView; + keyFrame.viewEnd = mutation.newChildShadowView; + } + } + keyFramesToAnimate.push_back(keyFrame); + continue; + } + } + } + if (keyFrame.finalMutationForKeyFrame.hasValue()) { - auto &mutation = *keyFrame.finalMutationForKeyFrame; - finalConflictingMutations.push_back(mutation); + auto &finalMutation = *keyFrame.finalMutationForKeyFrame; + auto mutationInstruction = ShadowViewMutation{ + finalMutation.type, + finalMutation.parentShadowView, + keyFrame.viewPrev, + finalMutation.newChildShadowView, + finalMutation.index}; + PrintMutationInstruction( + "Queueing up final mutation instruction - update:", + mutationInstruction); + assert(mutationInstruction.oldChildShadowView.tag != 0); + assert( + mutationInstruction.newChildShadowView.tag != 0 || + mutationInstruction.type == ShadowViewMutation::Delete || + mutationInstruction.type == ShadowViewMutation::Remove); + finalConflictingMutations.push_back(mutationInstruction); + } else { + // If there's no final mutation associated, create a mutation that + // corresponds to the animation being 100% complete. This is important + // for, for example, INSERT mutations being animated from opacity 0 + // to 1. If the animation is interrupted we must force the View to be + // at opacity 1. + // For Android - since it passes along only deltas, not an entire bag + // of props - generate an "animation" frame corresponding to a final + // update for this view. Only then, generate an update that will cause + // the ShadowTree to be consistent with the Mounting layer by passing + // viewEnd, unmodified, to the mounting layer. This helps with, for + // example, opacity animations. + auto mutatedShadowView = createInterpolatedShadowView( + 1, keyFrame.viewStart, keyFrame.viewEnd); + auto generatedPenultimateMutation = + ShadowViewMutation::UpdateMutation( + keyFrame.viewPrev, mutatedShadowView); + assert(generatedPenultimateMutation.oldChildShadowView.tag != 0); + assert(generatedPenultimateMutation.newChildShadowView.tag != 0); + PrintMutationInstruction( + "Queueing up penultimate mutation instruction - synthetic", + generatedPenultimateMutation); + finalConflictingMutations.push_back(generatedPenultimateMutation); + + auto generatedMutation = ShadowViewMutation::UpdateMutation( + mutatedShadowView, keyFrame.viewEnd); + assert(generatedMutation.oldChildShadowView.tag != 0); + assert(generatedMutation.newChildShadowView.tag != 0); + PrintMutationInstruction( + "Queueing up final mutation instruction - synthetic", + generatedMutation); + finalConflictingMutations.push_back(generatedMutation); } } @@ -1246,56 +1282,115 @@ LayoutAnimationKeyFrameManager::pullTransaction( finalConflictingMutations.end(), &shouldFirstComeBeforeSecondMutation); - // Use "final conflicting mutations" to adjust delayed mutations *before* - // we adjust immediate mutations based on delayed mutations + std::stable_sort( + immediateMutations.begin(), + immediateMutations.end(), + &shouldFirstComeBeforeSecondRemovesOnly); + + animation.keyFrames = keyFramesToAnimate; + inflightAnimations_.push_back(std::move(animation)); + + // At this point, we have the following information and knowledge graph: + // Knowledge Graph: + // [ImmediateMutations] -> assumes [FinalConflicting], [FrameDelayed], + // [Delayed] already executed [FrameDelayed] -> assumes + // [FinalConflicting], [Delayed] already executed [FinalConflicting] -> is + // adjusted based on [Delayed], no dependency on [FinalConflicting], + // [FrameDelayed] [Delayed] -> assumes [FinalConflicting], + // [ImmediateMutations] not executed yet + + // Adjust [Delayed] based on [FinalConflicting] + // Knowledge Graph: + // [ImmediateMutations] -> assumes [FinalConflicting], [FrameDelayed], + // [Delayed] already executed [FrameDelayed] -> assumes + // [FinalConflicting], [Delayed] already executed [FinalConflicting] -> is + // adjusted based on [Delayed], no dependency on [FinalConflicting], + // [FrameDelayed] [Delayed] -> adjusted for [FinalConflicting]; assumes + // [ImmediateMutations] not executed yet #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING - LOG(ERROR) - << "Adjust delayed mutations based on finalConflictingMutations"; + LOG(ERROR) << "Adjust [Delayed] based on [FinalConflicting]"; #endif for (auto &mutation : finalConflictingMutations) { - adjustDelayedMutationIndicesForMutation(surfaceId, mutation); + if (mutation.type == ShadowViewMutation::Type::Insert || + mutation.type == ShadowViewMutation::Type::Remove) { + adjustDelayedMutationIndicesForMutation(surfaceId, mutation, true); + } } - // Adjust keyframes based on already-delayed, existing animations, before - // queueing. We adjust them as if finalConflictingMutations have already - // been executed - in all cases, finalConflictingMutations will be - // executed before any of these delayed mutations are. + // Adjust [FrameDelayed] based on [Delayed] + // Knowledge Graph: + // [ImmediateExecutions] -> assumes [FinalConflicting], [Delayed], + // [FrameDelayed] already executed [FrameDelayed] -> adjusted for + // [Delayed]; assumes [FinalConflicting] already executed + // [FinalConflicting] -> is adjusted based on [Delayed], no dependency on + // [FinalConflicting], [FrameDelayed] [Delayed] -> adjusted for + // [FinalConflicting]; assumes [ImmediateExecutions] not executed yet #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING - LOG(ERROR) - << "Adjust immediate keyFramesToAnimate based on delayed mutations and finalConflictingMutations"; + LOG(ERROR) << "Adjust [FrameDelayed] based on [Delayed]"; #endif - for (auto &keyframe : keyFramesToAnimate) { + for (auto &keyframe : inflightAnimations_.back().keyFrames) { if (keyframe.finalMutationForKeyFrame.has_value()) { - auto &delayedMutation = *keyframe.finalMutationForKeyFrame; - if (delayedMutation.type == ShadowViewMutation::Type::Remove) { + auto &mutation = *keyframe.finalMutationForKeyFrame; + if (mutation.type == ShadowViewMutation::Type::Insert || + mutation.type == ShadowViewMutation::Type::Remove) { + // When adjusting, skip adjusting against last animation - because + // all `mutation`s here come from the last animation, so we can't + // adjust a batch against itself. adjustImmediateMutationIndicesForDelayedMutations( - surfaceId, delayedMutation /*, &finalConflictingMutations*/); + surfaceId, mutation, true); } } } - // REMOVE mutations from this animation batch *cannot* be impacted by - // other REMOVEs from this batch, since they're already taken into - // account. INSERTs can impact delayed REMOVEs; see below. + // Adjust [ImmediateExecutions] based on [Delayed] + // Knowledge Graph: + // [ImmediateExecutions] -> adjusted for [FrameDelayed], [Delayed]; + // assumes [FinalConflicting] already executed [FrameDelayed] -> adjusted + // for [Delayed]; assumes [FinalConflicting] already executed + // [FinalConflicting] -> is adjusted based on [Delayed], no dependency on + // [FinalConflicting], [FrameDelayed] [Delayed] -> adjusted for + // [FinalConflicting]; assumes [ImmediateExecutions] not executed yet + // + // THEN, + // Adjust [Delayed] based on [ImmediateExecutions] and [FinalConflicting] + // Knowledge Graph: + // [ImmediateExecutions] -> adjusted for [FrameDelayed], [Delayed]; + // assumes [FinalConflicting] already executed [FrameDelayed] -> adjusted + // for [Delayed]; assumes [FinalConflicting] already executed + // [FinalConflicting] -> is adjusted based on [Delayed], no dependency on + // [FinalConflicting], [FrameDelayed] [Delayed] -> adjusted for + // [FinalConflicting], [ImmediateExecutions] + // + // We do these in the same loop because each immediate execution is + // impacted by each delayed mutation, and also can impact each delayed + // mutation, and these effects compound. #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING LOG(ERROR) - << "Adjust immediateMutations REMOVEs only, based on previously delayed mutations, without most-recent animation"; + << "Adjust each [ImmediateExecution] based on [Delayed] and [Delayed] based on each [ImmediateExecution]"; #endif - std::stable_sort( - immediateMutations.begin(), - immediateMutations.end(), - &shouldFirstComeBeforeSecondRemovesOnly); for (auto &mutation : immediateMutations) { - if (mutation.type == ShadowViewMutation::Type::Remove) { + // Note: when adjusting [ImmediateExecutions] based on [FrameDelayed], + // we need only adjust Inserts. Since inserts are executed + // highest-index-first, lower indices being delayed does not impact the + // higher-index removals; and conversely, higher indices being delayed + // cannot impact lower index removal, regardless of order. + if (mutation.type == ShadowViewMutation::Type::Insert || + mutation.type == ShadowViewMutation::Type::Remove) { adjustImmediateMutationIndicesForDelayedMutations( - surfaceId, mutation); + surfaceId, + mutation, + mutation.type == ShadowViewMutation::Type::Remove); + // Here we need to adjust both Delayed and FrameDelayed mutations. + // Delayed Removes can be impacted by non-delayed Inserts from the + // same frame. adjustDelayedMutationIndicesForMutation(surfaceId, mutation); } } - animation.keyFrames = keyFramesToAnimate; - inflightAnimations_.push_back(std::move(animation)); - + // If the knowledge graph progression above is correct, it is now safe to + // execute finalConflictingMutations and immediateMutations in that order, + // and to queue the delayed animations from this frame. + // // Execute the conflicting, delayed operations immediately. Any UPDATE // operations that smoothly transition into another animation will be // overridden by generated UPDATE operations at the end of the list, and @@ -1303,45 +1398,93 @@ LayoutAnimationKeyFrameManager::pullTransaction( // Additionally, this should allow us to avoid performing index adjustment // between this list of conflicting animations and the batch we're about // to execute. - mutations = ShadowViewMutationList{}; - for (auto &mutation : finalConflictingMutations) { - mutations.push_back(mutation); + finalConflictingMutations.insert( + finalConflictingMutations.end(), + immediateMutations.begin(), + immediateMutations.end()); + mutations = finalConflictingMutations; + } /* if (currentAnimation) */ else { + // If there's no "next" animation, make sure we queue up "final" + // operations from all ongoing, conflicting animations. +#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING + LOG(ERROR) << "No Animation: Queue up final conflicting animations"; +#endif + ShadowViewMutationList finalMutationsForConflictingAnimations{}; + for (auto const &keyFrame : conflictingAnimations) { + if (keyFrame.finalMutationForKeyFrame.hasValue()) { + auto &finalMutation = (*keyFrame.finalMutationForKeyFrame); + auto mutation = ShadowViewMutation{ + finalMutation.type, + finalMutation.parentShadowView, + keyFrame.viewPrev, + finalMutation.newChildShadowView, + finalMutation.index}; + PrintMutationInstruction( + "No Animation: Queueing up final conflicting mutation instruction", + mutation); + finalMutationsForConflictingAnimations.push_back(mutation); + } else { + // If there's no final mutation associated, create a mutation that + // corresponds to the animation being 100% complete. This is important + // for, for example, INSERT mutations being animated from opacity 0 + // to 1. If the animation is interrupted we must force the View to be + // at opacity 1. + // For Android - since it passes along only deltas, not an entire bag + // of props - generate an "animation" frame corresponding to a final + // update for this view. Only then, generate an update that will cause + // the ShadowTree to be consistent with the Mounting layer by passing + // viewEnd, unmodified, to the mounting layer. This helps with, for + // example, opacity animations. + auto mutatedShadowView = createInterpolatedShadowView( + 1, keyFrame.viewStart, keyFrame.viewEnd); + auto generatedPenultimateMutation = + ShadowViewMutation::UpdateMutation( + keyFrame.viewPrev, mutatedShadowView); + assert(generatedPenultimateMutation.oldChildShadowView.tag != 0); + assert(generatedPenultimateMutation.newChildShadowView.tag != 0); + PrintMutationInstruction( + "No Animation: Queueing up penultimate mutation instruction - synthetic", + generatedPenultimateMutation); + finalMutationsForConflictingAnimations.push_back( + generatedPenultimateMutation); + + auto generatedMutation = ShadowViewMutation::UpdateMutation( + mutatedShadowView, keyFrame.viewEnd); + assert(generatedMutation.oldChildShadowView.tag != 0); + assert(generatedMutation.newChildShadowView.tag != 0); + PrintMutationInstruction( + "No Animation: Queueing up final mutation instruction - synthetic", + generatedMutation); + finalMutationsForConflictingAnimations.push_back(generatedMutation); + } } - // Before computing mutations based on animations / final mutations for - // this frame, we want to update any pending final mutations since they - // will execute *after* this batch of immediate mutations. Important case - // to consider (as an example, there are other interesting cases): there's - // a delayed "Remove", then an immediate "insert" is scheduled for an - // earlier index with the same parent. The remove needs to be adjusted - // upward here. Conversely, Inserts at later indices will assume the - // remove has already been executed, which may not be the case. + // Make sure that all operations execute in the proper order. + // REMOVE operations with highest indices must operate first. + std::stable_sort( + finalMutationsForConflictingAnimations.begin(), + finalMutationsForConflictingAnimations.end(), + &shouldFirstComeBeforeSecondMutation); + #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING LOG(ERROR) - << "Adjust immediateMutations and delayed mutations, including just-queued animations, based on each one"; + << "No Animation: Adjust delayed mutations based on all finalMutationsForConflictingAnimations"; #endif - for (auto &mutation : immediateMutations) { - if (mutation.type == ShadowViewMutation::Type::Remove) { - adjustLastAnimationDelayedMutationIndicesForMutation( - surfaceId, mutation); - } else if (mutation.type == ShadowViewMutation::Type::Insert) { - adjustImmediateMutationIndicesForDelayedMutations( - surfaceId, mutation); + for (auto const &mutation : finalMutationsForConflictingAnimations) { + if (mutation.type == ShadowViewMutation::Type::Remove || + mutation.type == ShadowViewMutation::Type::Insert) { adjustDelayedMutationIndicesForMutation(surfaceId, mutation); } } - // These will be executed immediately. These should already be sorted - // properly. - mutations.insert( - mutations.end(), - immediateMutations.begin(), - immediateMutations.end()); - } /* if (currentAnimation) */ else { // The ShadowTree layer doesn't realize that certain operations have been // delayed, so we must adjust all Remove and Insert operations based on // what else has been deferred, whether we are executing this immediately // or later. +#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING + LOG(ERROR) + << "No Animation: Adjust mutations based on remaining delayed mutations / adjust delayed, based on each"; +#endif for (auto &mutation : mutations) { if (mutation.type == ShadowViewMutation::Type::Remove || mutation.type == ShadowViewMutation::Type::Insert) { @@ -1351,24 +1494,6 @@ LayoutAnimationKeyFrameManager::pullTransaction( } } - // If there's no "next" animation, make sure we queue up "final" - // operations from all ongoing, conflicting animations. - ShadowViewMutationList finalMutationsForConflictingAnimations{}; - for (auto &conflictingKeyframeTuple : conflictingAnimations) { - auto &keyFrame = std::get<0>(conflictingKeyframeTuple); - if (keyFrame.finalMutationForKeyFrame.hasValue()) { - finalMutationsForConflictingAnimations.push_back( - *keyFrame.finalMutationForKeyFrame); - } - } - - // Make sure that all operations execute in the proper order. - // REMOVE operations with highest indices must operate first. - std::stable_sort( - finalMutationsForConflictingAnimations.begin(), - finalMutationsForConflictingAnimations.end(), - &shouldFirstComeBeforeSecondMutation); - // Append mutations to this list and swap - so that the final // conflicting mutations happen before any other mutations finalMutationsForConflictingAnimations.insert( @@ -1388,13 +1513,6 @@ LayoutAnimationKeyFrameManager::pullTransaction( ShadowViewMutationList mutationsForAnimation{}; animationMutationsForFrame(surfaceId, mutationsForAnimation, now); - // Erase any remaining animations that conflict with these mutations - // In some marginal cases, a DELETE animation can be queued up and a final - // DELETE mutation be executed by the animation driver. These cases deserve - // further scrutiny, but for now to prevent crashes, just make sure the queued - // DELETE operations are removed. - getAndEraseConflictingAnimations(surfaceId, mutationsForAnimation, true); - // If any delayed removes were executed, update remaining delayed keyframes #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING LOG(ERROR) @@ -1416,7 +1534,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( LOG(ERROR) << "FINISHING DISPLAYING ONGOING inflightAnimations_!"; int i = 0; int j = 0; - for (auto &inflightAnimation : inflightAnimations_) { + for (auto const &inflightAnimation : inflightAnimations_) { i++; j = 0; if (inflightAnimation.completed) { @@ -1427,7 +1545,8 @@ LayoutAnimationKeyFrameManager::pullTransaction( if (keyframe.invalidated) { continue; } - if (keyframe.finalMutationForKeyFrame) { + if (keyframe.finalMutationForKeyFrame && + !mutatedViewIsVirtual(*keyframe.finalMutationForKeyFrame)) { std::string msg = "Animation " + std::to_string(i) + " keyframe " + std::to_string(j) + ": Final Animation"; PrintMutationInstruction(msg, *keyframe.finalMutationForKeyFrame); @@ -1502,7 +1621,6 @@ void LayoutAnimationKeyFrameManager::setComponentDescriptorRegistry( */ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( double progress, - AnimationConfig const &animationConfig, ShadowView startingView, ShadowView finalView) const { if (!hasComponentDescriptorForShadowView(startingView)) { @@ -1510,7 +1628,15 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( } ComponentDescriptor const &componentDescriptor = getComponentDescriptorForShadowView(startingView); - auto mutatedShadowView = ShadowView(startingView); + + // Base the mutated view on the finalView, so that the following stay + // consistent: + // - state + // - eventEmitter + // For now, we do not allow interpolation of state. And we probably never + // will, so make sure we always keep the mounting layer consistent with the + // "final" state. + auto mutatedShadowView = ShadowView(finalView); if (startingView.props == nullptr || finalView.props == nullptr) { return finalView; diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h index 686fcaa9da9e21..de5239c30f838f 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h @@ -81,9 +81,9 @@ struct AnimationConfig { // This corresponds exactly with JS. struct LayoutAnimationConfig { double duration; // ms - better::optional createConfig; - better::optional updateConfig; - better::optional deleteConfig; + AnimationConfig createConfig; + AnimationConfig updateConfig; + AnimationConfig deleteConfig; }; struct AnimationKeyFrame { @@ -103,6 +103,9 @@ struct AnimationKeyFrame { ShadowView viewStart; ShadowView viewEnd; + // ShadowView representing the previous frame of the animation. + ShadowView viewPrev; + // If an animation interrupts an existing one, the starting state may actually // be halfway through the intended transition. double initialProgress; @@ -115,7 +118,6 @@ class LayoutAnimationCallbackWrapper { LayoutAnimationCallbackWrapper(jsi::Function &&callback) : callback_(std::make_shared(std::move(callback))) {} LayoutAnimationCallbackWrapper() : callback_(nullptr) {} - ~LayoutAnimationCallbackWrapper() {} // Copy and assignment-copy constructors should copy callback_, and not // std::move it. Copying is desirable, otherwise the shared_ptr and @@ -131,7 +133,7 @@ class LayoutAnimationCallbackWrapper { } std::weak_ptr callable = callback_; - std::shared_ptr callComplete = callComplete_; + std::shared_ptr callComplete = callComplete_; runtimeExecutor( [=, callComplete = std::move(callComplete)](jsi::Runtime &runtime) { @@ -147,7 +149,8 @@ class LayoutAnimationCallbackWrapper { } private: - std::shared_ptr callComplete_ = std::make_shared(false); + std::shared_ptr callComplete_ = + std::make_shared(false); std::shared_ptr callback_; }; @@ -212,21 +215,17 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, void adjustImmediateMutationIndicesForDelayedMutations( SurfaceId surfaceId, ShadowViewMutation &mutation, - ShadowViewMutationList *auxiliaryMutations = nullptr) const; + bool skipLastAnimation = false, + bool lastAnimationOnly = false) const; void adjustDelayedMutationIndicesForMutation( SurfaceId surfaceId, ShadowViewMutation const &mutation, - bool lastAnimationOnly = false) const; - - void adjustLastAnimationDelayedMutationIndicesForMutation( - SurfaceId surfaceId, - ShadowViewMutation const &mutation) const; + bool skipLastAnimation = false) const; - std::vector> - getAndEraseConflictingAnimations( + std::vector getAndEraseConflictingAnimations( SurfaceId surfaceId, - ShadowViewMutationList &mutations, + ShadowViewMutationList const &mutations, bool deletesOnly = false) const; mutable std::mutex surfaceIdsToStopMutex_; @@ -245,7 +244,6 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, ShadowView createInterpolatedShadowView( double progress, - AnimationConfig const &animationConfig, ShadowView startingView, ShadowView finalView) const; @@ -256,11 +254,6 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, ShadowViewMutation::List &mutationsList, uint64_t now) const = 0; - virtual double getProgressThroughAnimation( - AnimationKeyFrame const &keyFrame, - LayoutAnimation const *layoutAnimation, - ShadowView const &animationStateView) const = 0; - SharedComponentDescriptorRegistry componentDescriptorRegistry_; mutable better::optional currentAnimation_{}; mutable std::mutex currentAnimationMutex_; @@ -304,6 +297,14 @@ static inline bool shouldFirstComeBeforeSecondMutation( return true; } + // Update comes last, before deletes + if (rhs.type == ShadowViewMutation::Type::Update) { + return true; + } + if (lhs.type == ShadowViewMutation::Type::Update) { + return false; + } + // Remove comes before insert if (lhs.type == ShadowViewMutation::Type::Remove && rhs.type == ShadowViewMutation::Type::Insert) { @@ -313,6 +314,16 @@ static inline bool shouldFirstComeBeforeSecondMutation( lhs.type == ShadowViewMutation::Type::Insert) { return false; } + + // Create comes before insert + if (lhs.type == ShadowViewMutation::Type::Create && + rhs.type == ShadowViewMutation::Type::Insert) { + return true; + } + if (rhs.type == ShadowViewMutation::Type::Create && + lhs.type == ShadowViewMutation::Type::Insert) { + return false; + } } else { // Make sure that removes on the same level are sorted - highest indices // must come first. diff --git a/ReactCommon/react/renderer/attributedstring/AttributedStringBox.cpp b/ReactCommon/react/renderer/attributedstring/AttributedStringBox.cpp index 5983a7fc754518..83d10b365bf42a 100644 --- a/ReactCommon/react/renderer/attributedstring/AttributedStringBox.cpp +++ b/ReactCommon/react/renderer/attributedstring/AttributedStringBox.cpp @@ -24,6 +24,14 @@ AttributedStringBox::AttributedStringBox( std::shared_ptr const &opaquePointer) : mode_(Mode::OpaquePointer), value_({}), opaquePointer_(opaquePointer) {} +AttributedStringBox::AttributedStringBox(AttributedStringBox &&other) noexcept + : mode_(other.mode_), + value_(std::move(other.value_)), + opaquePointer_(std::move(other.opaquePointer_)) { + other.mode_ = AttributedStringBox::Mode::Value; + other.value_ = std::make_shared(AttributedString{}); +} + AttributedStringBox::Mode AttributedStringBox::getMode() const { return mode_; } @@ -40,6 +48,18 @@ std::shared_ptr AttributedStringBox::getOpaquePointer() const { return opaquePointer_; } +AttributedStringBox &AttributedStringBox::operator=( + AttributedStringBox &&other) { + if (this != &other) { + mode_ = other.mode_; + value_ = std::move(other.value_); + opaquePointer_ = std::move(other.opaquePointer_); + other.mode_ = AttributedStringBox::Mode::Value; + other.value_ = std::make_shared(AttributedString{}); + } + return *this; +} + bool operator==( AttributedStringBox const &lhs, AttributedStringBox const &rhs) { @@ -48,9 +68,9 @@ bool operator==( } switch (lhs.getMode()) { - case facebook::react::AttributedStringBox::Mode::Value: + case AttributedStringBox::Mode::Value: return lhs.getValue() == rhs.getValue(); - case facebook::react::AttributedStringBox::Mode::OpaquePointer: + case AttributedStringBox::Mode::OpaquePointer: return lhs.getOpaquePointer() == rhs.getOpaquePointer(); } } diff --git a/ReactCommon/react/renderer/attributedstring/AttributedStringBox.h b/ReactCommon/react/renderer/attributedstring/AttributedStringBox.h index 7965a7d6d288fd..b8bd96c9caebee 100644 --- a/ReactCommon/react/renderer/attributedstring/AttributedStringBox.h +++ b/ReactCommon/react/renderer/attributedstring/AttributedStringBox.h @@ -41,9 +41,9 @@ class AttributedStringBox final { * Movable, Copyable, Assignable. */ AttributedStringBox(AttributedStringBox const &other) = default; - AttributedStringBox(AttributedStringBox &&other) noexcept = default; + AttributedStringBox(AttributedStringBox &&other) noexcept; AttributedStringBox &operator=(AttributedStringBox const &other) = default; - AttributedStringBox &operator=(AttributedStringBox &&other) = default; + AttributedStringBox &operator=(AttributedStringBox &&other); /* * Getters. diff --git a/ReactCommon/react/renderer/attributedstring/BUCK b/ReactCommon/react/renderer/attributedstring/BUCK index 9ab399565e0078..7405ecddb60fb2 100644 --- a/ReactCommon/react/renderer/attributedstring/BUCK +++ b/ReactCommon/react/renderer/attributedstring/BUCK @@ -74,6 +74,7 @@ fb_xplat_cxx_test( "-Wall", ], contacts = ["oncall+react_native@xmail.facebook.com"], + fbandroid_use_instrumentation_test = True, platforms = (ANDROID, APPLE, CXX), deps = [ ":attributedstring", diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 26c8b5f37f0799..a121a09028e2ea 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -768,6 +768,10 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { _textAttributes( "layoutDirection", toString(*textAttributes.layoutDirection)); } + if (textAttributes.accessibilityRole.has_value()) { + _textAttributes( + "accessibilityRole", toString(*textAttributes.accessibilityRole)); + } return _textAttributes; } diff --git a/ReactCommon/react/renderer/attributedstring/tests/AttributedStringTest.cpp b/ReactCommon/react/renderer/attributedstring/tests/AttributedStringTest.cpp index 9e84969713d080..f0dff668592653 100644 --- a/ReactCommon/react/renderer/attributedstring/tests/AttributedStringTest.cpp +++ b/ReactCommon/react/renderer/attributedstring/tests/AttributedStringTest.cpp @@ -5,9 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -#include - -#include #include #include #include @@ -20,28 +17,28 @@ namespace react { #ifdef ANDROID TEST(AttributedStringTest, testToDynamic) { - auto attString = new AttributedString(); - auto fragment = new AttributedString::Fragment(); - fragment->string = "test"; + auto attributedString = AttributedString{}; + auto fragment = AttributedString::Fragment{}; + fragment.string = "test"; - auto text = new TextAttributes(); - text->foregroundColor = { + auto text = TextAttributes{}; + text.foregroundColor = { colorFromComponents({100 / 255.0, 153 / 255.0, 200 / 255.0, 1.0})}; - text->opacity = 0.5; - text->fontStyle = FontStyle::Italic; - text->fontWeight = FontWeight::Thin; - text->fontVariant = FontVariant::TabularNums; - fragment->textAttributes = *text; + text.opacity = 0.5; + text.fontStyle = FontStyle::Italic; + text.fontWeight = FontWeight::Thin; + text.fontVariant = FontVariant::TabularNums; + fragment.textAttributes = text; - attString->prependFragment(*fragment); + attributedString.appendFragment(fragment); - auto result = toDynamic(*attString); - assert(result["string"] == fragment->string); + auto result = toDynamic(attributedString); + EXPECT_EQ(result["string"], fragment.string); auto textAttribute = result["fragments"][0]["textAttributes"]; - assert(textAttribute["foregroundColor"] == toDynamic(text->foregroundColor)); - assert(textAttribute["opacity"] == text->opacity); - assert(textAttribute["fontStyle"] == toString(*text->fontStyle)); - assert(textAttribute["fontWeight"] == toString(*text->fontWeight)); + EXPECT_EQ(textAttribute["foregroundColor"], toDynamic(text.foregroundColor)); + EXPECT_EQ(textAttribute["opacity"], text.opacity); + EXPECT_EQ(textAttribute["fontStyle"], toString(text.fontStyle.value())); + EXPECT_EQ(textAttribute["fontWeight"], toString(text.fontWeight.value())); } #endif diff --git a/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp b/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp index 56378937062f11..8b44e8b9fc2b94 100644 --- a/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp +++ b/ReactCommon/react/renderer/attributedstring/tests/ParagraphAttributesTest.cpp @@ -5,9 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -#include - -#include #include #include #include @@ -19,20 +16,18 @@ namespace react { #ifdef ANDROID TEST(ParagraphAttributesTest, testToDynamic) { - auto paragraphAttributes = ParagraphAttributes(); + auto paragraphAttributes = ParagraphAttributes{}; paragraphAttributes.maximumNumberOfLines = 2; paragraphAttributes.adjustsFontSizeToFit = false; paragraphAttributes.ellipsizeMode = EllipsizeMode::Middle; auto result = toDynamic(paragraphAttributes); - assert( - result["maximumNumberOfLines"] == - paragraphAttributes.maximumNumberOfLines); - assert( - result["adjustsFontSizeToFit"] == - paragraphAttributes.adjustsFontSizeToFit); - assert( - result["ellipsizeMode"] == toString(paragraphAttributes.ellipsizeMode)); + EXPECT_EQ( + result["maximumNumberOfLines"], paragraphAttributes.maximumNumberOfLines); + EXPECT_EQ( + result["adjustsFontSizeToFit"], paragraphAttributes.adjustsFontSizeToFit); + EXPECT_EQ( + result["ellipsizeMode"], toString(paragraphAttributes.ellipsizeMode)); } #endif diff --git a/ReactCommon/react/renderer/attributedstring/tests/TextAttributesTest.cpp b/ReactCommon/react/renderer/attributedstring/tests/TextAttributesTest.cpp index 7c25e0c7278ad9..7fce2b9a7835b4 100644 --- a/ReactCommon/react/renderer/attributedstring/tests/TextAttributesTest.cpp +++ b/ReactCommon/react/renderer/attributedstring/tests/TextAttributesTest.cpp @@ -5,9 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -#include - -#include #include #include #include @@ -20,19 +17,20 @@ namespace react { #ifdef ANDROID TEST(TextAttributesTest, testToDynamic) { - auto text = TextAttributes(); - text.foregroundColor = { + auto textAttributes = TextAttributes{}; + textAttributes.foregroundColor = { colorFromComponents({200 / 255.0, 153 / 255.0, 100 / 255.0, 1.0})}; - text.opacity = 0.5; - text.fontStyle = FontStyle::Italic; - text.fontWeight = FontWeight::Thin; - text.fontVariant = FontVariant::TabularNums; - - auto result = toDynamic(text); - assert(result["foregroundColor"] == toDynamic(text.foregroundColor)); - assert(result["opacity"] == text.opacity); - assert(result["fontStyle"] == toString(*text.fontStyle)); - assert(result["fontWeight"] == toString(*text.fontWeight)); + textAttributes.opacity = 0.5; + textAttributes.fontStyle = FontStyle::Italic; + textAttributes.fontWeight = FontWeight::Thin; + textAttributes.fontVariant = FontVariant::TabularNums; + + auto result = toDynamic(textAttributes); + EXPECT_EQ( + result["foregroundColor"], toDynamic(textAttributes.foregroundColor)); + EXPECT_EQ(result["opacity"], textAttributes.opacity); + EXPECT_EQ(result["fontStyle"], toString(textAttributes.fontStyle.value())); + EXPECT_EQ(result["fontWeight"], toString(textAttributes.fontWeight.value())); } #endif diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProvider.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProvider.h index c321d4af91691c..99e91a8e9a7c23 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProvider.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProvider.h @@ -63,10 +63,11 @@ ComponentDescriptorProvider concreteComponentDescriptorProvider() { std::is_base_of::value, "ComponentDescriptorT must be a descendant of ComponentDescriptor"); - return {ComponentDescriptorT::ConcreteShadowNode::Handle(), - ComponentDescriptorT::ConcreteShadowNode::Name(), - nullptr, - &concreteComponentDescriptorConstructor}; + return { + ComponentDescriptorT::ConcreteShadowNode::Handle(), + ComponentDescriptorT::ConcreteShadowNode::Name(), + nullptr, + &concreteComponentDescriptorConstructor}; } } // namespace react diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index ede6ca809372ea..77f9fbcab89443 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -185,9 +185,9 @@ SharedShadowNode ComponentDescriptorRegistry::createNode( auto unifiedComponentName = componentNameByReactViewName(viewName); auto const &componentDescriptor = this->at(unifiedComponentName); - auto family = componentDescriptor.createFamily( - ShadowNodeFamilyFragment{tag, surfaceId, nullptr}, - std::move(eventTarget)); + auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr}; + auto family = + componentDescriptor.createFamily(fragment, std::move(eventTarget)); auto const props = componentDescriptor.cloneProps(nullptr, RawProps(propsDynamic)); auto const state = diff --git a/ReactCommon/react/renderer/components/image/BUCK b/ReactCommon/react/renderer/components/image/BUCK index 682ea9ddb22312..205771229aea14 100644 --- a/ReactCommon/react/renderer/components/image/BUCK +++ b/ReactCommon/react/renderer/components/image/BUCK @@ -47,10 +47,7 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ - "//third-party/glog:glog", - "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", - "//xplat/folly:memory", "//xplat/folly:molly", YOGA_CXX_TARGET, react_native_xplat_target("react/renderer/debug:debug"), diff --git a/ReactCommon/react/renderer/components/image/ImageProps.cpp b/ReactCommon/react/renderer/components/image/ImageProps.cpp index c716b786f7d390..4a496bba12d011 100644 --- a/ReactCommon/react/renderer/components/image/ImageProps.cpp +++ b/ReactCommon/react/renderer/components/image/ImageProps.cpp @@ -30,7 +30,12 @@ ImageProps::ImageProps(const ImageProps &sourceProps, const RawProps &rawProps) capInsets( convertRawProp(rawProps, "capInsets", sourceProps.capInsets, {})), tintColor( - convertRawProp(rawProps, "tintColor", sourceProps.tintColor, {})) {} + convertRawProp(rawProps, "tintColor", sourceProps.tintColor, {})), + internal_analyticTag(convertRawProp( + rawProps, + "internal_analyticTag", + sourceProps.internal_analyticTag, + {})) {} } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/components/image/ImageProps.h b/ReactCommon/react/renderer/components/image/ImageProps.h index 7ed6ac4e1800e1..7ecfc27b8f7143 100644 --- a/ReactCommon/react/renderer/components/image/ImageProps.h +++ b/ReactCommon/react/renderer/components/image/ImageProps.h @@ -26,6 +26,7 @@ class ImageProps final : public ViewProps { const Float blurRadius{}; const EdgeInsets capInsets{}; const SharedColor tintColor{}; + const std::string internal_analyticTag{}; }; } // namespace react diff --git a/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp b/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp index fe20bc78845db6..64a1020e2e2178 100644 --- a/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp +++ b/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp @@ -25,7 +25,7 @@ void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) { void ImageShadowNode::updateStateIfNeeded() { ensureUnsealed(); - auto const &imageSource = getImageSource(); + auto imageSource = getImageSource(); auto const ¤tState = getStateData(); bool hasSameRadius = getConcreteProps().blurRadius == currentState.getBlurRadius(); @@ -35,10 +35,10 @@ void ImageShadowNode::updateStateIfNeeded() { return; } - auto state = - ImageState{imageSource, - imageManager_->requestImage(imageSource, getSurfaceId()), - getConcreteProps().blurRadius}; + auto state = ImageState{ + imageSource, + imageManager_->requestImage(imageSource, getSurfaceId()), + getConcreteProps().blurRadius}; setStateData(std::move(state)); } diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp index 891c0e0aecce1e..5d123f49f4df43 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp @@ -10,10 +10,20 @@ namespace facebook { namespace react { +static folly::dynamic recursiveMerge( + folly::dynamic const &lhs, + folly::dynamic const &rhs) { + auto copy = lhs; + copy.merge_patch(rhs); + return copy; +} + LegacyViewManagerInteropViewProps::LegacyViewManagerInteropViewProps( const LegacyViewManagerInteropViewProps &sourceProps, const RawProps &rawProps) - : ViewProps(sourceProps, rawProps), otherProps((folly::dynamic)rawProps) {} + : ViewProps(sourceProps, rawProps), + otherProps( + recursiveMerge(sourceProps.otherProps, (folly::dynamic)rawProps)) {} } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm index d8f1b4abf4ed7b..cab75ac3882009 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,11 @@ - (instancetype)initWithComponentData:(RCTComponentData *)componentData bridge:( __weak __typeof(self) weakSelf = self; _componentData.eventInterceptor = ^(NSString *eventName, NSDictionary *event, NSNumber *reactTag) { __typeof(self) strongSelf = weakSelf; - InterceptorBlock block = [strongSelf->_eventInterceptors objectForKey:reactTag]; - if (block) { - block(std::string([RCTNormalizeInputEventName(eventName) UTF8String]), convertIdToFollyDynamic(event ?: @{})); + if (strongSelf) { + InterceptorBlock block = [strongSelf->_eventInterceptors objectForKey:reactTag]; + if (block) { + block(std::string([RCTNormalizeInputEventName(eventName) UTF8String]), convertIdToFollyDynamic(event ?: @{})); + } } }; } diff --git a/ReactCommon/react/renderer/components/modal/Android.mk b/ReactCommon/react/renderer/components/modal/Android.mk index dd404e8dbda309..fd6e0ab65527d4 100644 --- a/ReactCommon/react/renderer/components/modal/Android.mk +++ b/ReactCommon/react/renderer/components/modal/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_image libreact_render_uimanager libreact_render_imagemanager libreact_render_components_view libreact_render_componentregistry libreact_render_viewmanagers +LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_image libreact_render_uimanager libreact_render_imagemanager libreact_render_components_view libreact_render_componentregistry libreact_codegen_rncore include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/modal/ModalHostViewState.h b/ReactCommon/react/renderer/components/modal/ModalHostViewState.h index 51e3677ff5459b..92ab4c5afb7e40 100644 --- a/ReactCommon/react/renderer/components/modal/ModalHostViewState.h +++ b/ReactCommon/react/renderer/components/modal/ModalHostViewState.h @@ -32,8 +32,9 @@ class ModalHostViewState final { ModalHostViewState( ModalHostViewState const &previousState, folly::dynamic data) - : screenSize(Size{(Float)data["screenWidth"].getDouble(), - (Float)data["screenHeight"].getDouble()}){}; + : screenSize(Size{ + (Float)data["screenWidth"].getDouble(), + (Float)data["screenHeight"].getDouble()}){}; #endif const Size screenSize{}; diff --git a/ReactCommon/react/renderer/components/picker/Android.mk b/ReactCommon/react/renderer/components/picker/Android.mk index be55965cece467..a00db4ffb35bfc 100644 --- a/ReactCommon/react/renderer/components/picker/Android.mk +++ b/ReactCommon/react/renderer/components/picker/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_components_view libreact_render_componentregistry libreact_render_viewmanagers +LOCAL_SHARED_LIBRARIES := libyoga glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_uimanager libreact_render_components_view libreact_render_componentregistry libreact_codegen_rncore include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/picker/BUCK b/ReactCommon/react/renderer/components/picker/BUCK index 985b331f4ac36f..9c0661e9370b2d 100644 --- a/ReactCommon/react/renderer/components/picker/BUCK +++ b/ReactCommon/react/renderer/components/picker/BUCK @@ -19,11 +19,11 @@ APPLE_COMPILER_FLAGS = get_apple_compiler_flags() rn_xplat_cxx_library( name = "androidpicker", srcs = glob( - ["**/*.cpp"], + ["androidpicker/**/*.cpp"], exclude = glob(["tests/**/*.cpp"]), ), headers = glob( - ["**/*.h"], + ["androidpicker/**/*.h"], exclude = glob(["tests/**/*.h"]), ), header_namespace = "", diff --git a/ReactCommon/react/renderer/components/picker/iospicker/BUCK b/ReactCommon/react/renderer/components/picker/iospicker/BUCK new file mode 100644 index 00000000000000..8e48198de3ea73 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/BUCK @@ -0,0 +1,58 @@ +load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode") +load( + "//tools/build_defs/oss:rn_defs.bzl", + "ANDROID", + "APPLE", + "CXX", + "YOGA_CXX_TARGET", + "get_apple_compiler_flags", + "get_apple_inspector_flags", + "react_native_xplat_target", + "rn_xplat_cxx_library", + "subdir_glob", +) + +APPLE_COMPILER_FLAGS = get_apple_compiler_flags() + +rn_xplat_cxx_library( + name = "iospicker", + srcs = glob( + ["**/*.cpp"], + ), + headers = glob( + ["**/*.h"], + ), + header_namespace = "", + exported_headers = subdir_glob( + [ + ("", "*.h"), + ], + prefix = "react/renderer/components/iospicker", + ), + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, + fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), + force_static = True, + labels = ["supermodule:xplat/default/public.react_native.infra"], + platforms = (ANDROID, APPLE, CXX), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/folly:headers_only", + YOGA_CXX_TARGET, + react_native_xplat_target("react/utils:utils"), + react_native_xplat_target("react/renderer/attributedstring:attributedstring"), + react_native_xplat_target("react/renderer/core:core"), + react_native_xplat_target("react/renderer/graphics:graphics"), + react_native_xplat_target("react/renderer/components/text:text"), + react_native_xplat_target("react/renderer/components/view:view"), + ], +) diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerComponentDescriptor.h b/ReactCommon/react/renderer/components/picker/iospicker/PickerComponentDescriptor.h new file mode 100644 index 00000000000000..d134689e784623 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerComponentDescriptor.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +/* + * Descriptor for component. + */ +namespace facebook { +namespace react { + +class PickerComponentDescriptor final + : public ConcreteComponentDescriptor { + public: + using ConcreteComponentDescriptor::ConcreteComponentDescriptor; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.cpp b/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.cpp new file mode 100644 index 00000000000000..9e608966063531 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "PickerEventEmitter.h" + +namespace facebook { +namespace react { + +void PickerEventEmitter::onChange(PickerIOSChangeEvent event) const { + dispatchEvent("change", [event = std::move(event)](jsi::Runtime &runtime) { + auto payload = jsi::Object(runtime); + payload.setProperty(runtime, "newValue", event.newValue); + payload.setProperty(runtime, "newIndex", event.newIndex); + return payload; + }); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.h b/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.h new file mode 100644 index 00000000000000..fea36adf3f699f --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +class PickerEventEmitter : public ViewEventEmitter { + public: + using ViewEventEmitter::ViewEventEmitter; + + struct PickerIOSChangeEvent { + std::string newValue; + int newIndex; + }; + + void onChange(PickerIOSChangeEvent event) const; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.cpp b/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.cpp new file mode 100644 index 00000000000000..b3a06ad0029781 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "PickerProps.h" + +#include +#include +#include + +namespace facebook { +namespace react { + +PickerProps::PickerProps( + PickerProps const &sourceProps, + RawProps const &rawProps) + : ViewProps(sourceProps, rawProps), + BaseTextProps(sourceProps, rawProps), + items(convertRawProp(rawProps, "items", sourceProps.items, {})), + selectedIndex(convertRawProp( + rawProps, + "selectedIndex", + sourceProps.selectedIndex, + {0})), + testID(convertRawProp(rawProps, "testID", sourceProps.testID, {})), + accessibilityLabel(convertRawProp( + rawProps, + "accessibilityLabel", + sourceProps.accessibilityLabel, + {})){ + + }; + +TextAttributes PickerProps::getEffectiveTextAttributes() const { + auto result = TextAttributes::defaultTextAttributes(); + // Default is left aligned, but Picker wants default to be center aligned. + result.alignment = TextAlignment::Center; + result.apply(textAttributes); + return result; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.h b/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.h new file mode 100644 index 00000000000000..c87ca2fe4969a7 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerProps.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +#include + +namespace facebook { +namespace react { + +class PickerProps final : public ViewProps, public BaseTextProps { + public: + PickerProps() = default; + PickerProps(PickerProps const &sourceProps, RawProps const &rawProps); + +#pragma mark - Props + + std::vector items{}; + int selectedIndex{0}; + std::string const testID{}; + std::string const accessibilityLabel{}; + +#pragma mark - Accessors + TextAttributes getEffectiveTextAttributes() const; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.cpp b/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.cpp new file mode 100644 index 00000000000000..2d39cdb106b856 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "PickerShadowNode.h" + +namespace facebook { +namespace react { + +extern const char PickerComponentName[] = "Picker"; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.h b/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.h new file mode 100644 index 00000000000000..c2c80bc6ae2a03 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +extern const char PickerComponentName[]; + +/* + * `ShadowNode` for component. + */ +class PickerShadowNode final : public ConcreteViewShadowNode< + PickerComponentName, + PickerProps, + PickerEventEmitter, + PickerState> { + public: + using ConcreteViewShadowNode::ConcreteViewShadowNode; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/PickerState.h b/ReactCommon/react/renderer/components/picker/iospicker/PickerState.h new file mode 100644 index 00000000000000..fa50b38dfdbf6a --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/PickerState.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +namespace facebook { +namespace react { + +/* + * State for component. + */ +class PickerState final {}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/conversions.h b/ReactCommon/react/renderer/components/picker/iospicker/conversions.h new file mode 100644 index 00000000000000..b39f10431b78bc --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/conversions.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include + +namespace facebook { +namespace react { + +inline void fromRawValue( + const RawValue &value, + std::vector &items) { + assert(value.hasType>()); + auto array = (std::vector)value; + items.reserve(array.size()); + + for (auto const &val : array) { + bool check = val.hasType>(); + assert(check); + auto map = (better::map)val; + PickerItemsStruct item; + + if (map.find("label") != map.end()) { + assert(map.at("label").hasType()); + item.label = (std::string)map.at("label"); + } + if (map.find("value") != map.end()) { + assert(map.at("value").hasType()); + item.value = (std::string)map.at("value"); + } + if (map.find("textColor") != map.end()) { + assert(map.at("textColor").hasType()); + item.textColor = (int)map.at("textColor"); + } + items.push_back(item); + } +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/picker/iospicker/primitives.h b/ReactCommon/react/renderer/components/picker/iospicker/primitives.h new file mode 100644 index 00000000000000..d9804aa98868e4 --- /dev/null +++ b/ReactCommon/react/renderer/components/picker/iospicker/primitives.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include + +namespace facebook { +namespace react { + +struct PickerItemsStruct { + std::string label; + std::string value; + SharedColor textColor; + + bool operator==(const PickerItemsStruct &rhs) const { + return ( + label == rhs.label && value == rhs.value && textColor == rhs.textColor); + } +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/components/progressbar/Android.mk b/ReactCommon/react/renderer/components/progressbar/Android.mk index f17cb34c809c55..ad9a268c434986 100644 --- a/ReactCommon/react/renderer/components/progressbar/Android.mk +++ b/ReactCommon/react/renderer/components/progressbar/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libfbjni libreact_render_viewmanagers libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view +LOCAL_SHARED_LIBRARIES := libfbjni libreact_codegen_rncore libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h index 1bd4e47e62ea68..2a27f0ef227c38 100644 --- a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h +++ b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h @@ -26,6 +26,13 @@ class SafeAreaViewShadowNode final : public ConcreteViewShadowNode< ViewEventEmitter, SafeAreaViewState> { using ConcreteViewShadowNode::ConcreteViewShadowNode; + + public: + static ShadowNodeTraits BaseTraits() { + auto traits = ConcreteViewShadowNode::BaseTraits(); + traits.set(ShadowNodeTraits::Trait::DirtyYogaNode); + return traits; + } }; } // namespace react diff --git a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewState.h b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewState.h index 6b4c0c008059cb..f64b1bb275b6bf 100644 --- a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewState.h +++ b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewState.h @@ -17,9 +17,7 @@ namespace react { */ class SafeAreaViewState final { public: - using Shared = std::shared_ptr; - - EdgeInsets const padding{}; + EdgeInsets padding{}; }; } // namespace react diff --git a/ReactCommon/react/renderer/components/scrollview/RCTComponentViewHelpers.h b/ReactCommon/react/renderer/components/scrollview/RCTComponentViewHelpers.h index ce4303c2c94afd..0fab3ae8160e68 100644 --- a/ReactCommon/react/renderer/components/scrollview/RCTComponentViewHelpers.h +++ b/ReactCommon/react/renderer/components/scrollview/RCTComponentViewHelpers.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)flashScrollIndicators; - (void)scrollTo:(double)x y:(double)y animated:(BOOL)animated; - (void)scrollToEnd:(BOOL)animated; +- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated; @end RCT_EXTERN inline void @@ -90,6 +91,43 @@ RCTScrollViewHandleCommand(id componentView, NSString con [componentView scrollToEnd:animated]; return; } + + if ([commandName isEqualToString:@"zoomToRect"]) { +#if RCT_DEBUG + if ([args count] != 2) { + RCTLogError( + @"%@ command %@ received %d arguments, expected %d.", @"ScrollView", commandName, (int)[args count], 2); + return; + } +#endif + + NSObject *arg0 = args[0]; + +#if RCT_DEBUG + if (!RCTValidateTypeOfViewCommandArgument( + arg0, [NSDictionary class], @"dictionary", @"ScrollView", commandName, @"1st")) { + return; + } +#endif + + NSDictionary *rectDict = (NSDictionary *)arg0; + NSNumber *x = rectDict[@"x"]; + NSNumber *y = rectDict[@"y"]; + NSNumber *width = rectDict[@"width"]; + NSNumber *height = rectDict[@"height"]; + CGRect rect = CGRectMake(x.doubleValue, y.doubleValue, width.doubleValue, height.doubleValue); + + NSObject *arg1 = args[1]; +#if RCT_DEBUG + if (!RCTValidateTypeOfViewCommandArgument(arg1, [NSNumber class], @"boolean", @"ScrollView", commandName, @"2nd")) { + return; + } +#endif + + BOOL animated = [(NSNumber *)arg1 boolValue]; + [componentView zoomToRect:rect animated:animated]; + return; + } } NS_ASSUME_NONNULL_END diff --git a/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp b/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp index feaa68d8ddb39d..c030761da73279 100644 --- a/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +++ b/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp @@ -164,7 +164,12 @@ ScrollViewProps::ScrollViewProps( rawProps, "contentInsetAdjustmentBehavior", sourceProps.contentInsetAdjustmentBehavior, - {ContentInsetAdjustmentBehavior::Never})) {} + {ContentInsetAdjustmentBehavior::Never})), + scrollToOverflowEnabled(convertRawProp( + rawProps, + "scrollToOverflowEnabled", + sourceProps.scrollToOverflowEnabled, + {})) {} #pragma mark - DebugStringConvertible diff --git a/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h b/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h index 2a9c485f5406dc..09336eec7569b5 100644 --- a/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +++ b/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h @@ -53,6 +53,7 @@ class ScrollViewProps final : public ViewProps { bool snapToEnd{true}; ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{ ContentInsetAdjustmentBehavior::Never}; + bool scrollToOverflowEnabled{false}; #pragma mark - DebugStringConvertible diff --git a/ReactCommon/react/renderer/components/scrollview/ScrollViewState.h b/ReactCommon/react/renderer/components/scrollview/ScrollViewState.h index d2ec294a239e4f..a2ea7b945f81c0 100644 --- a/ReactCommon/react/renderer/components/scrollview/ScrollViewState.h +++ b/ReactCommon/react/renderer/components/scrollview/ScrollViewState.h @@ -30,8 +30,9 @@ class ScrollViewState final { #ifdef ANDROID ScrollViewState() = default; ScrollViewState(ScrollViewState const &previousState, folly::dynamic data) - : contentOffset({(Float)data["contentOffsetLeft"].getDouble(), - (Float)data["contentOffsetTop"].getDouble()}), + : contentOffset( + {(Float)data["contentOffsetLeft"].getDouble(), + (Float)data["contentOffsetTop"].getDouble()}), contentBoundingRect({}){}; folly::dynamic getDynamic() const { diff --git a/ReactCommon/react/renderer/components/slider/Android.mk b/ReactCommon/react/renderer/components/slider/Android.mk index 23e58023b81d81..a687de48bd0632 100644 --- a/ReactCommon/react/renderer/components/slider/Android.mk +++ b/ReactCommon/react/renderer/components/slider/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libfbjni libreact_render_viewmanagers libreact_render_imagemanager libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libreact_render_components_image libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view +LOCAL_SHARED_LIBRARIES := libfbjni libreact_codegen_rncore libreact_render_imagemanager libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libreact_render_components_image libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/slider/BUCK b/ReactCommon/react/renderer/components/slider/BUCK index 7030c52be1751f..00f0df782327af 100644 --- a/ReactCommon/react/renderer/components/slider/BUCK +++ b/ReactCommon/react/renderer/components/slider/BUCK @@ -80,10 +80,7 @@ rn_xplat_cxx_library( ], visibility = ["PUBLIC"], deps = [ - "//third-party/glog:glog", - "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", - "//xplat/folly:memory", "//xplat/folly:molly", YOGA_CXX_TARGET, react_native_xplat_target("react/renderer/debug:debug"), diff --git a/ReactCommon/react/renderer/components/slider/SliderShadowNode.h b/ReactCommon/react/renderer/components/slider/SliderShadowNode.h index 82ab4d0b1dc6c2..ebd2eca0483606 100644 --- a/ReactCommon/react/renderer/components/slider/SliderShadowNode.h +++ b/ReactCommon/react/renderer/components/slider/SliderShadowNode.h @@ -43,14 +43,15 @@ class SliderShadowNode final : public ConcreteViewShadowNode< ShadowNodeFamilyFragment const &familyFragment, ComponentDescriptor const &componentDescriptor) { auto imageSource = ImageSource{ImageSource::Type::Invalid}; - return {imageSource, - {imageSource, nullptr}, - imageSource, - {imageSource, nullptr}, - imageSource, - {imageSource, nullptr}, - imageSource, - {imageSource, nullptr}}; + return { + imageSource, + {imageSource, nullptr}, + imageSource, + {imageSource, nullptr}, + imageSource, + {imageSource, nullptr}, + imageSource, + {imageSource, nullptr}}; } #pragma mark - LayoutableShadowNode diff --git a/ReactCommon/react/renderer/components/slider/platform/android/react/renderer/components/slider/SliderMeasurementsManager.cpp b/ReactCommon/react/renderer/components/slider/platform/android/react/renderer/components/slider/SliderMeasurementsManager.cpp index 0f7322ad0efbbf..24bc977fbad790 100644 --- a/ReactCommon/react/renderer/components/slider/platform/android/react/renderer/components/slider/SliderMeasurementsManager.cpp +++ b/ReactCommon/react/renderer/components/slider/platform/android/react/renderer/components/slider/SliderMeasurementsManager.cpp @@ -59,8 +59,14 @@ Size SliderMeasurementsManager::measure( minimumSize.height, maximumSize.height)); - std::lock_guard lock(mutex_); - cachedMeasurement_ = measurement; + // Explicitly release smart pointers to free up space faster in JNI tables + componentName.reset(); + + { + std::lock_guard lock(mutex_); + cachedMeasurement_ = measurement; + } + return measurement; } diff --git a/ReactCommon/react/renderer/components/switch/Android.mk b/ReactCommon/react/renderer/components/switch/Android.mk index 65be95635a04d8..4805dc1292fdd6 100644 --- a/ReactCommon/react/renderer/components/switch/Android.mk +++ b/ReactCommon/react/renderer/components/switch/Android.mk @@ -21,7 +21,7 @@ LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall LOCAL_STATIC_LIBRARIES := -LOCAL_SHARED_LIBRARIES := libfbjni libreact_render_viewmanagers libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view +LOCAL_SHARED_LIBRARIES := libfbjni libreact_codegen_rncore libreactnativeutilsjni libreact_render_componentregistry libreact_render_uimanager libyoga libfolly_futures glog libfolly_json libglog_init libreact_render_core libreact_render_debug libreact_render_graphics libreact_render_components_view include $(BUILD_SHARED_LIBRARY) diff --git a/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h b/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h index d2e925f4c8c80a..c60b1da600148e 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h +++ b/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h @@ -54,12 +54,6 @@ class ParagraphComponentDescriptor final // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content // and communicate text rendering metrics to mounting layer. paragraphShadowNode->setTextLayoutManager(textLayoutManager_); - - paragraphShadowNode->dirtyLayout(); - - // All `ParagraphShadowNode`s must have leaf Yoga nodes with properly - // setup measure function. - paragraphShadowNode->enableMeasurement(); } private: diff --git a/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.cpp b/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.cpp index 1295108286f14b..ee16f5d02655c9 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.cpp +++ b/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.cpp @@ -38,12 +38,17 @@ static jsi::Value linesMeasurementsPayload( void ParagraphEventEmitter::onTextLayout( LinesMeasurements const &linesMeasurements) const { - dispatchEvent( - "textLayout", - [linesMeasurements](jsi::Runtime &runtime) { - return linesMeasurementsPayload(runtime, linesMeasurements); - }, - EventPriority::AsynchronousBatched); + { + std::lock_guard guard(linesMeasurementsMutex_); + if (linesMeasurementsMetrics_ == linesMeasurements) { + return; + } + linesMeasurementsMetrics_ = linesMeasurements; + } + + dispatchEvent("textLayout", [linesMeasurements](jsi::Runtime &runtime) { + return linesMeasurementsPayload(runtime, linesMeasurements); + }); } } // namespace react diff --git a/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.h b/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.h index b73eb967d5afb2..597ef6baa2ddcb 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.h +++ b/ReactCommon/react/renderer/components/text/ParagraphEventEmitter.h @@ -18,6 +18,10 @@ class ParagraphEventEmitter : public ViewEventEmitter { using ViewEventEmitter::ViewEventEmitter; void onTextLayout(LinesMeasurements const &linesMeasurements) const; + + private: + mutable std::mutex linesMeasurementsMutex_; + mutable LinesMeasurements linesMeasurementsMetrics_; }; } // namespace react diff --git a/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp b/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp index 993cc65b8834ee..0adadd10b18a6a 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp +++ b/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp @@ -112,9 +112,10 @@ void ParagraphShadowNode::updateStateIfNeeded(Content const &content) { return; } - setStateData(ParagraphState{content.attributedString, - content.paragraphAttributes, - textLayoutManager_}); + setStateData(ParagraphState{ + content.attributedString, + content.paragraphAttributes, + textLayoutManager_}); } #pragma mark - LayoutableShadowNode @@ -169,7 +170,6 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) { content.paragraphAttributes, layoutConstraints); -#ifndef ANDROID if (getConcreteProps().onTextLayout) { auto linesMeasurements = textLayoutManager_->measureLines( content.attributedString, @@ -177,10 +177,9 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) { measurement.size); getConcreteEventEmitter().onTextLayout(linesMeasurements); } -#endif if (content.attachments.empty()) { - // No attachments, nothing to layout. + // No attachments to layout. return; } diff --git a/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h b/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h index 4a584edb44a51d..4ff1beb859d464 100644 --- a/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h +++ b/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h @@ -41,6 +41,7 @@ class ParagraphShadowNode : public ConcreteViewShadowNode< auto traits = ConcreteViewShadowNode::BaseTraits(); traits.set(ShadowNodeTraits::Trait::LeafYogaNode); traits.set(ShadowNodeTraits::Trait::TextKind); + traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode); #ifdef ANDROID // Unsetting `FormsStackingContext` trait is essential on Android where we diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h index 3918684ed6015e..26abeff7b997ab 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h @@ -62,6 +62,8 @@ class AndroidTextInputComponentDescriptor final theme[YGEdgeBottom] = (YGValue){defaultTextInputPadding[3], YGUnitPoint}; surfaceIdToThemePaddingMap_.emplace(std::make_pair(surfaceId, theme)); + env->ReleaseFloatArrayElements( + defaultTextInputPaddingArray, defaultTextInputPadding, JNI_ABORT); } env->DeleteLocalRef(defaultTextInputPaddingArray); } diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp index 42b47276bf024c..6d3ad4e8308cbb 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp @@ -131,6 +131,11 @@ void AndroidTextInputShadowNode::updateStateIfNeeded() { return; } + // If props event counter is less than what we already have in state, skip it + if (getConcreteProps().mostRecentEventCount < state.mostRecentEventCount) { + return; + } + // Store default TextAttributes in state. // In the case where the TextInput is completely empty (no value, no // defaultValue, no placeholder, no children) there are therefore no fragments @@ -150,17 +155,18 @@ void AndroidTextInputShadowNode::updateStateIfNeeded() { // current attributedString unchanged, and pass in zero for the "event count" // so no changes are applied There's no way to prevent a state update from // flowing to Java, so we just ensure it's a noop in those cases. - setStateData(AndroidTextInputState{newEventCount, - newAttributedString, - reactTreeAttributedString, - getConcreteProps().paragraphAttributes, - defaultTextAttributes, - ShadowView(*this), - textLayoutManager_, - state.defaultThemePaddingStart, - state.defaultThemePaddingEnd, - state.defaultThemePaddingTop, - state.defaultThemePaddingBottom}); + setStateData(AndroidTextInputState{ + newEventCount, + newAttributedString, + reactTreeAttributedString, + getConcreteProps().paragraphAttributes, + defaultTextAttributes, + ShadowView(*this), + textLayoutManager_, + state.defaultThemePaddingStart, + state.defaultThemePaddingEnd, + state.defaultThemePaddingTop, + state.defaultThemePaddingBottom}); } #pragma mark - LayoutableShadowNode diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp index 6cb7b115612114..70f89eb40e7561 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.cpp @@ -13,15 +13,82 @@ namespace facebook { namespace react { +AndroidTextInputState::AndroidTextInputState( + int64_t mostRecentEventCount, + AttributedString const &attributedString, + AttributedString const &reactTreeAttributedString, + ParagraphAttributes const ¶graphAttributes, + TextAttributes const &defaultTextAttributes, + ShadowView const &defaultParentShadowView, + SharedTextLayoutManager const &layoutManager, + float defaultThemePaddingStart, + float defaultThemePaddingEnd, + float defaultThemePaddingTop, + float defaultThemePaddingBottom) + : mostRecentEventCount(mostRecentEventCount), + cachedAttributedStringId(0), + attributedString(attributedString), + reactTreeAttributedString(reactTreeAttributedString), + paragraphAttributes(paragraphAttributes), + defaultTextAttributes(defaultTextAttributes), + defaultParentShadowView(defaultParentShadowView), + layoutManager(layoutManager), + defaultThemePaddingStart(defaultThemePaddingStart), + defaultThemePaddingEnd(defaultThemePaddingEnd), + defaultThemePaddingTop(defaultThemePaddingTop), + defaultThemePaddingBottom(defaultThemePaddingBottom) {} + +AndroidTextInputState::AndroidTextInputState( + AndroidTextInputState const &previousState, + folly::dynamic const &data) + : mostRecentEventCount(data.getDefault( + "mostRecentEventCount", + previousState.mostRecentEventCount) + .getInt()), + cachedAttributedStringId(data.getDefault( + "opaqueCacheId", + previousState.cachedAttributedStringId) + .getInt()), + attributedString(previousState.attributedString), + reactTreeAttributedString(previousState.reactTreeAttributedString), + paragraphAttributes(previousState.paragraphAttributes), + defaultTextAttributes(previousState.defaultTextAttributes), + defaultParentShadowView(previousState.defaultParentShadowView), + layoutManager(previousState.layoutManager), + defaultThemePaddingStart(data.getDefault( + "themePaddingStart", + previousState.defaultThemePaddingStart) + .getDouble()), + defaultThemePaddingEnd(data.getDefault( + "themePaddingEnd", + previousState.defaultThemePaddingEnd) + .getDouble()), + defaultThemePaddingTop(data.getDefault( + "themePaddingTop", + previousState.defaultThemePaddingTop) + .getDouble()), + defaultThemePaddingBottom(data.getDefault( + "themePaddingBottom", + previousState.defaultThemePaddingBottom) + .getDouble()){}; + #ifdef ANDROID folly::dynamic AndroidTextInputState::getDynamic() const { - // Java doesn't need all fields, so we don't pass them along. + // Java doesn't need all fields, so we don't pass them all along. folly::dynamic newState = folly::dynamic::object(); - newState["mostRecentEventCount"] = mostRecentEventCount; - newState["attributedString"] = toDynamic(attributedString); - newState["hash"] = newState["attributedString"]["hash"]; - newState["paragraphAttributes"] = - toDynamic(paragraphAttributes); // TODO: can we memoize this in Java? + + // If we have a `cachedAttributedStringId` we know that we're (1) not trying + // to set a new string, so we don't need to pass it along; (2) setState was + // called from Java to trigger a relayout with a `cachedAttributedStringId`, + // so Java has all up-to-date information and we should pass an empty map + // through. + if (cachedAttributedStringId == 0) { + newState["mostRecentEventCount"] = mostRecentEventCount; + newState["attributedString"] = toDynamic(attributedString); + newState["hash"] = newState["attributedString"]["hash"]; + newState["paragraphAttributes"] = + toDynamic(paragraphAttributes); // TODO: can we memoize this in Java? + } return newState; } #endif diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h index 2c039ab8a3f92c..c97ade9565c5ec 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputState.h @@ -29,7 +29,7 @@ class AndroidTextInputState final { * Stores an opaque cache ID used on the Java side to refer to a specific * AttributedString for measurement purposes only. */ - int cachedAttributedStringId{0}; + int64_t cachedAttributedStringId{0}; /* * All content of component represented as an `AttributedString`. @@ -93,53 +93,12 @@ class AndroidTextInputState final { float defaultThemePaddingStart, float defaultThemePaddingEnd, float defaultThemePaddingTop, - float defaultThemePaddingBottom) - : mostRecentEventCount(mostRecentEventCount), - cachedAttributedStringId(0), - attributedString(attributedString), - reactTreeAttributedString(reactTreeAttributedString), - paragraphAttributes(paragraphAttributes), - defaultTextAttributes(defaultTextAttributes), - defaultParentShadowView(defaultParentShadowView), - layoutManager(layoutManager), - defaultThemePaddingStart(defaultThemePaddingStart), - defaultThemePaddingEnd(defaultThemePaddingEnd), - defaultThemePaddingTop(defaultThemePaddingTop), - defaultThemePaddingBottom(defaultThemePaddingBottom) {} + float defaultThemePaddingBottom); + AndroidTextInputState() = default; AndroidTextInputState( AndroidTextInputState const &previousState, - folly::dynamic const &data) - : mostRecentEventCount(data.getDefault( - "mostRecentEventCount", - previousState.mostRecentEventCount) - .getInt()), - cachedAttributedStringId( - data.getDefault("cacheId", previousState.cachedAttributedStringId) - .getInt()), - attributedString(previousState.attributedString), - reactTreeAttributedString(previousState.reactTreeAttributedString), - paragraphAttributes(previousState.paragraphAttributes), - defaultTextAttributes(previousState.defaultTextAttributes), - defaultParentShadowView(previousState.defaultParentShadowView), - layoutManager(previousState.layoutManager), - defaultThemePaddingStart(data.getDefault( - "themePaddingStart", - previousState.defaultThemePaddingStart) - .getDouble()), - defaultThemePaddingEnd(data.getDefault( - "themePaddingEnd", - previousState.defaultThemePaddingEnd) - .getDouble()), - defaultThemePaddingTop(data.getDefault( - "themePaddingTop", - previousState.defaultThemePaddingTop) - .getDouble()), - defaultThemePaddingBottom( - data.getDefault( - "themePaddingBottom", - previousState.defaultThemePaddingBottom) - .getDouble()){}; + folly::dynamic const &data); folly::dynamic getDynamic() const; }; diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h index 9614fd5712d5b8..55b4d8afa1b7e9 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h @@ -34,8 +34,6 @@ class TextInputComponentDescriptor final std::static_pointer_cast(shadowNode); concreteShadowNode->setTextLayoutManager(textLayoutManager_); - concreteShadowNode->dirtyLayout(); - concreteShadowNode->enableMeasurement(); } private: diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h index 4924c4f8b6b3b5..8974372c317af5 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h @@ -37,6 +37,7 @@ class TextInputShadowNode : public ConcreteViewShadowNode< auto traits = ConcreteViewShadowNode::BaseTraits(); traits.set(ShadowNodeTraits::Trait::TextKind); traits.set(ShadowNodeTraits::Trait::LeafYogaNode); + traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode); return traits; } diff --git a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index aa4c1f47795cdd..d47d3782a6bf4e 100644 --- a/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -88,7 +88,7 @@ AccessibilityProps::AccessibilityProps( "importantForAccessibility", sourceProps.importantForAccessibility, ImportantForAccessibility::Auto)), - testId(convertRawProp(rawProps, "testId", sourceProps.testId, "")) {} + testId(convertRawProp(rawProps, "testID", sourceProps.testId, "")) {} #pragma mark - DebugStringConvertible diff --git a/ReactCommon/react/renderer/components/view/TouchEvent.h b/ReactCommon/react/renderer/components/view/TouchEvent.h index 4725fa4eec4d32..02f7ab4e636191 100644 --- a/ReactCommon/react/renderer/components/view/TouchEvent.h +++ b/ReactCommon/react/renderer/components/view/TouchEvent.h @@ -16,8 +16,6 @@ namespace facebook { namespace react { -using Touches = std::unordered_set; - /* * Defines the `touchstart`, `touchend`, `touchmove`, and `touchcancel` event * types. diff --git a/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp b/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp index 4b582c6ba47bb3..c02b1c3bcc784e 100644 --- a/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp +++ b/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp @@ -12,8 +12,10 @@ namespace react { #pragma mark - Touches -static jsi::Value touchPayload(jsi::Runtime &runtime, Touch const &touch) { - auto object = jsi::Object(runtime); +static void setTouchPayloadOnObject( + jsi::Object &object, + jsi::Runtime &runtime, + Touch const &touch) { object.setProperty(runtime, "locationX", touch.offsetPoint.x); object.setProperty(runtime, "locationY", touch.offsetPoint.y); object.setProperty(runtime, "pageX", touch.pagePoint.x); @@ -24,7 +26,6 @@ static jsi::Value touchPayload(jsi::Runtime &runtime, Touch const &touch) { object.setProperty(runtime, "target", touch.target); object.setProperty(runtime, "timestamp", touch.timestamp * 1000); object.setProperty(runtime, "force", touch.force); - return object; } static jsi::Value touchesPayload( @@ -33,7 +34,9 @@ static jsi::Value touchesPayload( auto array = jsi::Array(runtime, touches.size()); int i = 0; for (auto const &touch : touches) { - array.setValueAtIndex(runtime, i++, touchPayload(runtime, touch)); + auto object = jsi::Object(runtime); + setTouchPayloadOnObject(object, runtime, touch); + array.setValueAtIndex(runtime, i++, object); } return array; } @@ -48,6 +51,11 @@ static jsi::Value touchEventPayload( runtime, "changedTouches", touchesPayload(runtime, event.changedTouches)); object.setProperty( runtime, "targetTouches", touchesPayload(runtime, event.targetTouches)); + + if (!event.changedTouches.empty()) { + auto const &firstChangedTouch = *event.changedTouches.begin(); + setTouchPayloadOnObject(object, runtime, firstChangedTouch); + } return object; } @@ -68,7 +76,9 @@ void TouchEventEmitter::onTouchStart(TouchEvent const &event) const { } void TouchEventEmitter::onTouchMove(TouchEvent const &event) const { - dispatchTouchEvent("touchMove", event, EventPriority::AsynchronousBatched); + dispatchUniqueEvent("touchMove", [event](jsi::Runtime &runtime) { + return touchEventPayload(runtime, event); + }); } void TouchEventEmitter::onTouchEnd(TouchEvent const &event) const { diff --git a/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h b/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h index fd078e656c89b1..4ec013c7fb5bdb 100644 --- a/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h +++ b/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h @@ -25,7 +25,15 @@ class ViewComponentDescriptor float animationProgress, const SharedProps &props, const SharedProps &newProps) const override { +#ifdef ANDROID + // On Android only, the merged props should have the same RawProps as the + // final props struct + SharedProps interpolatedPropsShared = + (newProps != nullptr ? cloneProps(newProps, newProps->rawProps) + : cloneProps(newProps, {})); +#else SharedProps interpolatedPropsShared = cloneProps(newProps, {}); +#endif interpolateViewProps( animationProgress, props, newProps, interpolatedPropsShared); diff --git a/ReactCommon/react/renderer/components/view/ViewEventEmitter.cpp b/ReactCommon/react/renderer/components/view/ViewEventEmitter.cpp index fe2a83f5f43d8d..04902b3bedfa8c 100644 --- a/ReactCommon/react/renderer/components/view/ViewEventEmitter.cpp +++ b/ReactCommon/react/renderer/components/view/ViewEventEmitter.cpp @@ -35,27 +35,84 @@ void ViewEventEmitter::onAccessibilityEscape() const { #pragma mark - Layout void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const { - // Due to State Reconciliation, `onLayout` can be called potentially many - // times with identical layoutMetrics. Ensure that the JS event is only - // dispatched when the value changes. + // A copy of a shared pointer (`layoutEventState_`) establishes shared + // ownership that will be captured by lambda. + auto layoutEventState = layoutEventState_; + + // Dispatched `frame` values to JavaScript thread are throttled here. + // Basic ideas: + // - Scheduling a lambda with some value that already was dispatched, does + // nothing. + // - If some lambda is already in flight, we don't schedule another; + // - When a lambda is being executed on the JavaScript thread, the *most + // recent* `frame` value is used (not the value that was current at the + // moment of scheduling the lambda). + // + // This implies the following caveats: + // - Some events can be skipped; + // - When values change rapidly, even events with different values + // can be skipped (only the very last will be delivered). + // - Ordering is preserved. + { - std::lock_guard guard(layoutMetricsMutex_); - if (lastLayoutMetrics_ == layoutMetrics) { + std::lock_guard guard(layoutEventState->mutex); + + // If a *particular* `frame` was already dispatched to the JavaScript side, + // no other work is required. + if (layoutEventState->frame == layoutMetrics.frame && + layoutEventState->wasDispatched) { return; } - lastLayoutMetrics_ = layoutMetrics; + + // If the *particular* `frame` was not already dispatched *or* + // some *other* `frame` was dispatched before, + // we need to schedule the dispatching. + layoutEventState->wasDispatched = false; + layoutEventState->frame = layoutMetrics.frame; + + // Something is already in flight, dispatching another event is not + // required. + if (layoutEventState->isDispatching) { + return; + } + + layoutEventState->isDispatching = true; } - dispatchEvent("layout", [frame = layoutMetrics.frame](jsi::Runtime &runtime) { - auto layout = jsi::Object(runtime); - layout.setProperty(runtime, "x", frame.origin.x); - layout.setProperty(runtime, "y", frame.origin.y); - layout.setProperty(runtime, "width", frame.size.width); - layout.setProperty(runtime, "height", frame.size.height); - auto payload = jsi::Object(runtime); - payload.setProperty(runtime, "layout", std::move(layout)); - return payload; - }); + dispatchEvent( + "layout", + [layoutEventState](jsi::Runtime &runtime) { + auto frame = Rect{}; + + { + std::lock_guard guard(layoutEventState->mutex); + + layoutEventState->isDispatching = false; + + // If some *particular* `frame` was already dispatched before, + // and since then there were no other new values of the `frame` + // observed, do nothing. + if (layoutEventState->wasDispatched) { + return jsi::Value::null(); + } + + frame = layoutEventState->frame; + + // If some *particular* `frame` was *not* already dispatched before, + // it's time to dispatch it and mark as dispatched. + layoutEventState->wasDispatched = true; + } + + auto layout = jsi::Object(runtime); + layout.setProperty(runtime, "x", frame.origin.x); + layout.setProperty(runtime, "y", frame.origin.y); + layout.setProperty(runtime, "width", frame.size.width); + layout.setProperty(runtime, "height", frame.size.height); + auto payload = jsi::Object(runtime); + payload.setProperty(runtime, "layout", std::move(layout)); + return jsi::Value(std::move(payload)); + }, + EventPriority::AsynchronousUnbatched); } } // namespace react diff --git a/ReactCommon/react/renderer/components/view/ViewEventEmitter.h b/ReactCommon/react/renderer/components/view/ViewEventEmitter.h index 0aa1f5e588eba2..1a4e17e84e5151 100644 --- a/ReactCommon/react/renderer/components/view/ViewEventEmitter.h +++ b/ReactCommon/react/renderer/components/view/ViewEventEmitter.h @@ -38,8 +38,35 @@ class ViewEventEmitter : public TouchEventEmitter { void onLayout(const LayoutMetrics &layoutMetrics) const; private: - mutable std::mutex layoutMetricsMutex_; - mutable LayoutMetrics lastLayoutMetrics_; + /* + * Contains the most recent `frame` and a `mutex` protecting access to it. + */ + struct LayoutEventState { + /* + * Protects an access to other fields of the struct. + */ + std::mutex mutex; + + /* + * Last dispatched `frame` value or value that's being dispatched right now. + */ + Rect frame{}; + + /* + * Indicates that the `frame` value was already dispatched (and dispatching + * of the *same* value is not needed). + */ + bool wasDispatched{false}; + + /* + * Indicates that some lambda is already being dispatching (and dispatching + * another one is not needed). + */ + bool isDispatching{false}; + }; + + mutable std::shared_ptr layoutEventState_{ + std::make_shared()}; }; } // namespace react diff --git a/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 124babc4c195a5..657169b5395ba7 100644 --- a/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -54,7 +54,8 @@ void ViewShadowNode::initialize() noexcept { bool formsView = isColorMeaningful(viewProps.backgroundColor) || isColorMeaningful(viewProps.foregroundColor) || - !(viewProps.yogaStyle.border() == YGStyle::Edges{}); + !(viewProps.yogaStyle.border() == YGStyle::Edges{}) || + !viewProps.testId.empty(); formsView = formsView || formsStackingContext; diff --git a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 11352bb9d23b66..fded6490063eb2 100644 --- a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -21,6 +20,8 @@ namespace facebook { namespace react { +thread_local LayoutContext threadLocalLayoutContext; + static void applyLayoutConstraints( YGStyle &yogaStyle, LayoutConstraints const &layoutConstraints) { @@ -57,6 +58,13 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( // This is not a default for `YGNode`. yogaNode_.setDirty(true); + if (getTraits().check(ShadowNodeTraits::Trait::MeasurableYogaNode)) { + assert(getTraits().check(ShadowNodeTraits::Trait::LeafYogaNode)); + + yogaNode_.setMeasureFunc( + YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector); + } + updateYogaProps(); updateYogaChildren(); @@ -72,14 +80,26 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( static_cast(sourceShadowNode) .yogaNode_, &initializeYogaConfig(yogaConfig_)) { + // Note, cloned `YGNode` instance (copied using copy-constructor) inherits + // dirty flag, measure function, and other properties being set originally in + // the `YogaLayoutableShadowNode` constructor above. + + assert( + static_cast(sourceShadowNode) + .yogaNode_.isDirty() == yogaNode_.isDirty() && + "Yoga node must inherit dirty flag."); + yogaNode_.setContext(this); yogaNode_.setOwner(nullptr); updateYogaChildrenOwnersIfNeeded(); - // Yoga node must inherit dirty flag. - assert( - static_cast(sourceShadowNode) - .yogaNode_.isDirty() == yogaNode_.isDirty()); + // This is the only legit place where we can dirty cloned Yoga node. + // If we do it later, ancestor nodes will not be able to observe this and + // dirty (and clone) themselves as a result. + if (getTraits().check(ShadowNodeTraits::Trait::DirtyYogaNode) || + getTraits().check(ShadowNodeTraits::Trait::MeasurableYogaNode)) { + yogaNode_.setDirty(true); + } if (fragment.props) { updateYogaProps(); @@ -332,7 +352,7 @@ void YogaLayoutableShadowNode::layoutTree( applyLayoutConstraints(yogaNode_.getStyle(), layoutConstraints); - ThreadStorage::getInstance().set(layoutContext); + threadLocalLayoutContext = layoutContext; if (layoutContext.swapLeftAndRightInRTL) { swapLeftAndRightInTree(*this); @@ -445,9 +465,10 @@ YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector( auto oldNode = static_cast(oldYogaNode->getContext()); - auto clonedNode = oldNode->clone({ShadowNodeFragment::propsPlaceholder(), - ShadowNodeFragment::childrenPlaceholder(), - oldNode->getState()}); + auto clonedNode = oldNode->clone( + {ShadowNodeFragment::propsPlaceholder(), + ShadowNodeFragment::childrenPlaceholder(), + oldNode->getState()}); parentNode->replaceChild(*oldNode, clonedNode, childIndex); return &static_cast(*clonedNode).yogaNode_; } @@ -465,8 +486,9 @@ YGSize YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector( static_cast(yogaNode->getContext()); auto minimumSize = Size{0, 0}; - auto maximumSize = Size{std::numeric_limits::infinity(), - std::numeric_limits::infinity()}; + auto maximumSize = Size{ + std::numeric_limits::infinity(), + std::numeric_limits::infinity()}; switch (widthMode) { case YGMeasureModeUndefined: @@ -492,13 +514,11 @@ YGSize YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector( break; } - auto layoutContext = ThreadStorage::getInstance().get(); - auto size = shadowNodeRawPtr->measureContent( - layoutContext.value_or(LayoutContext{}), {minimumSize, maximumSize}); + threadLocalLayoutContext, {minimumSize, maximumSize}); - return YGSize{yogaFloatFromFloat(size.width), - yogaFloatFromFloat(size.height)}; + return YGSize{ + yogaFloatFromFloat(size.width), yogaFloatFromFloat(size.height)}; } #ifdef RN_DEBUG_YOGA_LOGGER diff --git a/ReactCommon/react/renderer/components/view/conversions.h b/ReactCommon/react/renderer/components/view/conversions.h index 93eb658be343e3..5e91976209737d 100644 --- a/ReactCommon/react/renderer/components/view/conversions.h +++ b/ReactCommon/react/renderer/components/view/conversions.h @@ -117,11 +117,13 @@ inline better::optional optionalFloatFromYogaValue( inline LayoutMetrics layoutMetricsFromYogaNode(YGNode &yogaNode) { auto layoutMetrics = LayoutMetrics{}; - layoutMetrics.frame = - Rect{Point{floatFromYogaFloat(YGNodeLayoutGetLeft(&yogaNode)), - floatFromYogaFloat(YGNodeLayoutGetTop(&yogaNode))}, - Size{floatFromYogaFloat(YGNodeLayoutGetWidth(&yogaNode)), - floatFromYogaFloat(YGNodeLayoutGetHeight(&yogaNode))}}; + layoutMetrics.frame = Rect{ + Point{ + floatFromYogaFloat(YGNodeLayoutGetLeft(&yogaNode)), + floatFromYogaFloat(YGNodeLayoutGetTop(&yogaNode))}, + Size{ + floatFromYogaFloat(YGNodeLayoutGetWidth(&yogaNode)), + floatFromYogaFloat(YGNodeLayoutGetHeight(&yogaNode))}}; layoutMetrics.borderWidth = EdgeInsets{ floatFromYogaFloat(YGNodeLayoutGetBorder(&yogaNode, YGEdgeLeft)), diff --git a/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp b/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp index 0b99e92624286a..0c5adbdba7c379 100644 --- a/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp +++ b/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp @@ -208,9 +208,10 @@ TEST_F(YogaDirtyFlagTest, updatingStateForScrollViewMistNotDirtyYogaNode) { oldShadowNode.getFamily(), std::make_shared(state)); - return oldShadowNode.clone({ShadowNodeFragment::propsPlaceholder(), - ShadowNodeFragment::childrenPlaceholder(), - newState}); + return oldShadowNode.clone( + {ShadowNodeFragment::propsPlaceholder(), + ShadowNodeFragment::childrenPlaceholder(), + newState}); }); EXPECT_FALSE( diff --git a/ReactCommon/react/renderer/core/BatchedEventQueue.cpp b/ReactCommon/react/renderer/core/BatchedEventQueue.cpp index d8acdd6112b4c1..1c363a64c65d58 100644 --- a/ReactCommon/react/renderer/core/BatchedEventQueue.cpp +++ b/ReactCommon/react/renderer/core/BatchedEventQueue.cpp @@ -6,29 +6,45 @@ */ #include "BatchedEventQueue.h" -#include namespace facebook { namespace react { -void BatchedEventQueue::onEnqueue() const { - EventQueue::onEnqueue(); +BatchedEventQueue::BatchedEventQueue( + EventPipe eventPipe, + StatePipe statePipe, + std::unique_ptr eventBeat) + : EventQueue(eventPipe, statePipe, std::move(eventBeat)) {} +void BatchedEventQueue::onEnqueue() const { eventBeat_->request(); } -void BatchedEventQueue::enqueueUniqueEvent(const RawEvent &rawEvent) const { +void BatchedEventQueue::enqueueUniqueEvent(RawEvent const &rawEvent) const { { std::lock_guard lock(queueMutex_); - if (!eventQueue_.empty()) { - auto const position = eventQueue_.back(); - if (position.type == rawEvent.type && - position.eventTarget == rawEvent.eventTarget) { - eventQueue_.pop_back(); + + auto repeatedEvent = eventQueue_.rend(); + + for (auto it = eventQueue_.rbegin(); it != eventQueue_.rend(); ++it) { + if (it->type == rawEvent.type && + it->eventTarget == rawEvent.eventTarget) { + repeatedEvent = it; + break; + } else if (it->eventTarget == rawEvent.eventTarget) { + // It is necessary to maintain order of different event types + // for the same target. If the same target has event types A1, B1 + // in the event queue and event A2 occurs. A1 has to stay in the + // queue. + break; } } - eventQueue_.push_back(rawEvent); + if (repeatedEvent == eventQueue_.rend()) { + eventQueue_.push_back(rawEvent); + } else { + *repeatedEvent = std::move(rawEvent); + } } onEnqueue(); diff --git a/ReactCommon/react/renderer/core/BatchedEventQueue.h b/ReactCommon/react/renderer/core/BatchedEventQueue.h index 2acabd8600b746..827ef87886ef4a 100644 --- a/ReactCommon/react/renderer/core/BatchedEventQueue.h +++ b/ReactCommon/react/renderer/core/BatchedEventQueue.h @@ -18,13 +18,16 @@ namespace react { */ class BatchedEventQueue final : public EventQueue { public: - using EventQueue::EventQueue; + BatchedEventQueue( + EventPipe eventPipe, + StatePipe statePipe, + std::unique_ptr eventBeat); void onEnqueue() const override; /* - * Enqueues and (probably later) dispatch a given event. - * Deletes last RawEvent from the queu if it has the same type and target. + * Enqueues and (probably later) dispatches a given event. + * Deletes last RawEvent from the queue if it has the same type and target. * Can be called on any thread. */ void enqueueUniqueEvent(const RawEvent &rawEvent) const; diff --git a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 497cf561e3d8ca..18217e60e1e532 100644 --- a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -127,6 +127,14 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { const SharedProps &props, const SharedProps &newProps) const override { // By default, this does nothing. +#ifdef ANDROID + // On Android only, the merged props should have the same RawProps as the + // final props struct + if (newProps != nullptr) { + return cloneProps(newProps, newProps->rawProps); + } +#endif + return cloneProps(newProps, {}); }; diff --git a/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/ReactCommon/react/renderer/core/ConcreteShadowNode.h index e6b842f3c820b9..bafe8e23946120 100644 --- a/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include #include @@ -49,7 +48,6 @@ class ConcreteShadowNode : public BaseShadowNodeT { using SharedConcreteEventEmitter = std::shared_ptr; using SharedConcreteShadowNode = std::shared_ptr; using ConcreteState = ConcreteState; - using ConcreteStateTeller = ConcreteStateTeller; using ConcreteStateData = StateDataT; static ComponentName Name() { diff --git a/ReactCommon/react/renderer/core/ConcreteState.h b/ReactCommon/react/renderer/core/ConcreteState.h index c57a6518bc61e0..9ee3b21ec518c6 100644 --- a/ReactCommon/react/renderer/core/ConcreteState.h +++ b/ReactCommon/react/renderer/core/ConcreteState.h @@ -60,27 +60,24 @@ class ConcreteState : public State { */ void updateState( Data &&newData, - std::function failureCallback = nullptr, EventPriority priority = EventPriority::AsynchronousUnbatched) const { updateState( - [data = std::move(newData)](Data const &oldData) mutable -> Data && { - return std::move(data); + [data = std::move(newData)](Data const &oldData) mutable -> SharedData { + return std::make_shared(std::move(data)); }, - failureCallback, priority); } /* * Initiate a state update process with a given function (that transforms an - * old data value to a new one) and priority. The update function can be - * called from any thread any moment later. The function can be called only - * once or not called at all (in the case where the node was already unmounted - * and updating makes no sense). The state update operation might fail in case - * of conflict. + * old data value to a new one) and priority. The callback function can be + * called from any thread any moment later. + * In case of a conflict, the `callback` might be called several times until + * it succeeded. To cancel the state update operation, the callback needs to + * return `nullptr`. */ void updateState( - std::function callback, - std::function failureCallback = nullptr, + std::function callback, EventPriority priority = EventPriority::AsynchronousBatched) const { auto family = family_.lock(); @@ -91,13 +88,10 @@ class ConcreteState : public State { } auto stateUpdate = StateUpdate{ - family, - [=](StateData::Shared const &oldData) -> StateData::Shared { + family, [=](StateData::Shared const &oldData) -> StateData::Shared { assert(oldData); - return std::make_shared( - callback(*std::static_pointer_cast(oldData))); - }, - failureCallback}; + return callback(*std::static_pointer_cast(oldData)); + }}; family->dispatchRawState(std::move(stateUpdate), priority); } @@ -107,9 +101,8 @@ class ConcreteState : public State { return getData().getDynamic(); } - void updateState(folly::dynamic data, std::function failureCallback) - const override { - updateState(std::move(Data(getData(), data)), failureCallback); + void updateState(folly::dynamic data) const override { + updateState(std::move(Data(getData(), data))); } #endif }; diff --git a/ReactCommon/react/renderer/core/ConcreteStateTeller.h b/ReactCommon/react/renderer/core/ConcreteStateTeller.h deleted file mode 100644 index 2354ae0daaf7ee..00000000000000 --- a/ReactCommon/react/renderer/core/ConcreteStateTeller.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include - -namespace facebook { -namespace react { - -/* - * Wrapper for `ConreteState` class designed to make interactions with - * ConcreteState easier. - */ -template -class ConcreteStateTeller { - public: - using Data = typename ConcreteStateT::Data; - - /* - * Sets backing `ConcreteState` on which all the methods will be called. - * Can be called from any thread. - */ - void setConcreteState(State::Shared const &state) { - std::lock_guard lock(mutex_); - concreteState_ = std::static_pointer_cast(state); - } - - /* - * Removes reference to `ConcreteState` previously set in `setConcreteState`. - * Can be called from any thread. - */ - void invalidate() { - std::lock_guard lock(mutex_); - concreteState_ = nullptr; - } - - /* - * Returns data if state isn't nullptr. - * Can be called from any thread. - */ - better::optional getData() const { - std::lock_guard lock(mutex_); - if (concreteState_) { - return concreteState_->getData(); - } else { - return {}; - } - } - - /* - * Returns true if backing state isn't nullptr, false otherwise. - * Can be called from any thread. - */ - bool isValid() const { - std::lock_guard lock(mutex_); - return concreteState_ != nullptr; - } - - /* - * Initiate a state update process with given new data and priority. - * This is a simplified convenience version of the method that receives a - * function for cases where a new value of data does not depend on an old - * value. - */ - void updateState( - Data &&newData, - EventPriority priority = EventPriority::AsynchronousUnbatched) const { - updateState( - [data = std::move(newData)](Data const &oldData) -> Data { - return std::move(data); - }, - priority); - } - - /* - * Initiate a state update process with a given function (that transforms an - * old data value to a new one) and priority. The update function can be - * called from any thread any moment later. The function can be called only - * once or not called at all (in the case where the node was already unmounted - * and updating makes no sense). The state update operation might fail in case - * of conflict. - */ - void updateState( - std::function callback, - EventPriority priority = EventPriority::AsynchronousBatched) const { - std::shared_ptr concreteState; - { - std::lock_guard lock(mutex_); - if (!concreteState_) { - return; - } - concreteState = concreteState_; - } - - concreteState->updateState( - callback, - [=]() { - updateStateRetryIfNecesarry_(concreteState, callback, priority, 1); - }, - priority); - } - - private: - /* - * Protected by `mutex_`. - */ - std::shared_ptr concreteState_; - - /* - * Protects `concreteState_`. - */ - std::mutex mutable mutex_; - - void updateStateRetryIfNecesarry_( - std::shared_ptr concreteState, - std::function callback, - EventPriority priority, - int retryCount) const { - { - std::lock_guard lock(mutex_); - - if (concreteState != concreteState_) { - LOG(WARNING) << "ConcreteState_ changed while retrying"; - return; - } - } - - if (retryCount > 60) { - LOG(ERROR) << "Exceeded 60 retries"; - assert(false); - return; - } - - concreteState->updateState( - callback, - [=] { - updateStateRetryIfNecesarry_( - concreteState, callback, priority, retryCount + 1); - }, - priority); - } -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/core/Constants.cpp b/ReactCommon/react/renderer/core/Constants.cpp new file mode 100644 index 00000000000000..150473be2889b8 --- /dev/null +++ b/ReactCommon/react/renderer/core/Constants.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "Constants.h" + +namespace facebook { +namespace react { + +static bool isPropsForwardingEnabled = false; + +void Constants::setPropsForwardingEnabled(bool propsForwardingEnabled) { + isPropsForwardingEnabled = propsForwardingEnabled; +} + +bool Constants::getPropsForwardingEnabled() { + return isPropsForwardingEnabled; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/core/Constants.h b/ReactCommon/react/renderer/core/Constants.h new file mode 100644 index 00000000000000..795952902417df --- /dev/null +++ b/ReactCommon/react/renderer/core/Constants.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +namespace facebook { +namespace react { + +struct Constants { + /* + Flag controling props forwarding when shadow node is cloned on Android. + Has no effect on iOS. + */ + static void setPropsForwardingEnabled(bool propsForwardingEnabled); + static bool getPropsForwardingEnabled(); +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/core/EventQueue.cpp b/ReactCommon/react/renderer/core/EventQueue.cpp index 2861d7a14f05ec..639d29a4751729 100644 --- a/ReactCommon/react/renderer/core/EventQueue.cpp +++ b/ReactCommon/react/renderer/core/EventQueue.cpp @@ -8,6 +8,7 @@ #include "EventQueue.h" #include "EventEmitter.h" +#include "ShadowNodeFamily.h" namespace facebook { namespace react { @@ -35,16 +36,18 @@ void EventQueue::enqueueEvent(const RawEvent &rawEvent) const { void EventQueue::enqueueStateUpdate(const StateUpdate &stateUpdate) const { { std::lock_guard lock(queueMutex_); + if (!stateUpdateQueue_.empty()) { + auto const position = stateUpdateQueue_.back(); + if (stateUpdate.family == position.family) { + stateUpdateQueue_.pop_back(); + } + } stateUpdateQueue_.push_back(stateUpdate); } onEnqueue(); } -void EventQueue::onEnqueue() const { - // Default implementation does nothing. -} - void EventQueue::onBeat(jsi::Runtime &runtime) const { flushEvents(runtime); flushStateUpdates(); diff --git a/ReactCommon/react/renderer/core/EventQueue.h b/ReactCommon/react/renderer/core/EventQueue.h index ab6bac9ac3bbf2..ed77cad3f6157d 100644 --- a/ReactCommon/react/renderer/core/EventQueue.h +++ b/ReactCommon/react/renderer/core/EventQueue.h @@ -51,7 +51,7 @@ class EventQueue { * Override in subclasses to trigger beat `request` and/or beat `induce`. * Default implementation does nothing. */ - virtual void onEnqueue() const; + virtual void onEnqueue() const = 0; void onBeat(jsi::Runtime &runtime) const; void flushEvents(jsi::Runtime &runtime) const; diff --git a/ReactCommon/react/renderer/core/EventTarget.cpp b/ReactCommon/react/renderer/core/EventTarget.cpp index c9f418c2d88fa6..01a5a77bd50f48 100644 --- a/ReactCommon/react/renderer/core/EventTarget.cpp +++ b/ReactCommon/react/renderer/core/EventTarget.cpp @@ -14,7 +14,7 @@ using Tag = EventTarget::Tag; EventTarget::EventTarget( jsi::Runtime &runtime, - const jsi::Value &instanceHandle, + jsi::Value const &instanceHandle, Tag tag) : weakInstanceHandle_( jsi::WeakObject(runtime, instanceHandle.asObject(runtime))), diff --git a/ReactCommon/react/renderer/core/EventTarget.h b/ReactCommon/react/renderer/core/EventTarget.h index 8bd7a03a1995ac..92f382a96c4965 100644 --- a/ReactCommon/react/renderer/core/EventTarget.h +++ b/ReactCommon/react/renderer/core/EventTarget.h @@ -35,7 +35,7 @@ class EventTarget { /* * Constructs an EventTarget from a weak instance handler and a tag. */ - EventTarget(jsi::Runtime &runtime, const jsi::Value &instanceHandle, Tag tag); + EventTarget(jsi::Runtime &runtime, jsi::Value const &instanceHandle, Tag tag); /* * Sets the `enabled` flag that allows creating a strong instance handle from diff --git a/ReactCommon/react/renderer/core/LayoutConstraints.h b/ReactCommon/react/renderer/core/LayoutConstraints.h index 5f838b5e4f2bab..cb166c81da8bfb 100644 --- a/ReactCommon/react/renderer/core/LayoutConstraints.h +++ b/ReactCommon/react/renderer/core/LayoutConstraints.h @@ -21,8 +21,9 @@ namespace react { */ struct LayoutConstraints { Size minimumSize{0, 0}; - Size maximumSize{std::numeric_limits::infinity(), - std::numeric_limits::infinity()}; + Size maximumSize{ + std::numeric_limits::infinity(), + std::numeric_limits::infinity()}; LayoutDirection layoutDirection{LayoutDirection::Undefined}; /* diff --git a/ReactCommon/react/renderer/core/LayoutContext.h b/ReactCommon/react/renderer/core/LayoutContext.h index be8353a46fb060..dcd441028eb51e 100644 --- a/ReactCommon/react/renderer/core/LayoutContext.h +++ b/ReactCommon/react/renderer/core/LayoutContext.h @@ -63,5 +63,24 @@ struct LayoutContext { Point viewportOffset{}; }; +inline bool operator==(LayoutContext const &lhs, LayoutContext const &rhs) { + return std::tie( + lhs.pointScaleFactor, + lhs.affectedNodes, + lhs.swapLeftAndRightInRTL, + lhs.fontSizeMultiplier, + lhs.viewportOffset) == + std::tie( + rhs.pointScaleFactor, + rhs.affectedNodes, + rhs.swapLeftAndRightInRTL, + rhs.fontSizeMultiplier, + rhs.viewportOffset); +} + +inline bool operator!=(LayoutContext const &lhs, LayoutContext const &rhs) { + return !(lhs == rhs); +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/core/LayoutMetrics.h b/ReactCommon/react/renderer/core/LayoutMetrics.h index 603a56beab867e..88611dabb67251 100644 --- a/ReactCommon/react/renderer/core/LayoutMetrics.h +++ b/ReactCommon/react/renderer/core/LayoutMetrics.h @@ -28,8 +28,9 @@ struct LayoutMetrics { Rect getContentFrame() const { return Rect{ Point{contentInsets.left, contentInsets.top}, - Size{frame.size.width - contentInsets.left - contentInsets.right, - frame.size.height - contentInsets.top - contentInsets.bottom}}; + Size{ + frame.size.width - contentInsets.left - contentInsets.right, + frame.size.height - contentInsets.top - contentInsets.bottom}}; } bool operator==(const LayoutMetrics &rhs) const { diff --git a/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp b/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp index 51b29867787525..1b49fd9eb3627d 100644 --- a/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp +++ b/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp @@ -159,13 +159,6 @@ Point LayoutableShadowNode::getContentOriginOffset() const { return {0, 0}; } -LayoutMetrics LayoutableShadowNode::getRelativeLayoutMetrics( - LayoutableShadowNode const &ancestorLayoutableShadowNode, - LayoutInspectingPolicy policy) const { - return computeRelativeLayoutMetrics( - getFamily(), ancestorLayoutableShadowNode, policy); -} - LayoutableShadowNode::UnsharedList LayoutableShadowNode::getLayoutableChildNodes() const { LayoutableShadowNode::UnsharedList layoutableChildren; @@ -238,7 +231,17 @@ ShadowNode::Shared LayoutableShadowNode::findNodeAtPoint( auto newPoint = point - transformedFrame.origin - layoutableShadowNode->getContentOriginOffset(); - for (const auto &childShadowNode : node->getChildren()) { + + auto sortedChildren = node->getChildren(); + std::stable_sort( + sortedChildren.begin(), + sortedChildren.end(), + [](auto const &lhs, auto const &rhs) -> bool { + return lhs->getOrderIndex() < rhs->getOrderIndex(); + }); + + for (auto it = sortedChildren.rbegin(); it != sortedChildren.rend(); it++) { + auto const &childShadowNode = *it; auto hitView = findNodeAtPoint(childShadowNode, newPoint); if (hitView) { return hitView; diff --git a/ReactCommon/react/renderer/core/LayoutableShadowNode.h b/ReactCommon/react/renderer/core/LayoutableShadowNode.h index 83ad3273a1397b..b30f1d2124213a 100644 --- a/ReactCommon/react/renderer/core/LayoutableShadowNode.h +++ b/ReactCommon/react/renderer/core/LayoutableShadowNode.h @@ -122,21 +122,6 @@ class LayoutableShadowNode : public ShadowNode { */ virtual Point getContentOriginOffset() const; - /* - * Returns layout metrics relatively to the given ancestor node. - * Uses `computeRelativeLayoutMetrics()` under the hood. - */ - LayoutMetrics getRelativeLayoutMetrics( - ShadowNodeFamily const &descendantNodeFamily, - LayoutInspectingPolicy policy) const; - - /* - * Returns layout metrics relatively to the given ancestor node. - */ - LayoutMetrics getRelativeLayoutMetrics( - LayoutableShadowNode const &ancestorLayoutableShadowNode, - LayoutInspectingPolicy policy) const; - /* * Sets layout metrics for the shadow node. */ diff --git a/ReactCommon/react/renderer/core/RawPropsKey.cpp b/ReactCommon/react/renderer/core/RawPropsKey.cpp index 505eca510eb64f..2bc87ea6a43612 100644 --- a/ReactCommon/react/renderer/core/RawPropsKey.cpp +++ b/ReactCommon/react/renderer/core/RawPropsKey.cpp @@ -15,8 +15,8 @@ namespace facebook { namespace react { -void RawPropsKey::render(char *buffer, RawPropsPropNameLength *length) const - noexcept { +void RawPropsKey::render(char *buffer, RawPropsPropNameLength *length) + const noexcept { *length = 0; // Prefix diff --git a/ReactCommon/react/renderer/core/RawPropsParser.h b/ReactCommon/react/renderer/core/RawPropsParser.h index 4dc557b708f9f4..ff1a73b4c16a9d 100644 --- a/ReactCommon/react/renderer/core/RawPropsParser.h +++ b/ReactCommon/react/renderer/core/RawPropsParser.h @@ -64,8 +64,8 @@ class RawPropsParser final { /* * To be used by `RawProps` only. */ - RawValue const *at(RawProps const &rawProps, RawPropsKey const &key) const - noexcept; + RawValue const *at(RawProps const &rawProps, RawPropsKey const &key) + const noexcept; mutable better::small_vector keys_{}; diff --git a/ReactCommon/react/renderer/core/ShadowNode.cpp b/ReactCommon/react/renderer/core/ShadowNode.cpp index a5839fc820d80b..3fb034f3b2204b 100644 --- a/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -6,6 +6,7 @@ */ #include "ShadowNode.h" +#include "Constants.h" #include "ShadowNodeFragment.h" #include @@ -24,6 +25,33 @@ SharedShadowNodeSharedList ShadowNode::emptySharedShadowNodeSharedList() { return emptySharedShadowNodeSharedList; } +/* + * On iOS, this method returns `props` if provided, `sourceShadowNode`'s props + * otherwise. On Android, we forward props in case `sourceShadowNode` hasn't + * been mounted. `Props::rawProps` are merged from `props` to a copy of + * `sourceShadowNode.props_` and returned. This is necessary to enable + * Background Executor and should be removed once reimplementation of JNI layer + * is finished. + */ +SharedProps ShadowNode::propsForClonedShadowNode( + ShadowNode const &sourceShadowNode, + Props::Shared const &props) { +#ifdef ANDROID + if (Constants::getPropsForwardingEnabled()) { + bool hasBeenMounted = sourceShadowNode.hasBeenMounted_; + bool sourceNodeHasRawProps = !sourceShadowNode.getProps()->rawProps.empty(); + if (!hasBeenMounted && sourceNodeHasRawProps && props) { + auto copiedProps = sourceShadowNode.getProps()->rawProps; + copiedProps.merge_patch(props->rawProps); + auto &castedProps = const_cast(*props); + castedProps.rawProps = copiedProps; + return props; + } + } +#endif + return props ? props : sourceShadowNode.getProps(); +} + bool ShadowNode::sameFamily(const ShadowNode &first, const ShadowNode &second) { return first.family_ == second.family_; } @@ -60,13 +88,13 @@ ShadowNode::ShadowNode( } ShadowNode::ShadowNode( - const ShadowNode &sourceShadowNode, - const ShadowNodeFragment &fragment) + ShadowNode const &sourceShadowNode, + ShadowNodeFragment const &fragment) : #if RN_DEBUG_STRING_CONVERTIBLE revision_(sourceShadowNode.revision_ + 1), #endif - props_(fragment.props ? fragment.props : sourceShadowNode.props_), + props_(propsForClonedShadowNode(sourceShadowNode, fragment.props)), children_( fragment.children ? fragment.children : sourceShadowNode.children_), state_( @@ -214,6 +242,7 @@ void ShadowNode::cloneChildrenIfShared() { void ShadowNode::setMounted(bool mounted) const { if (mounted) { family_->setMostRecentState(getState()); + hasBeenMounted_ = mounted; } family_->eventEmitter_->setEnabled(mounted); diff --git a/ReactCommon/react/renderer/core/ShadowNode.h b/ReactCommon/react/renderer/core/ShadowNode.h index 30f5774b7d5f2f..7c385ab7f2b927 100644 --- a/ReactCommon/react/renderer/core/ShadowNode.h +++ b/ReactCommon/react/renderer/core/ShadowNode.h @@ -176,8 +176,6 @@ class ShadowNode : public Sealable, public DebugStringConvertible { */ void setMounted(bool mounted) const; - int getStateRevision() const; - #pragma mark - DebugStringConvertible #if RN_DEBUG_STRING_CONVERTIBLE @@ -214,6 +212,12 @@ class ShadowNode : public Sealable, public DebugStringConvertible { */ ShadowNodeFamily::Shared family_; + mutable std::atomic hasBeenMounted_{false}; + + static SharedProps propsForClonedShadowNode( + ShadowNode const &sourceShadowNode, + Props::Shared const &props); + protected: /* * Traits associated with the particular `ShadowNode` class and an instance of diff --git a/ReactCommon/react/renderer/core/ShadowNodeTraits.h b/ReactCommon/react/renderer/core/ShadowNodeTraits.h index 16b7129bd00c71..0ae4ba1a02b47c 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeTraits.h +++ b/ReactCommon/react/renderer/core/ShadowNodeTraits.h @@ -54,16 +54,25 @@ class ShadowNodeTraits { // Nodes with this trait (and all their descendants) will not produce views. Hidden = 1 << 6, + // Indicates that the `YogaLayoutableShadowNode` must set `isDirty` flag for + // Yoga node when a `ShadowNode` is being cloned. `ShadowNode`s that modify + // Yoga styles in the constructor (or later) *after* the `ShadowNode` + // is cloned must set this trait. + // Any Yoga node (not only Leaf ones) can have this trait. + DirtyYogaNode = 1 << 9, + // Inherits `YogaLayoutableShadowNode` and enforces that the `YGNode` is a // leaf. LeafYogaNode = 1 << 10, - // Inherits `LayoutableShadowNode` and calls `measure()`. - HasMeasure = 1 << 11, + // Inherits `YogaLayoutableShadowNode` and has a custom measure function. + // Only Leaf nodes can have this trait. + MeasurableYogaNode = 1 << 11, - // Indicates that the `ShadowNode` must form a stacking context (a level - // of the hierarchy; `ShadowView`s formed by descendants the node will be - // descendants of a `ShadowView` formed by the node). + // Indicates that the `ShadowNode` must form a stacking context. + // A Stacking Context forms a level of a `ShadowView` hierarchy (in contrast + // with a level of a `ShadowNode` hierarchy). + // See W3C standard for more details: https://www.w3.org/TR/CSS2/zindex.html FormsStackingContext = 1 << 13, // Indicates that the node must form a `ShadowView`. diff --git a/ReactCommon/react/renderer/core/State.h b/ReactCommon/react/renderer/core/State.h index ae636f37e421cd..c0472fec057bf5 100644 --- a/ReactCommon/react/renderer/core/State.h +++ b/ReactCommon/react/renderer/core/State.h @@ -65,9 +65,7 @@ class State { #ifdef ANDROID virtual folly::dynamic getDynamic() const = 0; - virtual void updateState( - folly::dynamic data, - std::function failureCallback) const = 0; + virtual void updateState(folly::dynamic data) const = 0; #endif protected: diff --git a/ReactCommon/react/renderer/core/StateUpdate.h b/ReactCommon/react/renderer/core/StateUpdate.h index a77abb90dc6d5d..890e56d141092b 100644 --- a/ReactCommon/react/renderer/core/StateUpdate.h +++ b/ReactCommon/react/renderer/core/StateUpdate.h @@ -25,7 +25,6 @@ class StateUpdate { SharedShadowNodeFamily family; Callback callback; - FailureCallback failureCallback; }; } // namespace react diff --git a/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp b/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp index 4de0e8c747d85a..98210411f7482d 100644 --- a/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp +++ b/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp @@ -11,8 +11,6 @@ namespace facebook { namespace react { void UnbatchedEventQueue::onEnqueue() const { - EventQueue::onEnqueue(); - eventBeat_->request(); eventBeat_->induce(); } diff --git a/ReactCommon/react/renderer/core/conversions.h b/ReactCommon/react/renderer/core/conversions.h index 9dc3daa994fa89..70dda9a9f5589c 100644 --- a/ReactCommon/react/renderer/core/conversions.h +++ b/ReactCommon/react/renderer/core/conversions.h @@ -34,6 +34,17 @@ inline int toInt(const LayoutDirection &layoutDirection) { } } +inline int toInt(const DisplayType &displayType) { + switch (displayType) { + case DisplayType::None: + return 0; + case DisplayType::Flex: + return 1; + case DisplayType::Inline: + return 2; + } +} + inline std::string toString(const DisplayType &displayType) { switch (displayType) { case DisplayType::None: diff --git a/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp b/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp index 79787b4bf9bfef..37f1c4106db603 100644 --- a/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp +++ b/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp @@ -6,134 +6,224 @@ */ #include +#include +#include + #include "TestComponent.h" using namespace facebook::react; -/* - *┌─────────────────────────┐ - *│nodeA_ │ - *│ │ - *│ │ - *│ │ - *│ │ - *│ │ - *│ │ - *│ ┌────────────────┐ │ - *│ │nodeAA_ │ │ - *│ │ │ │ - *│ │ ┌───────┐ │ │ - *│ │ │nodeAA_│ │ │ - *│ │ │ │ │ │ - *│ │ └───────┘ │ │ - *│ └────────────────┘ │ - *└─────────────────────────┘ - */ -class FindNodeAtPointTest : public ::testing::Test { - protected: - FindNodeAtPointTest() - : eventDispatcher_(std::shared_ptr()), - componentDescriptor_(TestComponentDescriptor({eventDispatcher_})) { - auto traits = TestShadowNode::BaseTraits(); - - auto familyA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 9, - /* .surfaceId = */ 1, - /* .eventEmitter = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); - - nodeA_ = std::make_shared( - ShadowNodeFragment{ - /* .props = */ std::make_shared(), - /* .children = */ ShadowNode::emptySharedShadowNodeSharedList(), - }, - familyA, - traits); - - auto familyAA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 10, - /* .surfaceId = */ 1, - /* .eventEmitter = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); - - nodeAA_ = std::make_shared( - ShadowNodeFragment{ - /* .props = */ std::make_shared(), - /* .children = */ ShadowNode::emptySharedShadowNodeSharedList(), - }, - familyAA, - traits); - - auto familyAAA = std::make_shared( - ShadowNodeFamilyFragment{ - /* .tag = */ 11, - /* .surfaceId = */ 1, - /* .eventEmitter = */ nullptr, - }, - eventDispatcher_, - componentDescriptor_); - - nodeAAA_ = std::make_shared( - ShadowNodeFragment{ - /* .props = */ std::make_shared(), - /* .children = */ ShadowNode::emptySharedShadowNodeSharedList(), - }, - familyAAA, - traits); - - nodeA_->appendChild(nodeAA_); - nodeAA_->appendChild(nodeAAA_); - - auto layoutMetrics = EmptyLayoutMetrics; - - layoutMetrics.frame = facebook::react::Rect{ - facebook::react::Point{0, 0}, facebook::react::Size{1000, 1000}}; - nodeA_->setLayoutMetrics(layoutMetrics); - - layoutMetrics.frame = facebook::react::Rect{ - facebook::react::Point{100, 100}, facebook::react::Size{100, 100}}; - nodeAA_->setLayoutMetrics(layoutMetrics); - - layoutMetrics.frame = facebook::react::Rect{facebook::react::Point{10, 10}, - facebook::react::Size{10, 10}}; - nodeAAA_->setLayoutMetrics(layoutMetrics); - } - - std::shared_ptr eventDispatcher_; - std::shared_ptr nodeA_; - std::shared_ptr nodeAA_; - std::shared_ptr nodeAAA_; - TestComponentDescriptor componentDescriptor_; -}; - -TEST_F(FindNodeAtPointTest, withoutTransform) { +TEST(FindNodeAtPointTest, withoutTransform) { + auto builder = simpleComponentBuilder(); + + // clang-format off + auto element = + Element() + .tag(1) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.size = {1000, 1000}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(2) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {100, 100}; + layoutMetrics.frame.size = {100, 100}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(3) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {10, 10}; + layoutMetrics.frame.size = {10, 10}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + }) + }); + + auto parentShadowNode = builder.build(element); + EXPECT_EQ( - LayoutableShadowNode::findNodeAtPoint(nodeA_, {115, 115}), nodeAAA_); - EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(nodeA_, {105, 105}), nodeAA_); - EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(nodeA_, {900, 900}), nodeA_); + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {115, 115})->getTag(), 3); + EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {105, 105})->getTag(), 2); + EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {900, 900})->getTag(), 1); EXPECT_EQ( - LayoutableShadowNode::findNodeAtPoint(nodeA_, {1001, 1001}), nullptr); + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {1001, 1001}), nullptr); } -TEST_F(FindNodeAtPointTest, viewIsTranslated) { - nodeA_->_contentOriginOffset = {-100, -100}; +TEST(FindNodeAtPointTest, viewIsTranslated) { + auto builder = simpleComponentBuilder(); + + // clang-format off + auto element = + Element() + .tag(1) + .finalize([](ScrollViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.size = {1000, 1000}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .stateData([](ScrollViewState &data) { + data.contentOffset = {100, 100}; + }) + .children({ + Element() + .tag(2) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {100, 100}; + layoutMetrics.frame.size = {100, 100}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(3) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {10, 10}; + layoutMetrics.frame.size = {10, 10}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + }) + }); + + auto parentShadowNode = builder.build(element); EXPECT_EQ( - LayoutableShadowNode::findNodeAtPoint(nodeA_, {15, 15})->getTag(), - nodeAAA_->getTag()); - EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(nodeA_, {5, 5}), nodeAA_); + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {15, 15})->getTag(), + 3); + EXPECT_EQ(LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {5, 5})->getTag(), 2); } -TEST_F(FindNodeAtPointTest, viewIsScaled) { - nodeAAA_->_transform = Transform::Identity() * Transform::Scale(0.5, 0.5, 0); +TEST(FindNodeAtPointTest, viewIsScaled) { + auto builder = simpleComponentBuilder(); + + // clang-format off + auto element = + Element() + .tag(1) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.size = {1000, 1000}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(2) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {100, 100}; + layoutMetrics.frame.size = {100, 100}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(3) + .props([] { + auto sharedProps = std::make_shared(); + sharedProps->transform = Transform::Scale(0.5, 0.5, 0); + return sharedProps; + }) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {10, 10}; + layoutMetrics.frame.size = {10, 10}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + }) + }); + + auto parentShadowNode = builder.build(element); + + EXPECT_EQ( + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {119, 119})->getTag(), + 2); +} +TEST(FindNodeAtPointTest, overlappingViews) { + auto builder = simpleComponentBuilder(); + + // clang-format off + auto element = + Element() + .tag(1) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.size = {100, 100}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(2) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {25, 25}; + layoutMetrics.frame.size = {50, 50}; + shadowNode.setLayoutMetrics(layoutMetrics); + }), + Element() + .tag(3) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {50, 50}; + layoutMetrics.frame.size = {50, 50}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + }); + + auto parentShadowNode = builder.build(element); + EXPECT_EQ( - LayoutableShadowNode::findNodeAtPoint(nodeA_, {119, 119})->getTag(), - nodeAA_->getTag()); + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 3); } + +TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) { + auto builder = simpleComponentBuilder(); + + // clang-format off + auto element = + Element() + .tag(1) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.size = {100, 100}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + .children({ + Element() + .tag(2) + .props([] { + auto sharedProps = std::make_shared(); + sharedProps->zIndex = 1; + auto &yogaStyle = sharedProps->yogaStyle; + yogaStyle.positionType() = YGPositionTypeAbsolute; + return sharedProps; + }) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {25, 25}; + layoutMetrics.frame.size = {50, 50}; + shadowNode.setLayoutMetrics(layoutMetrics); + }), + Element() + .tag(3) + .finalize([](ViewShadowNode &shadowNode){ + auto layoutMetrics = EmptyLayoutMetrics; + layoutMetrics.frame.origin = {50, 50}; + layoutMetrics.frame.size = {50, 50}; + shadowNode.setLayoutMetrics(layoutMetrics); + }) + }); + + auto parentShadowNode = builder.build(element); + + EXPECT_EQ( + LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50})->getTag(), 2); +} + + diff --git a/ReactCommon/react/renderer/core/tests/FollyDynamicMergePatchTest.cpp b/ReactCommon/react/renderer/core/tests/FollyDynamicMergePatchTest.cpp new file mode 100644 index 00000000000000..0362d6e01743c4 --- /dev/null +++ b/ReactCommon/react/renderer/core/tests/FollyDynamicMergePatchTest.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include +#include +#include + +using namespace folly; + +/* + Tests that verify expected behaviour from `folly::dynamic::merge_patch`. + `merge_patch` is used for props forwarding on Android to enable Background + Executor and will be removed once JNI layer is reimplmeneted. + */ +TEST(FollyDynamicMergePatchTest, handleNestedObjects) { + dynamic map1 = dynamic::object; + map1["style"] = dynamic::object("backgroundColor", "red"); + + dynamic map2 = dynamic::object; + map2["style"] = dynamic::object("backgroundColor", "blue")("color", "black"); + map2["height"] = 100; + + map2.merge_patch(map1); + + EXPECT_TRUE(map2["style"].isObject()); + EXPECT_TRUE(map2["style"]["backgroundColor"].isString()); + EXPECT_TRUE(map2["style"]["color"].isString()); + EXPECT_TRUE(map2["height"].isInt()); + + EXPECT_EQ(map2["style"]["backgroundColor"], "red"); + EXPECT_EQ(map2["style"]["color"], "black"); + EXPECT_EQ(map2["height"], 100); +} + +TEST(FollyDynamicMergePatchTest, handleEmptyObject) { + dynamic map1 = dynamic::object; + + dynamic map2 = dynamic::object; + map2["height"] = 100; + + map2.merge_patch(map1); + + EXPECT_TRUE(map2["height"].isInt()); + EXPECT_EQ(map2["height"], 100); + + map1.merge_patch(map2); + + EXPECT_TRUE(map1["height"].isInt()); + EXPECT_EQ(map1["height"], 100); +} diff --git a/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp b/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp index 8e02861ae79c97..c6dc5f68b5bfac 100644 --- a/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp +++ b/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp @@ -52,7 +52,8 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetrics) { auto parentShadowNode = builder.build(element); auto relativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {}); // A is a parent to B, A has origin {10, 10}, B has origin {10, 10}. // B's relative origin to A should be {10, 10}. @@ -104,13 +105,14 @@ TEST(LayoutableShadowNodeTest, contentOriginOffset) { auto parentShadowNode = builder.build(element); auto relativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 0); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 10); - relativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {false}); + relativeLayoutMetrics = LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {false}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 10); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 20); @@ -157,7 +159,8 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedNode) { auto parentShadowNode = builder.build(element); auto relativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 35); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 70); @@ -222,7 +225,8 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedParent) { auto parentShadowNode = builder.build(element); auto relativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 45); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 45); @@ -254,7 +258,8 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnSameNode) { auto shadowNode = builder.build(element); auto relativeLayoutMetrics = - shadowNode->getRelativeLayoutMetrics(*shadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + shadowNode->getFamily(), *shadowNode, {}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 0); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 0); @@ -290,7 +295,8 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnSameTransformedNode) { auto shadowNode = builder.build(element); auto relativeLayoutMetrics = - shadowNode->getRelativeLayoutMetrics(*shadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + shadowNode->getFamily(), *shadowNode, {}); EXPECT_EQ(relativeLayoutMetrics.frame.origin.x, 0); EXPECT_EQ(relativeLayoutMetrics.frame.origin.y, 0); @@ -332,7 +338,8 @@ TEST(LayoutableShadowNodeTest, relativeLayourMetricsOnClonedNode) { parentShadowNode->replaceChild(*childShadowNode, clonedChildShadowNode); auto newRelativeLayoutMetrics = - childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + LayoutableShadowNode::computeRelativeLayoutMetrics( + childShadowNode->getFamily(), *parentShadowNode, {}); EXPECT_EQ(newRelativeLayoutMetrics.frame.size.width, 50); EXPECT_EQ(newRelativeLayoutMetrics.frame.size.height, 60); } @@ -379,7 +386,7 @@ TEST( auto parentShadowNode = builder.build(element); - auto relativeLayoutMetrics = childShadowNode->getRelativeLayoutMetrics(*parentShadowNode, {}); + auto relativeLayoutMetrics = LayoutableShadowNode::computeRelativeLayoutMetrics(childShadowNode->getFamily(), *parentShadowNode, {}); // relativeLayoutMetrics do not include offsset of nodeAA_ because it is a // RootKindNode. @@ -410,13 +417,15 @@ TEST(LayoutableShadowNodeTest, includeViewportOffset) { // `includeViewportOffset` has to work with `includeTransform` enabled and // disabled. - auto layoutMetrics = viewShadowNode->getRelativeLayoutMetrics( + auto layoutMetrics = LayoutableShadowNode::computeRelativeLayoutMetrics( + viewShadowNode->getFamily(), *rootShadowNode, {/* includeTransform = */ false, /* includeViewportOffset = */ true}); EXPECT_EQ(layoutMetrics.frame.origin.x, 10); EXPECT_EQ(layoutMetrics.frame.origin.y, 20); - layoutMetrics = viewShadowNode->getRelativeLayoutMetrics( + layoutMetrics = LayoutableShadowNode::computeRelativeLayoutMetrics( + viewShadowNode->getFamily(), *rootShadowNode, {/* includeTransform = */ true, /* includeViewportOffset = */ true}); EXPECT_EQ(layoutMetrics.frame.origin.x, 10); diff --git a/ReactCommon/react/renderer/core/tests/TestComponent.h b/ReactCommon/react/renderer/core/tests/TestComponent.h index 936fe0167cbe0a..9943d78a031b49 100644 --- a/ReactCommon/react/renderer/core/tests/TestComponent.h +++ b/ReactCommon/react/renderer/core/tests/TestComponent.h @@ -33,7 +33,7 @@ static const char TestComponentName[] = "Test"; class TestProps : public ViewProps { public: - using ViewProps::ViewProps; + TestProps() = default; TestProps(const TestProps &sourceProps, const RawProps &rawProps) : ViewProps(sourceProps, rawProps) {} diff --git a/ReactCommon/react/renderer/debug/SystraceSection.h b/ReactCommon/react/renderer/debug/SystraceSection.h index a21cd36b2b7263..603c823b4e5132 100644 --- a/ReactCommon/react/renderer/debug/SystraceSection.h +++ b/ReactCommon/react/renderer/debug/SystraceSection.h @@ -29,7 +29,7 @@ struct ConcreteSystraceSection { template explicit ConcreteSystraceSection( const char *name, - ConvertsToStringPiece &&... args) + ConvertsToStringPiece &&...args) : m_section(TRACE_TAG_REACT_CXX_BRIDGE, name, args...) {} private: @@ -42,7 +42,7 @@ struct DummySystraceSection { template explicit DummySystraceSection( const char *name, - ConvertsToStringPiece &&... args) {} + ConvertsToStringPiece &&...args) {} }; using SystraceSection = DummySystraceSection; #endif diff --git a/ReactCommon/react/renderer/element/ComponentBuilder.cpp b/ReactCommon/react/renderer/element/ComponentBuilder.cpp index 242b8d854e6623..c1438bb63aafd8 100644 --- a/ReactCommon/react/renderer/element/ComponentBuilder.cpp +++ b/ReactCommon/react/renderer/element/ComponentBuilder.cpp @@ -45,9 +45,10 @@ ShadowNode::Unshared ComponentBuilder::build( *family, elementFragment.stateCallback()); constShadowNode = componentDescriptor.cloneShadowNode( *constShadowNode, - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - ShadowNodeFragment::childrenPlaceholder(), - newState}); + ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + ShadowNodeFragment::childrenPlaceholder(), + newState}); } auto shadowNode = std::const_pointer_cast(constShadowNode); diff --git a/ReactCommon/react/renderer/element/Element.h b/ReactCommon/react/renderer/element/Element.h index 44ff785ccdb917..b6e36a789effd4 100644 --- a/ReactCommon/react/renderer/element/Element.h +++ b/ReactCommon/react/renderer/element/Element.h @@ -93,7 +93,8 @@ class Element final { * Sets `state` using callback. */ Element &stateData(std::function callback) { - fragment_.stateCallback = [&]() -> StateData::Shared { + fragment_.stateCallback = [callback = + std::move(callback)]() -> StateData::Shared { auto stateData = ConcreteStateData(); callback(stateData); return std::make_shared(stateData); diff --git a/ReactCommon/react/renderer/graphics/BUCK b/ReactCommon/react/renderer/graphics/BUCK index 9b7fd05c2d0b46..87064ce89c0436 100644 --- a/ReactCommon/react/renderer/graphics/BUCK +++ b/ReactCommon/react/renderer/graphics/BUCK @@ -7,6 +7,7 @@ load( "fb_xplat_cxx_test", "get_apple_compiler_flags", "get_apple_inspector_flags", + "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob", ) @@ -95,6 +96,7 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + react_native_xplat_target("better:better"), "//third-party/glog:glog", "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", diff --git a/ReactCommon/react/renderer/graphics/React-graphics.podspec b/ReactCommon/react/renderer/graphics/React-graphics.podspec index 30bffb22f09d7b..be4b996c41bd65 100644 --- a/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -5,7 +5,7 @@ require "json" -package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "package.json"))) +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json"))) version = package['version'] source = { :git => 'https://github.com/facebook/react-native.git' } @@ -27,16 +27,16 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "9.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0", :tvos => "11.0" } s.source = source s.library = "stdc++" s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.source_files = "**/*.{m,mm,cpp,h}" - s.exclude_files = "**/tests/*", - "**/android/*", - "**/cxx/*" - s.header_dir = "react/graphics" - s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + s.exclude_files = "tests", + "platform/android", + "platform/cxx" + s.header_dir = "react/renderer/graphics" + s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_TARGET_SRCROOT)/../../../\" \"$(PODS_ROOT)/RCT-Folly\"" } - s.dependency "Folly/Fabric", folly_version + s.dependency "RCT-Folly/Fabric", folly_version end diff --git a/ReactCommon/react/renderer/graphics/Rect.h b/ReactCommon/react/renderer/graphics/Rect.h index 78b29c4a3b76e3..19db0b44b6ac1f 100644 --- a/ReactCommon/react/renderer/graphics/Rect.h +++ b/ReactCommon/react/renderer/graphics/Rect.h @@ -94,9 +94,10 @@ struct Rect { rightBottomPoint.y = std::max(rightBottomPoint.y, c.y); rightBottomPoint.y = std::max(rightBottomPoint.y, d.y); - return {leftTopPoint, - {rightBottomPoint.x - leftTopPoint.x, - rightBottomPoint.y - leftTopPoint.y}}; + return { + leftTopPoint, + {rightBottomPoint.x - leftTopPoint.x, + rightBottomPoint.y - leftTopPoint.y}}; } }; diff --git a/ReactCommon/react/renderer/graphics/RectangleCorners.h b/ReactCommon/react/renderer/graphics/RectangleCorners.h index c3932cd67620ec..771dc9f24b8e09 100644 --- a/ReactCommon/react/renderer/graphics/RectangleCorners.h +++ b/ReactCommon/react/renderer/graphics/RectangleCorners.h @@ -57,8 +57,8 @@ namespace std { template struct hash> { - size_t operator()(facebook::react::RectangleCorners const &corners) const - noexcept { + size_t operator()( + facebook::react::RectangleCorners const &corners) const noexcept { return folly::hash::hash_combine( 0, corners.topLeft, diff --git a/ReactCommon/react/renderer/graphics/RectangleEdges.h b/ReactCommon/react/renderer/graphics/RectangleEdges.h index b99b8645576a2b..616abe07e7b253 100644 --- a/ReactCommon/react/renderer/graphics/RectangleEdges.h +++ b/ReactCommon/react/renderer/graphics/RectangleEdges.h @@ -45,20 +45,22 @@ template RectangleEdges operator+( RectangleEdges const &lhs, RectangleEdges const &rhs) noexcept { - return RectangleEdges{lhs.left + rhs.left, - lhs.top + rhs.top, - lhs.right + rhs.right, - lhs.bottom + rhs.bottom}; + return RectangleEdges{ + lhs.left + rhs.left, + lhs.top + rhs.top, + lhs.right + rhs.right, + lhs.bottom + rhs.bottom}; } template RectangleEdges operator-( RectangleEdges const &lhs, RectangleEdges const &rhs) noexcept { - return RectangleEdges{lhs.left - rhs.left, - lhs.top - rhs.top, - lhs.right - rhs.right, - lhs.bottom - rhs.bottom}; + return RectangleEdges{ + lhs.left - rhs.left, + lhs.top - rhs.top, + lhs.right - rhs.right, + lhs.bottom - rhs.bottom}; } /* @@ -70,9 +72,10 @@ using EdgeInsets = RectangleEdges; * Adjusts a rectangle by the given edge insets. */ inline Rect insetBy(Rect const &rect, EdgeInsets const &insets) noexcept { - return Rect{{rect.origin.x + insets.left, rect.origin.y + insets.top}, - {rect.size.width - insets.left - insets.right, - rect.size.height - insets.top - insets.bottom}}; + return Rect{ + {rect.origin.x + insets.left, rect.origin.y + insets.top}, + {rect.size.width - insets.left - insets.right, + rect.size.height - insets.top - insets.bottom}}; } } // namespace react @@ -82,8 +85,8 @@ namespace std { template struct hash> { - size_t operator()(facebook::react::RectangleEdges const &edges) const - noexcept { + size_t operator()( + facebook::react::RectangleEdges const &edges) const noexcept { return folly::hash::hash_combine( 0, edges.left, edges.right, edges.top, edges.bottom); } diff --git a/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.cpp b/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.cpp index c54b57cc503fcd..ff2acbb81425ce 100644 --- a/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.cpp +++ b/ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/Color.cpp @@ -22,10 +22,11 @@ SharedColor colorFromComponents(ColorComponents components) { ColorComponents colorComponentsFromColor(SharedColor sharedColor) { float ratio = 256; Color color = *sharedColor; - return ColorComponents{(float)((color >> 16) & 0xff) / ratio, - (float)((color >> 8) & 0xff) / ratio, - (float)((color >> 0) & 0xff) / ratio, - (float)((color >> 24) & 0xff) / ratio}; + return ColorComponents{ + (float)((color >> 16) & 0xff) / ratio, + (float)((color >> 8) & 0xff) / ratio, + (float)((color >> 0) & 0xff) / ratio, + (float)((color >> 24) & 0xff) / ratio}; } SharedColor clearColor() { diff --git a/ReactCommon/react/renderer/graphics/platform/ios/Color.cpp b/ReactCommon/react/renderer/graphics/platform/ios/Color.cpp index 8cbdeee7fdc60b..d2f5f10ad351a0 100644 --- a/ReactCommon/react/renderer/graphics/platform/ios/Color.cpp +++ b/ReactCommon/react/renderer/graphics/platform/ios/Color.cpp @@ -12,28 +12,28 @@ namespace facebook { namespace react { SharedColor colorFromComponents(ColorComponents components) { - const CGFloat componentsArray[] = { - components.red, components.green, components.blue, components.alpha}; - - auto color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), componentsArray); - - return SharedColor(color, CGColorRelease); + float ratio = 255.9999; + return SharedColor( + ((int)(components.alpha * ratio) & 0xff) << 24 | + ((int)(components.red * ratio) & 0xff) << 16 | + ((int)(components.green * ratio) & 0xff) << 8 | + ((int)(components.blue * ratio) & 0xff)); } -ColorComponents colorComponentsFromColor(SharedColor color) { - if (!color) { +ColorComponents colorComponentsFromColor(SharedColor sharedColor) { + if (!sharedColor) { // Empty color object can be considered as `clear` (black, fully // transparent) color. return ColorComponents{0, 0, 0, 0}; } - auto numberOfComponents __unused = CGColorGetNumberOfComponents(color.get()); - assert(numberOfComponents == 4); - const CGFloat *components = CGColorGetComponents(color.get()); - return ColorComponents{(float)components[0], - (float)components[1], - (float)components[2], - (float)components[3]}; + float ratio = 256; + Color color = *sharedColor; + return ColorComponents{ + (float)((color >> 16) & 0xff) / ratio, + (float)((color >> 8) & 0xff) / ratio, + (float)((color >> 0) & 0xff) / ratio, + (float)((color >> 24) & 0xff) / ratio}; } SharedColor clearColor() { diff --git a/ReactCommon/react/renderer/graphics/platform/ios/Color.h b/ReactCommon/react/renderer/graphics/platform/ios/Color.h index abaf98f4245e56..0b8ab406b40f50 100644 --- a/ReactCommon/react/renderer/graphics/platform/ios/Color.h +++ b/ReactCommon/react/renderer/graphics/platform/ios/Color.h @@ -7,17 +7,17 @@ #pragma once -#include +#include -#include #include #include namespace facebook { namespace react { -using Color = CGColor; -using SharedColor = std::shared_ptr; +using Color = int32_t; + +using SharedColor = better::optional; SharedColor colorFromComponents(ColorComponents components); ColorComponents colorComponentsFromColor(SharedColor color); diff --git a/ReactCommon/react/renderer/graphics/rounding.h b/ReactCommon/react/renderer/graphics/rounding.h index 8427303fe8a308..b43b9d494d4b21 100644 --- a/ReactCommon/react/renderer/graphics/rounding.h +++ b/ReactCommon/react/renderer/graphics/rounding.h @@ -30,20 +30,23 @@ Float roundToPixel(Float value, Float scaleFactor) { template Point roundToPixel(Point value, Float scaleFactor) { - return Point{roundToPixel(value.x, scaleFactor), - roundToPixel(value.y, scaleFactor)}; + return Point{ + roundToPixel(value.x, scaleFactor), + roundToPixel(value.y, scaleFactor)}; } template Size roundToPixel(Size value, Float scaleFactor) { - return Size{roundToPixel(value.width, scaleFactor), - roundToPixel(value.height, scaleFactor)}; + return Size{ + roundToPixel(value.width, scaleFactor), + roundToPixel(value.height, scaleFactor)}; } template Rect roundToPixel(Rect value, Float scaleFactor) { - return Rect{roundToPixel(value.origin), - roundToPixel(value.size)}; + return Rect{ + roundToPixel(value.origin), + roundToPixel(value.size)}; } /* diff --git a/ReactCommon/react/renderer/graphics/tests/TransformTest.cpp b/ReactCommon/react/renderer/graphics/tests/TransformTest.cpp index c11c0c2b701146..9c40fc341f49e3 100644 --- a/ReactCommon/react/renderer/graphics/tests/TransformTest.cpp +++ b/ReactCommon/react/renderer/graphics/tests/TransformTest.cpp @@ -6,6 +6,7 @@ */ #include + #include #include diff --git a/ReactCommon/react/renderer/imagemanager/BUCK b/ReactCommon/react/renderer/imagemanager/BUCK index 9ea987914490db..52f99b3fec6fc0 100644 --- a/ReactCommon/react/renderer/imagemanager/BUCK +++ b/ReactCommon/react/renderer/imagemanager/BUCK @@ -70,7 +70,6 @@ rn_xplat_cxx_library( ios_exported_headers = subdir_glob( [ ("", "*.h"), - ("platform/ios", "RCTImageInstrumentationProxy.h"), ("platform/ios", "RCTImagePrimitivesConversions.h"), ], prefix = "react/renderer/imagemanager", @@ -103,10 +102,7 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ - "//third-party/glog:glog", - "//xplat/fbsystrace:fbsystrace", "//xplat/folly:headers_only", - "//xplat/folly:memory", "//xplat/folly:molly", YOGA_CXX_TARGET, react_native_xplat_target("react/renderer/core:core"), diff --git a/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h b/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h deleted file mode 100644 index c1671cb6790376..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook { -namespace react { - -/* - * A base class for performing image loading instrumentation. - * The actual instrumentation is app, platform, and image loader-specific. - */ -class ImageInstrumentation { - public: - virtual ~ImageInstrumentation() noexcept = default; - - /** - * Mark that the image content is set on the native image component on screen. - */ - virtual void didSetImage() const = 0; - - /** - * Mark that the image view starts to be visible on screen. - */ - virtual void didEnterVisibilityRange() const = 0; - - /** - * Mark that the image view is no longer visible on screen. - */ - virtual void didExitVisibilityRange() const = 0; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/ImageRequest.h b/ReactCommon/react/renderer/imagemanager/ImageRequest.h index 8c5dc8d5fe814c..2c181d3b9b28f5 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageRequest.h +++ b/ReactCommon/react/renderer/imagemanager/ImageRequest.h @@ -7,10 +7,10 @@ #pragma once -#include #include #include #include +#include #include namespace facebook { @@ -30,7 +30,7 @@ class ImageRequest final { */ ImageRequest( const ImageSource &imageSource, - std::shared_ptr instrumentation); + std::shared_ptr telemetry); /* * The move constructor. @@ -49,6 +49,11 @@ class ImageRequest final { */ void setCancelationFunction(std::function cancelationFunction); + /* + * Returns the Image Source associated with the request. + */ + const ImageSource &getImageSource() const; + /* * Returns stored observer coordinator as a shared pointer. * Retain this *or* `ImageRequest` to ensure a correct lifetime of the object. @@ -64,18 +69,10 @@ class ImageRequest final { const ImageResponseObserverCoordinator &getObserverCoordinator() const; /* - * Returns stored image instrumentation object as a shared pointer. + * Returns stored image telemetry object as a shared pointer. * Retain this *or* `ImageRequest` to ensure a correct lifetime of the object. */ - const std::shared_ptr - &getSharedImageInstrumentation() const; - - /* - * Returns the image instrumentation object specific to this request. - * Use this if a correct lifetime of the object is ensured in some other way - * (e.g. by retaining an `ImageRequest`). - */ - const ImageInstrumentation &getImageInstrumentation() const; + const std::shared_ptr &getSharedTelemetry() const; private: /* @@ -84,24 +81,19 @@ class ImageRequest final { ImageSource imageSource_; /* - * Event coordinator associated with the reqest. + * Image telemetry associated with the request. */ - std::shared_ptr coordinator_{}; + std::shared_ptr telemetry_{}; /* - * Image instrumentation specific to the request. + * Event coordinator associated with the reqest. */ - std::shared_ptr instrumentation_; + std::shared_ptr coordinator_{}; /* * Function we can call to cancel image request (see destructor). */ std::function cancelRequest_; - - /* - * Indicates that the object was moved and hence cannot be used anymore. - */ - bool moved_{false}; }; } // namespace react diff --git a/ReactCommon/react/renderer/imagemanager/ImageResponse.cpp b/ReactCommon/react/renderer/imagemanager/ImageResponse.cpp index ab874617d7d492..361e5fe7f88541 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageResponse.cpp +++ b/ReactCommon/react/renderer/imagemanager/ImageResponse.cpp @@ -10,12 +10,18 @@ namespace facebook { namespace react { -ImageResponse::ImageResponse(const std::shared_ptr &image) - : image_(image) {} +ImageResponse::ImageResponse( + const std::shared_ptr &image, + const std::shared_ptr &metadata) + : image_(image), metadata_(metadata) {} std::shared_ptr ImageResponse::getImage() const { return image_; } +std::shared_ptr ImageResponse::getMetadata() const { + return metadata_; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/ImageResponse.h b/ReactCommon/react/renderer/imagemanager/ImageResponse.h index 52efffd9760369..23cc49f65bf680 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageResponse.h +++ b/ReactCommon/react/renderer/imagemanager/ImageResponse.h @@ -23,12 +23,18 @@ class ImageResponse final { Failed, }; - ImageResponse(const std::shared_ptr &image); + ImageResponse( + const std::shared_ptr &image, + const std::shared_ptr &metadata); std::shared_ptr getImage() const; + std::shared_ptr getMetadata() const; + private: std::shared_ptr image_{}; + + std::shared_ptr metadata_{}; }; } // namespace react diff --git a/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.cpp b/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.cpp index d50469818fcdeb..3f3fd6a5ffbbb4 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.cpp +++ b/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.cpp @@ -24,8 +24,9 @@ void ImageResponseObserverCoordinator::addObserver( } case ImageResponse::Status::Completed: { auto imageData = imageData_; + auto imageMetadata = imageMetadata_; mutex_.unlock(); - observer.didReceiveImage(ImageResponse{imageData}); + observer.didReceiveImage(ImageResponse{imageData, imageMetadata}); break; } case ImageResponse::Status::Failed: { @@ -63,6 +64,7 @@ void ImageResponseObserverCoordinator::nativeImageResponseComplete( ImageResponse const &imageResponse) const { mutex_.lock(); imageData_ = imageResponse.getImage(); + imageMetadata_ = imageResponse.getMetadata(); assert(status_ == ImageResponse::Status::Loading); status_ = ImageResponse::Status::Completed; auto observers = observers_; diff --git a/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.h b/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.h index f28e7e5805c37c..6b1f8301588197 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.h +++ b/ReactCommon/react/renderer/imagemanager/ImageResponseObserverCoordinator.h @@ -73,6 +73,12 @@ class ImageResponseObserverCoordinator { */ mutable std::shared_ptr imageData_; + /* + * Cache image metadata. + * Mutable: protected by mutex_. + */ + mutable std::shared_ptr imageMetadata_; + /* * Observer and data mutex. */ diff --git a/ReactCommon/react/renderer/imagemanager/ImageTelemetry.cpp b/ReactCommon/react/renderer/imagemanager/ImageTelemetry.cpp new file mode 100644 index 00000000000000..40524e5b0ff0f6 --- /dev/null +++ b/ReactCommon/react/renderer/imagemanager/ImageTelemetry.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "ImageTelemetry.h" + +namespace facebook { +namespace react { + +SurfaceId ImageTelemetry::getSurfaceId() const { + return surfaceId_; +} + +TelemetryTimePoint ImageTelemetry::getWillRequestUrlTime() const { + return willRequestUrlTime_; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/ImageTelemetry.h b/ReactCommon/react/renderer/imagemanager/ImageTelemetry.h new file mode 100644 index 00000000000000..1ffaffd0a4aa0c --- /dev/null +++ b/ReactCommon/react/renderer/imagemanager/ImageTelemetry.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +/* + * Represents telemetry data associated with a image request + * where the willRequestUrlTime is the time at ImageTelemetry's creation. + */ +class ImageTelemetry final { + public: + ImageTelemetry(SurfaceId const surfaceId) : surfaceId_(surfaceId) { + willRequestUrlTime_ = telemetryTimePointNow(); + } + + TelemetryTimePoint getWillRequestUrlTime() const; + + SurfaceId getSurfaceId() const; + + private: + TelemetryTimePoint willRequestUrlTime_; + + const SurfaceId surfaceId_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp index 35475d1083149a..9f811bc4d4a3d2 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp @@ -12,13 +12,14 @@ namespace react { ImageRequest::ImageRequest( const ImageSource &imageSource, - std::shared_ptr instrumentation) - : imageSource_(imageSource), instrumentation_(instrumentation) { + std::shared_ptr telemetry) + : imageSource_(imageSource), telemetry_(telemetry) { // Not implemented. } ImageRequest::ImageRequest(ImageRequest &&other) noexcept : imageSource_(std::move(other.imageSource_)), + telemetry_(std::move(other.telemetry_)), coordinator_(std::move(other.coordinator_)) { // Not implemented. } @@ -39,16 +40,5 @@ const std::shared_ptr abort(); } -const std::shared_ptr - &ImageRequest::getSharedImageInstrumentation() const { - // Not implemented - abort(); -} - -const ImageInstrumentation &ImageRequest::getImageInstrumentation() const { - // Not implemented - abort(); -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp index 96911824679a85..ac01f5b1c1903f 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp @@ -11,20 +11,20 @@ namespace facebook { namespace react { ImageRequest::ImageRequest( - const ImageSource &imageSource, - std::shared_ptr instrumentation) - : imageSource_(imageSource), instrumentation_(instrumentation) { + ImageSource const &imageSource, + std::shared_ptr telemetry) + : imageSource_(imageSource), telemetry_(telemetry) { coordinator_ = std::make_shared(); } ImageRequest::ImageRequest(ImageRequest &&other) noexcept : imageSource_(std::move(other.imageSource_)), - coordinator_(std::move(other.coordinator_)), - instrumentation_(std::move(other.instrumentation_)) { - other.moved_ = true; + telemetry_(std::move(other.telemetry_)), + coordinator_(std::move(other.coordinator_)) { other.coordinator_ = nullptr; other.cancelRequest_ = nullptr; - other.instrumentation_ = nullptr; + other.telemetry_ = nullptr; + other.imageSource_ = {}; } ImageRequest::~ImageRequest() { @@ -38,6 +38,15 @@ void ImageRequest::setCancelationFunction( cancelRequest_ = cancelationFunction; } +const ImageSource &ImageRequest::getImageSource() const { + return imageSource_; +} + +const std::shared_ptr &ImageRequest::getSharedTelemetry() + const { + return telemetry_; +} + const ImageResponseObserverCoordinator &ImageRequest::getObserverCoordinator() const { return *coordinator_; @@ -48,14 +57,5 @@ const std::shared_ptr return coordinator_; } -const std::shared_ptr - &ImageRequest::getSharedImageInstrumentation() const { - return instrumentation_; -} - -const ImageInstrumentation &ImageRequest::getImageInstrumentation() const { - return *instrumentation_; -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h deleted file mode 100644 index 95726a5ff0cccf..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include -#include - -NS_ASSUME_NONNULL_BEGIN - -namespace facebook { -namespace react { - -class RCTImageInstrumentationProxy final : public ImageInstrumentation { - public: - RCTImageInstrumentationProxy(id imageLoader); - ~RCTImageInstrumentationProxy(); - - void didSetImage() const override; - void didEnterVisibilityRange() const override; - void didExitVisibilityRange() const override; - - void trackNativeImageView(UIView *imageView) const; - void setImageURLLoaderRequest(RCTImageURLLoaderRequest *request); - - private: - __weak id imageLoader_; - RCTImageURLLoaderRequest *imageURLLoaderRequest_; -}; - -} // namespace react -} // namespace facebook - -NS_ASSUME_NONNULL_END diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm deleted file mode 100644 index 1ed24f9faacda3..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTImageInstrumentationProxy.h" - -namespace facebook { -namespace react { - -RCTImageInstrumentationProxy::RCTImageInstrumentationProxy(id imageLoader) - : imageLoader_(imageLoader) -{ -} - -RCTImageInstrumentationProxy::~RCTImageInstrumentationProxy() -{ - if (!imageURLLoaderRequest_) { - return; - } - [imageLoader_ trackURLImageDidDestroy:imageURLLoaderRequest_]; -} - -void RCTImageInstrumentationProxy::didSetImage() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - if (!imageURLLoaderRequest_) { - return; - } - - [imageLoader_ trackURLImageContentDidSetForRequest:imageURLLoaderRequest_]; -} - -void RCTImageInstrumentationProxy::didEnterVisibilityRange() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - // TODO (T58941612): Not yet supported. - if (!imageURLLoaderRequest_) { - return; - } -} - -void RCTImageInstrumentationProxy::didExitVisibilityRange() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - // TODO (T58941612): Not yet supported. - if (!imageURLLoaderRequest_) { - return; - } -} - -void RCTImageInstrumentationProxy::trackNativeImageView(UIView *imageView) const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - if (!imageURLLoaderRequest_) { - return; - } - [imageLoader_ trackURLImageVisibilityForRequest:imageURLLoaderRequest_ imageView:imageView]; -} - -void RCTImageInstrumentationProxy::setImageURLLoaderRequest(RCTImageURLLoaderRequest *request) -{ - imageURLLoaderRequest_ = request; -} - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm index 9ad64c68fd28e2..4922b96ef03d3f 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm @@ -16,7 +16,6 @@ #import #import -#import "RCTImageInstrumentationProxy.h" #import "RCTImagePrimitivesConversions.h" using namespace facebook::react; @@ -41,8 +40,15 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa { SystraceSection s("RCTImageManager::requestImage"); - auto imageInstrumentation = std::make_shared(_imageLoader); - auto imageRequest = ImageRequest(imageSource, imageInstrumentation); + NSURLRequest *request = NSURLRequestFromImageSource(imageSource); + std::shared_ptr telemetry; + if ([self->_imageLoader shouldEnablePerfLoggingForRequestUrl:request.URL]) { + telemetry = std::make_shared(surfaceId); + } else { + telemetry = nullptr; + } + + auto imageRequest = ImageRequest(imageSource, telemetry); auto weakObserverCoordinator = (std::weak_ptr)imageRequest.getSharedObserverCoordinator(); @@ -60,16 +66,15 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa * T46024425 for more details. */ dispatch_async(_backgroundSerialQueue, ^{ - NSURLRequest *request = NSURLRequestFromImageSource(imageSource); - - auto completionBlock = ^(NSError *error, UIImage *image) { + auto completionBlock = ^(NSError *error, UIImage *image, id metadata) { auto observerCoordinator = weakObserverCoordinator.lock(); if (!observerCoordinator) { return; } if (image && !error) { - observerCoordinator->nativeImageResponseComplete(ImageResponse(wrapManagedObject(image))); + auto wrappedMetadata = metadata ? wrapManagedObject(metadata) : nullptr; + observerCoordinator->nativeImageResponseComplete(ImageResponse(wrapManagedObject(image), wrappedMetadata)); } else { observerCoordinator->nativeImageResponseFailed(); } @@ -99,10 +104,6 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa completionBlock:completionBlock]; RCTImageLoaderCancellationBlock cancelationBlock = loaderRequest.cancellationBlock; sharedCancelationFunction.assign([cancelationBlock]() { cancelationBlock(); }); - - if (imageInstrumentation) { - imageInstrumentation->setImageURLLoaderRequest(loaderRequest); - } }); return imageRequest; diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm index 6f8c54d492c72b..7a36d42ea4a283 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm @@ -36,7 +36,8 @@ - (instancetype)initWithImageLoader:(id)i - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfaceId { - auto imageRequest = ImageRequest(imageSource, nullptr); + auto telemetry = std::make_shared(surfaceId); + auto imageRequest = ImageRequest(imageSource, telemetry); auto weakObserverCoordinator = (std::weak_ptr)imageRequest.getSharedObserverCoordinator(); @@ -49,14 +50,15 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa NSURLRequest *request = NSURLRequestFromImageSource(imageSource); - auto completionBlock = ^(NSError *error, UIImage *image) { + auto completionBlock = ^(NSError *error, UIImage *image, id metadata) { auto observerCoordinator = weakObserverCoordinator.lock(); if (!observerCoordinator) { return; } if (image && !error) { - observerCoordinator->nativeImageResponseComplete(ImageResponse(wrapManagedObject(image))); + auto wrappedMetadata = metadata ? wrapManagedObject(metadata) : nullptr; + observerCoordinator->nativeImageResponseComplete(ImageResponse(wrapManagedObject(image), wrappedMetadata)); } else { observerCoordinator->nativeImageResponseFailed(); } diff --git a/ReactCommon/react/renderer/mapbuffer/BUCK b/ReactCommon/react/renderer/mapbuffer/BUCK index 5bd4038921efe8..dc246215845732 100644 --- a/ReactCommon/react/renderer/mapbuffer/BUCK +++ b/ReactCommon/react/renderer/mapbuffer/BUCK @@ -22,7 +22,7 @@ rn_xplat_cxx_library( [ ("", "*.h"), ], - prefix = "react", + prefix = "react/renderer/mapbuffer", ), compiler_flags = [ "-fexceptions", @@ -63,5 +63,6 @@ fb_xplat_cxx_test( deps = [ "//xplat/folly:molly", "//xplat/third-party/gmock:gtest", + react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"), ], ) diff --git a/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp b/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp index 085ccae66c975d..2113ecf41e0a3d 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp +++ b/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp @@ -14,5 +14,9 @@ MapBuffer::MapBuffer() {} MapBuffer::~MapBuffer() {} +int MapBuffer::getSize() { + return 0; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/mapbuffer/MapBuffer.h b/ReactCommon/react/renderer/mapbuffer/MapBuffer.h index 3ce365990d5250..1a3e5b12e3b401 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBuffer.h +++ b/ReactCommon/react/renderer/mapbuffer/MapBuffer.h @@ -31,6 +31,8 @@ class MapBuffer { public: MapBuffer(); virtual ~MapBuffer(); + + int getSize(); }; } // namespace react diff --git a/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp b/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp index 4785f09ae7e498..eba9018f90971d 100644 --- a/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp +++ b/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp @@ -7,8 +7,14 @@ #include +#include #include +#include -TEST(MapBufferTest, testSomething) { - // TODO +using namespace facebook::react; + +// Dummy test to create setup of tests +TEST(MapBufferTest, testMapCreation) { + auto buffer = MapBuffer(); + assert(buffer.getSize() == 0); } diff --git a/ReactCommon/react/renderer/mounting/Differentiator.cpp b/ReactCommon/react/renderer/mounting/Differentiator.cpp index 300c38059f8a64..5545674c3e272d 100644 --- a/ReactCommon/react/renderer/mounting/Differentiator.cpp +++ b/ReactCommon/react/renderer/mounting/Differentiator.cpp @@ -251,7 +251,7 @@ ShadowViewNodePair::List sliceChildShadowNodeViewPairsV2( reorderInPlaceIfNeeded(pairList); // Set list and mountIndex for each after reordering - int mountIndex = 0; + size_t mountIndex = 0; for (auto &child : pairList) { child.mountIndex = (child.isConcreteView ? mountIndex++ : -1); } @@ -376,7 +376,7 @@ static void calculateShadowViewMutationsFlattener( << " [" << node.shadowView.tag << "]"; LOG(ERROR) << "Differ Flattener Entry: Child Pairs: "; std::string strTreeChildPairs; - for (int k = 0; k < treeChildren.size(); k++) { + for (size_t k = 0; k < treeChildren.size(); k++) { strTreeChildPairs.append(std::to_string(treeChildren[k].shadowView.tag)); strTreeChildPairs.append(treeChildren[k].isConcreteView ? "" : "'"); strTreeChildPairs.append(treeChildren[k].flattened ? "*" : ""); @@ -410,7 +410,7 @@ static void calculateShadowViewMutationsFlattener( auto deletionCreationCandidatePairs = TinyMap{}; - for (int index = 0; + for (size_t index = 0; index < treeChildren.size() && index < treeChildren.size(); index++) { // First, remove all children of the tree being flattened, or insert @@ -486,10 +486,7 @@ static void calculateShadowViewMutationsFlattener( newTreeNodePair.isConcreteView && oldTreeNodePair.isConcreteView) { mutationInstructionContainer.updateMutations.push_back( ShadowViewMutation::UpdateMutation( - parentShadowView, - oldTreeNodePair.shadowView, - newTreeNodePair.shadowView, - newTreeNodePair.mountIndex)); + oldTreeNodePair.shadowView, newTreeNodePair.shadowView)); } // Update children if appropriate. @@ -530,7 +527,7 @@ static void calculateShadowViewMutationsFlattener( // this "else" block, including any annotations we put on them. auto newFlattenedNodes = sliceChildShadowNodeViewPairsV2( *newTreeNodePair.shadowNode, true); - for (int i = 0; i < newFlattenedNodes.size(); i++) { + for (size_t i = 0; i < newFlattenedNodes.size(); i++) { auto &newChild = newFlattenedNodes[i]; auto unvisitedOtherNodesIt = @@ -582,7 +579,7 @@ static void calculateShadowViewMutationsFlattener( // this "else" block, including any annotations we put on them. auto oldFlattenedNodes = sliceChildShadowNodeViewPairsV2( *oldTreeNodePair.shadowNode, true); - for (int i = 0; i < oldFlattenedNodes.size(); i++) { + for (size_t i = 0; i < oldFlattenedNodes.size(); i++) { auto &oldChild = oldFlattenedNodes[i]; auto unvisitedOtherNodesIt = @@ -767,7 +764,7 @@ static void calculateShadowViewMutationsV2( return; } - auto index = int{0}; + size_t index = 0; // Lists of mutations auto createMutations = ShadowViewMutation::List{}; @@ -777,20 +774,20 @@ static void calculateShadowViewMutationsV2( auto updateMutations = ShadowViewMutation::List{}; auto downwardMutations = ShadowViewMutation::List{}; auto destructiveDownwardMutations = ShadowViewMutation::List{}; - auto mutationInstructionContainer = - OrderedMutationInstructionContainer{createMutations, - deleteMutations, - insertMutations, - removeMutations, - updateMutations, - downwardMutations, - destructiveDownwardMutations}; + auto mutationInstructionContainer = OrderedMutationInstructionContainer{ + createMutations, + deleteMutations, + insertMutations, + removeMutations, + updateMutations, + downwardMutations, + destructiveDownwardMutations}; DEBUG_LOGS({ LOG(ERROR) << "Differ Entry: Child Pairs of node: [" << parentShadowView.tag << "]"; std::string strOldChildPairs; - for (int oldIndex = 0; oldIndex < oldChildPairs.size(); oldIndex++) { + for (size_t oldIndex = 0; oldIndex < oldChildPairs.size(); oldIndex++) { strOldChildPairs.append( std::to_string(oldChildPairs[oldIndex].shadowView.tag)); strOldChildPairs.append( @@ -799,7 +796,7 @@ static void calculateShadowViewMutationsV2( strOldChildPairs.append(", "); } std::string strNewChildPairs; - for (int newIndex = 0; newIndex < newChildPairs.size(); newIndex++) { + for (size_t newIndex = 0; newIndex < newChildPairs.size(); newIndex++) { strNewChildPairs.append( std::to_string(newChildPairs[newIndex].shadowView.tag)); strNewChildPairs.append( @@ -850,10 +847,7 @@ static void calculateShadowViewMutationsV2( if (newChildPair.isConcreteView && oldChildPair.shadowView != newChildPair.shadowView) { updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - newChildPair.mountIndex)); + oldChildPair.shadowView, newChildPair.shadowView)); } // Recursively update tree if ShadowNode pointers are not equal @@ -872,7 +866,7 @@ static void calculateShadowViewMutationsV2( } } - int lastIndexAfterFirstStage = index; + size_t lastIndexAfterFirstStage = index; if (index == newChildPairs.size()) { // We've reached the end of the new children. We can delete+remove the @@ -943,9 +937,9 @@ static void calculateShadowViewMutationsV2( // Walk through both lists at the same time // We will perform updates, create+insert, remove+delete, remove+insert // (move) here. - int oldIndex = lastIndexAfterFirstStage, - newIndex = lastIndexAfterFirstStage, newSize = newChildPairs.size(), - oldSize = oldChildPairs.size(); + size_t oldIndex = lastIndexAfterFirstStage, + newIndex = lastIndexAfterFirstStage, newSize = newChildPairs.size(), + oldSize = oldChildPairs.size(); while (newIndex < newSize || oldIndex < oldSize) { bool haveNewPair = newIndex < newSize; bool haveOldPair = oldIndex < oldSize; @@ -955,8 +949,8 @@ static void calculateShadowViewMutationsV2( auto const &oldChildPair = oldChildPairs[oldIndex]; auto const &newChildPair = newChildPairs[newIndex]; - int newTag = newChildPair.shadowView.tag; - int oldTag = oldChildPair.shadowView.tag; + Tag newTag = newChildPair.shadowView.tag; + Tag oldTag = oldChildPair.shadowView.tag; if (newTag == oldTag) { DEBUG_LOGS({ @@ -995,10 +989,7 @@ static void calculateShadowViewMutationsV2( // concrete view. The case where they're different is handled above. if (oldChildPair.shadowView != newChildPair.shadowView) { updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - newChildPair.mountIndex)); + oldChildPair.shadowView, newChildPair.shadowView)); } // Remove from newRemainingPairs @@ -1050,7 +1041,7 @@ static void calculateShadowViewMutationsV2( // children from other nodes, etc. auto oldFlattenedNodes = sliceChildShadowNodeViewPairsV2( *oldChildPair.shadowNode, true); - for (int i = 0, j = 0; + for (size_t i = 0, j = 0; i < oldChildPairs.size() && j < oldFlattenedNodes.size(); i++) { auto &oldChild = oldChildPairs[i]; @@ -1076,11 +1067,7 @@ static void calculateShadowViewMutationsV2( for (auto &oldFlattenedNode : oldFlattenedNodes) { auto unvisitedOldChildPairIt = unvisitedOldChildPairs.find( oldFlattenedNode.shadowView.tag); - if (unvisitedOldChildPairIt != unvisitedOldChildPairs.end()) { - // Node unvisited - delete it entirely - deleteMutations.push_back(ShadowViewMutation::DeleteMutation( - oldFlattenedNode.shadowView)); - } else { + if (unvisitedOldChildPairIt == unvisitedOldChildPairs.end()) { // Node was visited - make sure to remove it from // "newRemainingPairs" map auto newRemainingIt = @@ -1123,7 +1110,7 @@ static void calculateShadowViewMutationsV2( if (haveOldPair) { auto const &oldChildPair = oldChildPairs[oldIndex]; - int oldTag = oldChildPair.shadowView.tag; + Tag oldTag = oldChildPair.shadowView.tag; // Was oldTag already inserted? This indicates a reordering, not just // a move. The new node has already been inserted, we just need to @@ -1175,7 +1162,7 @@ static void calculateShadowViewMutationsV2( // children from other nodes, etc. auto oldFlattenedNodes = sliceChildShadowNodeViewPairsV2( *oldChildPair.shadowNode, true); - for (int i = 0, j = 0; + for (size_t i = 0, j = 0; i < oldChildPairs.size() && j < oldFlattenedNodes.size(); i++) { auto &oldChild = oldChildPairs[i]; @@ -1202,11 +1189,7 @@ static void calculateShadowViewMutationsV2( for (auto &oldFlattenedNode : oldFlattenedNodes) { auto unvisitedOldChildPairIt = unvisitedOldChildPairs.find( oldFlattenedNode.shadowView.tag); - if (unvisitedOldChildPairIt != unvisitedOldChildPairs.end()) { - // Node unvisited - delete it entirely - deleteMutations.push_back(ShadowViewMutation::DeleteMutation( - oldFlattenedNode.shadowView)); - } else { + if (unvisitedOldChildPairIt == unvisitedOldChildPairs.end()) { // Node was visited - make sure to remove it from // "newRemainingPairs" map auto newRemainingIt = @@ -1259,10 +1242,7 @@ static void calculateShadowViewMutationsV2( if (oldChildPair.shadowView != newChildPair.shadowView) { updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - newChildPair.mountIndex)); + oldChildPair.shadowView, newChildPair.shadowView)); } } if (!oldChildPair.flattened && @@ -1450,7 +1430,10 @@ static void calculateShadowViewMutationsV2( std::back_inserter(mutations)); } -static void sliceChildShadowNodeViewPairsRecursively( +/** + * Only used by unit tests currently. + */ +static void sliceChildShadowNodeViewPairsRecursivelyLegacy( ShadowViewNodePair::List &pairList, Point layoutOffset, ShadowNode const &shadowNode) { @@ -1481,13 +1464,16 @@ static void sliceChildShadowNodeViewPairsRecursively( pairList.push_back({shadowView, &childShadowNode}); } - sliceChildShadowNodeViewPairsRecursively( + sliceChildShadowNodeViewPairsRecursivelyLegacy( pairList, origin, childShadowNode); } } } -ShadowViewNodePair::List sliceChildShadowNodeViewPairs( +/** + * Only used by unit tests currently. + */ +ShadowViewNodePair::List sliceChildShadowNodeViewPairsLegacy( ShadowNode const &shadowNode) { auto pairList = ShadowViewNodePair::List{}; @@ -1497,363 +1483,14 @@ ShadowViewNodePair::List sliceChildShadowNodeViewPairs( return pairList; } - sliceChildShadowNodeViewPairsRecursively(pairList, {0, 0}, shadowNode); + sliceChildShadowNodeViewPairsRecursivelyLegacy(pairList, {0, 0}, shadowNode); return pairList; } -static void calculateShadowViewMutations( - ShadowViewMutation::List &mutations, - ShadowView const &parentShadowView, - ShadowViewNodePair::List &&oldChildPairs, - ShadowViewNodePair::List &&newChildPairs) { - if (oldChildPairs.empty() && newChildPairs.empty()) { - return; - } - - // Sorting pairs based on `orderIndex` if needed. - reorderInPlaceIfNeeded(oldChildPairs); - reorderInPlaceIfNeeded(newChildPairs); - - auto index = int{0}; - - // Lists of mutations - auto createMutations = ShadowViewMutation::List{}; - auto deleteMutations = ShadowViewMutation::List{}; - auto insertMutations = ShadowViewMutation::List{}; - auto removeMutations = ShadowViewMutation::List{}; - auto updateMutations = ShadowViewMutation::List{}; - auto downwardMutations = ShadowViewMutation::List{}; - auto destructiveDownwardMutations = ShadowViewMutation::List{}; - - // Stage 1: Collecting `Update` mutations - for (index = 0; index < oldChildPairs.size() && index < newChildPairs.size(); - index++) { - auto const &oldChildPair = oldChildPairs[index]; - auto const &newChildPair = newChildPairs[index]; - - if (oldChildPair.shadowView.tag != newChildPair.shadowView.tag) { - DEBUG_LOGS({ - LOG(ERROR) << "Differ Branch 1.1: Tags Different: [" - << oldChildPair.shadowView.tag << "] [" - << newChildPair.shadowView.tag << "]"; - }); - - // Totally different nodes, updating is impossible. - break; - } - - DEBUG_LOGS({ - LOG(ERROR) << "Differ Branch 1.2: Same tags, update and recurse: [" - << oldChildPair.shadowView.tag << "]" - << (oldChildPair.flattened ? " (flattened)" : "") - << (oldChildPair.isConcreteView ? " (concrete)" : "") << "[" - << newChildPair.shadowView.tag << "]" - << (newChildPair.flattened ? " (flattened)" : "") - << (newChildPair.isConcreteView ? " (concrete)" : ""); - }); - - if (oldChildPair.shadowView != newChildPair.shadowView) { - updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - index)); - } - - auto oldGrandChildPairs = - sliceChildShadowNodeViewPairs(*oldChildPair.shadowNode); - auto newGrandChildPairs = - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode); - calculateShadowViewMutations( - *(newGrandChildPairs.size() ? &downwardMutations - : &destructiveDownwardMutations), - oldChildPair.shadowView, - std::move(oldGrandChildPairs), - std::move(newGrandChildPairs)); - } - - int lastIndexAfterFirstStage = index; - - if (index == newChildPairs.size()) { - // We've reached the end of the new children. We can delete+remove the - // rest. - for (; index < oldChildPairs.size(); index++) { - auto const &oldChildPair = oldChildPairs[index]; - - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 2: Deleting Tag/Tree (may be reparented): [" - << oldChildPair.shadowView.tag << "]"; - }); - - deleteMutations.push_back( - ShadowViewMutation::DeleteMutation(oldChildPair.shadowView)); - removeMutations.push_back(ShadowViewMutation::RemoveMutation( - parentShadowView, oldChildPair.shadowView, index)); - - // We also have to call the algorithm recursively to clean up the entire - // subtree starting from the removed view. - calculateShadowViewMutations( - destructiveDownwardMutations, - oldChildPair.shadowView, - sliceChildShadowNodeViewPairs(*oldChildPair.shadowNode), - {}); - } - } else if (index == oldChildPairs.size()) { - // If we don't have any more existing children we can choose a fast path - // since the rest will all be create+insert. - for (; index < newChildPairs.size(); index++) { - auto const &newChildPair = newChildPairs[index]; - - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 3: Creating Tag/Tree (may be reparented): [" - << newChildPair.shadowView.tag << "]"; - }); - - insertMutations.push_back(ShadowViewMutation::InsertMutation( - parentShadowView, newChildPair.shadowView, index)); - createMutations.push_back( - ShadowViewMutation::CreateMutation(newChildPair.shadowView)); - - calculateShadowViewMutations( - downwardMutations, - newChildPair.shadowView, - {}, - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode)); - } - } else { - // Collect map of tags in the new list - // In the future it would be nice to use TinyMap for newInsertedPairs, but - // it's challenging to build an iterator that will work for our use-case - // here. - auto newRemainingPairs = TinyMap{}; - auto newInsertedPairs = TinyMap{}; - for (; index < newChildPairs.size(); index++) { - auto const &newChildPair = newChildPairs[index]; - newRemainingPairs.insert({newChildPair.shadowView.tag, &newChildPair}); - } - - // Walk through both lists at the same time - // We will perform updates, create+insert, remove+delete, remove+insert - // (move) here. - int oldIndex = lastIndexAfterFirstStage, - newIndex = lastIndexAfterFirstStage, newSize = newChildPairs.size(), - oldSize = oldChildPairs.size(); - while (newIndex < newSize || oldIndex < oldSize) { - bool haveNewPair = newIndex < newSize; - bool haveOldPair = oldIndex < oldSize; - - // Advance both pointers if pointing to the same element - if (haveNewPair && haveOldPair) { - auto const &newChildPair = newChildPairs[newIndex]; - auto const &oldChildPair = oldChildPairs[oldIndex]; - - int newTag = newChildPair.shadowView.tag; - int oldTag = oldChildPair.shadowView.tag; - - if (newTag == oldTag) { - DEBUG_LOGS({ - LOG(ERROR) << "Differ Branch 5: Matched Tags at indices: " - << oldIndex << " " << newIndex << ": [" - << oldChildPair.shadowView.tag << "][" - << newChildPair.shadowView.tag << "]"; - }); - - // Generate Update instructions - if (oldChildPair.shadowView != newChildPair.shadowView) { - updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - index)); - } - - // Remove from newRemainingPairs - auto newRemainingPairIt = newRemainingPairs.find(oldTag); - if (newRemainingPairIt != newRemainingPairs.end()) { - newRemainingPairs.erase(newRemainingPairIt); - } - - // Update subtrees - if (oldChildPair.shadowNode != newChildPair.shadowNode) { - auto oldGrandChildPairs = - sliceChildShadowNodeViewPairs(*oldChildPair.shadowNode); - auto newGrandChildPairs = - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode); - calculateShadowViewMutations( - *(newGrandChildPairs.size() ? &downwardMutations - : &destructiveDownwardMutations), - oldChildPair.shadowView, - std::move(oldGrandChildPairs), - std::move(newGrandChildPairs)); - } - - newIndex++; - oldIndex++; - continue; - } - } - - if (haveOldPair) { - auto const &oldChildPair = oldChildPairs[oldIndex]; - int oldTag = oldChildPair.shadowView.tag; - - // Was oldTag already inserted? This indicates a reordering, not just - // a move. The new node has already been inserted, we just need to - // remove the node from its old position now. - auto const insertedIt = newInsertedPairs.find(oldTag); - if (insertedIt != newInsertedPairs.end()) { - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 6: Removing tag that was already inserted: " - << oldIndex << ": [" << oldChildPair.shadowView.tag << "]"; - }); - - removeMutations.push_back(ShadowViewMutation::RemoveMutation( - parentShadowView, oldChildPair.shadowView, oldIndex)); - - // Generate update instruction since we have an iterator ref to the - // new node - auto const &newChildPair = *insertedIt->second; - if (oldChildPair.shadowView != newChildPair.shadowView) { - updateMutations.push_back(ShadowViewMutation::UpdateMutation( - parentShadowView, - oldChildPair.shadowView, - newChildPair.shadowView, - index)); - } - - // Update subtrees - if (oldChildPair.shadowNode != newChildPair.shadowNode) { - auto oldGrandChildPairs = - sliceChildShadowNodeViewPairs(*oldChildPair.shadowNode); - auto newGrandChildPairs = - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode); - calculateShadowViewMutations( - *(newGrandChildPairs.size() ? &downwardMutations - : &destructiveDownwardMutations), - oldChildPair.shadowView, - std::move(oldGrandChildPairs), - std::move(newGrandChildPairs)); - } - - newInsertedPairs.erase(insertedIt); - oldIndex++; - continue; - } - - // Should we generate a delete+remove instruction for the old node? - // If there's an old node and it's not found in the "new" list, we - // generate remove+delete for this node and its subtree. - auto const newIt = newRemainingPairs.find(oldTag); - if (newIt == newRemainingPairs.end()) { - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 8: Removing tag/tree that was not reinserted (may be reparented): " - << oldIndex << ": [" << oldChildPair.shadowView.tag << "]"; - }); - - removeMutations.push_back(ShadowViewMutation::RemoveMutation( - parentShadowView, oldChildPair.shadowView, oldIndex)); - - deleteMutations.push_back( - ShadowViewMutation::DeleteMutation(oldChildPair.shadowView)); - - // We also have to call the algorithm recursively to clean up the - // entire subtree starting from the removed view. - calculateShadowViewMutations( - destructiveDownwardMutations, - oldChildPair.shadowView, - sliceChildShadowNodeViewPairs(*oldChildPair.shadowNode), - {}); - - oldIndex++; - continue; - } - } - - // At this point, oldTag is -1 or is in the new list, and hasn't been - // inserted or matched yet. We're not sure yet if the new node is in the - // old list - generate an insert instruction for the new node. - auto const &newChildPair = newChildPairs[newIndex]; - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 9: Inserting tag/tree that was not yet removed from hierarchy (may be reparented): " - << newIndex << ": [" << newChildPair.shadowView.tag << "]"; - }); - insertMutations.push_back(ShadowViewMutation::InsertMutation( - parentShadowView, newChildPair.shadowView, newIndex)); - newInsertedPairs.insert({newChildPair.shadowView.tag, &newChildPair}); - newIndex++; - } - - // Final step: generate Create instructions for new nodes - for (auto it = newInsertedPairs.begin(); it != newInsertedPairs.end(); - it++) { - // Erased elements of a TinyMap will have a Tag/key of 0 - skip those - // These *should* be removed by the map; there are currently no KNOWN - // cases where TinyMap will do the wrong thing, but there are not yet - // any unit tests explicitly for TinyMap, so this is safer for now. - if (it->first == 0) { - continue; - } - - auto const &newChildPair = *it->second; - - DEBUG_LOGS({ - LOG(ERROR) - << "Differ Branch 9: Inserting tag/tree that was not yet removed from hierarchy (may be reparented): " - << newIndex << ": [" << newChildPair.shadowView.tag << "]"; - }); - - createMutations.push_back( - ShadowViewMutation::CreateMutation(newChildPair.shadowView)); - - calculateShadowViewMutations( - downwardMutations, - newChildPair.shadowView, - {}, - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode)); - } - } - - // All mutations in an optimal order: - std::move( - destructiveDownwardMutations.begin(), - destructiveDownwardMutations.end(), - std::back_inserter(mutations)); - std::move( - updateMutations.begin(), - updateMutations.end(), - std::back_inserter(mutations)); - std::move( - removeMutations.rbegin(), - removeMutations.rend(), - std::back_inserter(mutations)); - std::move( - deleteMutations.begin(), - deleteMutations.end(), - std::back_inserter(mutations)); - std::move( - createMutations.begin(), - createMutations.end(), - std::back_inserter(mutations)); - std::move( - downwardMutations.begin(), - downwardMutations.end(), - std::back_inserter(mutations)); - std::move( - insertMutations.begin(), - insertMutations.end(), - std::back_inserter(mutations)); -} - ShadowViewMutation::List calculateShadowViewMutations( ShadowNode const &oldRootShadowNode, - ShadowNode const &newRootShadowNode, - bool enableReparentingDetection) { + ShadowNode const &newRootShadowNode) { SystraceSection s("calculateShadowViewMutations"); // Root shadow nodes must be belong the same family. @@ -1867,22 +1504,14 @@ ShadowViewMutation::List calculateShadowViewMutations( if (oldRootShadowView != newRootShadowView) { mutations.push_back(ShadowViewMutation::UpdateMutation( - ShadowView(), oldRootShadowView, newRootShadowView, -1)); + oldRootShadowView, newRootShadowView)); } - if (enableReparentingDetection) { - calculateShadowViewMutationsV2( - mutations, - ShadowView(oldRootShadowNode), - sliceChildShadowNodeViewPairsV2(oldRootShadowNode), - sliceChildShadowNodeViewPairsV2(newRootShadowNode)); - } else { - calculateShadowViewMutations( - mutations, - ShadowView(oldRootShadowNode), - sliceChildShadowNodeViewPairs(oldRootShadowNode), - sliceChildShadowNodeViewPairs(newRootShadowNode)); - } + calculateShadowViewMutationsV2( + mutations, + ShadowView(oldRootShadowNode), + sliceChildShadowNodeViewPairsV2(oldRootShadowNode), + sliceChildShadowNodeViewPairsV2(newRootShadowNode)); return mutations; } diff --git a/ReactCommon/react/renderer/mounting/Differentiator.h b/ReactCommon/react/renderer/mounting/Differentiator.h index 762bb43ae6bedd..15ba37f4088696 100644 --- a/ReactCommon/react/renderer/mounting/Differentiator.h +++ b/ReactCommon/react/renderer/mounting/Differentiator.h @@ -22,15 +22,7 @@ enum class ReparentMode { Flatten, Unflatten }; */ ShadowViewMutationList calculateShadowViewMutations( ShadowNode const &oldRootShadowNode, - ShadowNode const &newRootShadowNode, - bool enableReparentingDetection = false); - -/* - * Generates a list of `ShadowViewNodePair`s that represents a layer of a - * flattened view hierarchy. - */ -ShadowViewNodePair::List sliceChildShadowNodeViewPairs( - ShadowNode const &shadowNode); + ShadowNode const &newRootShadowNode); /** * Generates a list of `ShadowViewNodePair`s that represents a layer of a @@ -41,5 +33,12 @@ ShadowViewNodePair::List sliceChildShadowNodeViewPairsV2( ShadowNode const &shadowNode, bool allowFlattened = false); +/* + * Generates a list of `ShadowViewNodePair`s that represents a layer of a + * flattened view hierarchy. This is *only* used by unit tests currently. + */ +ShadowViewNodePair::List sliceChildShadowNodeViewPairsLegacy( + ShadowNode const &shadowNode); + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp b/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp index 7ad2b08e5e5700..d753a43ba9395e 100644 --- a/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp +++ b/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp @@ -19,17 +19,13 @@ namespace facebook { namespace react { -MountingCoordinator::MountingCoordinator( - ShadowTreeRevision baseRevision, - std::weak_ptr delegate, - bool enableReparentingDetection) - : surfaceId_(baseRevision.getRootShadowNode().getSurfaceId()), +MountingCoordinator::MountingCoordinator(ShadowTreeRevision baseRevision) + : surfaceId_(baseRevision.rootShadowNode->getSurfaceId()), baseRevision_(baseRevision), - mountingOverrideDelegate_(delegate), - telemetryController_(*this), - enableReparentingDetection_(enableReparentingDetection) { + telemetryController_(*this) { #ifdef RN_SHADOW_TREE_INTROSPECTION - stubViewTree_ = stubViewTreeFromShadowNode(baseRevision_.getRootShadowNode()); + stubViewTree_ = buildStubViewTreeWithoutUsingDifferentiator( + *baseRevision_.rootShadowNode); #endif } @@ -37,17 +33,15 @@ SurfaceId MountingCoordinator::getSurfaceId() const { return surfaceId_; } -void MountingCoordinator::push(ShadowTreeRevision &&revision) const { +void MountingCoordinator::push(ShadowTreeRevision const &revision) const { { std::lock_guard lock(mutex_); assert( - !lastRevision_.has_value() || - revision.getNumber() != lastRevision_->getNumber()); + !lastRevision_.has_value() || revision.number != lastRevision_->number); - if (!lastRevision_.has_value() || - lastRevision_->getNumber() < revision.getNumber()) { - lastRevision_ = std::move(revision); + if (!lastRevision_.has_value() || lastRevision_->number < revision.number) { + lastRevision_ = revision; } } @@ -60,7 +54,7 @@ void MountingCoordinator::revoke() const { // 1. We need to stop retaining `ShadowNode`s to not prolong their lifetime // to prevent them from overliving `ComponentDescriptor`s. // 2. A possible call to `pullTransaction()` should return empty optional. - baseRevision_.rootShadowNode_.reset(); + baseRevision_.rootShadowNode.reset(); lastRevision_.reset(); } @@ -90,18 +84,15 @@ better::optional MountingCoordinator::pullTransaction() if (lastRevision_.has_value()) { number_++; - auto telemetry = lastRevision_->getTelemetry(); + auto telemetry = lastRevision_->telemetry; telemetry.willDiff(); auto mutations = calculateShadowViewMutations( - baseRevision_.getRootShadowNode(), lastRevision_->getRootShadowNode()); + *baseRevision_.rootShadowNode, *lastRevision_->rootShadowNode); telemetry.didDiff(); - baseRevision_ = std::move(*lastRevision_); - lastRevision_.reset(); - transaction = MountingTransaction{ surfaceId_, number_, std::move(mutations), telemetry}; } @@ -119,10 +110,13 @@ better::optional MountingCoordinator::pullTransaction() mutations = transaction->getMutations(); telemetry = transaction->getTelemetry(); } else { + number_++; telemetry.willLayout(); telemetry.didLayout(); telemetry.willCommit(); telemetry.didCommit(); + telemetry.willDiff(); + telemetry.didDiff(); } transaction = mountingOverrideDelegate->pullTransaction( @@ -141,15 +135,17 @@ better::optional MountingCoordinator::pullTransaction() // If the transaction was overridden, we don't have a model of the shadow // tree therefore we cannot validate the validity of the mutation // instructions. - if (!shouldOverridePullTransaction) { - auto line = std::string{}; + if (!shouldOverridePullTransaction && lastRevision_.has_value()) { + auto stubViewTree = buildStubViewTreeWithoutUsingDifferentiator( + *lastRevision_->rootShadowNode); - auto stubViewTree = - stubViewTreeFromShadowNode(baseRevision_.getRootShadowNode()); + bool treesEqual = stubViewTree_ == stubViewTree; - if (stubViewTree_ != stubViewTree) { + if (!treesEqual) { + // Display debug info + auto line = std::string{}; std::stringstream ssOldTree( - baseRevision_.getRootShadowNode().getDebugDescription()); + baseRevision_.rootShadowNode->getDebugDescription()); while (std::getline(ssOldTree, line, '\n')) { LOG(ERROR) << "Old tree:" << line; } @@ -160,19 +156,21 @@ better::optional MountingCoordinator::pullTransaction() } std::stringstream ssNewTree( - lastRevision_->getRootShadowNode().getDebugDescription()); + lastRevision_->rootShadowNode->getDebugDescription()); while (std::getline(ssNewTree, line, '\n')) { LOG(ERROR) << "New tree:" << line; } } - assert( - (stubViewTree_ == stubViewTree) && - "Incorrect set of mutations detected."); + assert((treesEqual) && "Incorrect set of mutations detected."); } } #endif + if (lastRevision_.has_value()) { + baseRevision_ = std::move(*lastRevision_); + lastRevision_.reset(); + } return transaction; } @@ -180,5 +178,11 @@ TelemetryController const &MountingCoordinator::getTelemetryController() const { return telemetryController_; } +void MountingCoordinator::setMountingOverrideDelegate( + std::weak_ptr delegate) const { + std::lock_guard lock(mutex_); + mountingOverrideDelegate_ = delegate; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/mounting/MountingCoordinator.h b/ReactCommon/react/renderer/mounting/MountingCoordinator.h index 54bb0a3a63d4a7..9356126ed4e884 100644 --- a/ReactCommon/react/renderer/mounting/MountingCoordinator.h +++ b/ReactCommon/react/renderer/mounting/MountingCoordinator.h @@ -43,10 +43,7 @@ class MountingCoordinator final { * The constructor is meant to be used only inside `ShadowTree`, and it's * `public` only to enable using with `std::make_shared<>`. */ - MountingCoordinator( - ShadowTreeRevision baseRevision, - std::weak_ptr delegate, - bool enableReparentingDetection = false); + MountingCoordinator(ShadowTreeRevision baseRevision); /* * Returns the id of the surface that the coordinator belongs to. @@ -85,13 +82,16 @@ class MountingCoordinator final { void updateBaseRevision(ShadowTreeRevision const &baseRevision) const; void resetLatestRevision() const; + void setMountingOverrideDelegate( + std::weak_ptr delegate) const; + /* * Methods from this section are meant to be used by `ShadowTree` only. */ private: friend class ShadowTree; - void push(ShadowTreeRevision &&revision) const; + void push(ShadowTreeRevision const &revision) const; /* * Revokes the last pushed `ShadowTreeRevision`. @@ -110,12 +110,11 @@ class MountingCoordinator final { mutable better::optional lastRevision_{}; mutable MountingTransaction::Number number_{0}; mutable std::condition_variable signal_; - std::weak_ptr mountingOverrideDelegate_; + mutable std::weak_ptr + mountingOverrideDelegate_; TelemetryController telemetryController_; - bool enableReparentingDetection_{false}; // temporary - #ifdef RN_SHADOW_TREE_INTROSPECTION mutable StubViewTree stubViewTree_; // Protected by `mutex_`. #endif diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 1c5cef2ecf964a..fdfa5b990fd815 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -21,6 +21,9 @@ namespace facebook { namespace react { +using CommitStatus = ShadowTree::CommitStatus; +using CommitMode = ShadowTree::CommitMode; + /* * Generates (possibly) a new tree where all nodes with non-obsolete `State` * objects. If all `State` objects in the tree are not obsolete for the moment @@ -219,33 +222,35 @@ ShadowTree::ShadowTree( SurfaceId surfaceId, LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext, - RootComponentDescriptor const &rootComponentDescriptor, - ShadowTreeDelegate const &delegate, - std::weak_ptr mountingOverrideDelegate, - bool enableReparentingDetection) - : surfaceId_(surfaceId), - delegate_(delegate), - enableReparentingDetection_(enableReparentingDetection) { + ShadowTreeDelegate const &delegate) + : surfaceId_(surfaceId), delegate_(delegate) { const auto noopEventEmitter = std::make_shared( nullptr, -1, std::shared_ptr()); + static auto globalRootComponentDescriptor = + std::make_unique( + ComponentDescriptorParameters{ + EventDispatcher::Shared{}, nullptr, nullptr}); + const auto props = std::make_shared( *RootShadowNode::defaultSharedProps(), layoutConstraints, layoutContext); - auto family = rootComponentDescriptor.createFamily( - ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter}, - nullptr); - rootShadowNode_ = std::static_pointer_cast( - rootComponentDescriptor.createShadowNode( + auto const fragment = + ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter}; + auto family = globalRootComponentDescriptor->createFamily(fragment, nullptr); + + auto rootShadowNode = std::static_pointer_cast( + globalRootComponentDescriptor->createShadowNode( ShadowNodeFragment{ /* .props = */ props, }, family)); - mountingCoordinator_ = std::make_shared( - ShadowTreeRevision{rootShadowNode_, 0, {}}, - mountingOverrideDelegate, - enableReparentingDetection); + currentRevision_ = ShadowTreeRevision{ + rootShadowNode, ShadowTreeRevision::Number{0}, TransactionTelemetry{}}; + + mountingCoordinator_ = + std::make_shared(currentRevision_); } ShadowTree::~ShadowTree() { @@ -256,21 +261,46 @@ Tag ShadowTree::getSurfaceId() const { return surfaceId_; } +void ShadowTree::setCommitMode(CommitMode commitMode) const { + auto revision = ShadowTreeRevision{}; + + { + std::unique_lock lock(commitMutex_); + if (commitMode_ == commitMode) { + return; + } + + commitMode_ = commitMode; + revision = currentRevision_; + } + + if (commitMode == CommitMode::Normal) { + mount(revision); + } +} + +CommitMode ShadowTree::getCommitMode() const { + std::shared_lock lock(commitMutex_); + return commitMode_; +} + MountingCoordinator::Shared ShadowTree::getMountingCoordinator() const { return mountingCoordinator_; } -void ShadowTree::commit( +CommitStatus ShadowTree::commit( ShadowTreeCommitTransaction transaction, - bool enableStateReconciliation) const { + CommitOptions commitOptions) const { SystraceSection s("ShadowTree::commit"); int attempts = 0; while (true) { attempts++; - if (tryCommit(transaction, enableStateReconciliation)) { - return; + + auto status = tryCommit(transaction, commitOptions); + if (status != CommitStatus::Failed) { + return status; } // After multiple attempts, we failed to commit the transaction. @@ -279,38 +309,43 @@ void ShadowTree::commit( } } -bool ShadowTree::tryCommit( +CommitStatus ShadowTree::tryCommit( ShadowTreeCommitTransaction transaction, - bool enableStateReconciliation) const { + CommitOptions commitOptions) const { SystraceSection s("ShadowTree::tryCommit"); auto telemetry = TransactionTelemetry{}; telemetry.willCommit(); - RootShadowNode::Shared oldRootShadowNode; + CommitMode commitMode; + auto oldRevision = ShadowTreeRevision{}; + auto newRevision = ShadowTreeRevision{}; { - // Reading `rootShadowNode_` in shared manner. + // Reading `currentRevision_` in shared manner. std::shared_lock lock(commitMutex_); - oldRootShadowNode = rootShadowNode_; + commitMode = commitMode_; + oldRevision = currentRevision_; } - RootShadowNode::Unshared newRootShadowNode = transaction(oldRootShadowNode); + auto oldRootShadowNode = oldRevision.rootShadowNode; + auto newRootShadowNode = transaction(*oldRevision.rootShadowNode); - if (!newRootShadowNode) { - return false; + if (!newRootShadowNode || + (commitOptions.shouldYield && commitOptions.shouldYield())) { + return CommitStatus::Cancelled; } - if (enableStateReconciliation) { + if (commitOptions.enableStateReconciliation) { auto updatedNewRootShadowNode = - progressState(*newRootShadowNode, *oldRootShadowNode); + progressState(*newRootShadowNode, *oldRevision.rootShadowNode); if (updatedNewRootShadowNode) { newRootShadowNode = std::static_pointer_cast(updatedNewRootShadowNode); } } - // Layout nodes + // Layout nodes. std::vector affectedLayoutableNodes{}; affectedLayoutableNodes.reserve(1024); @@ -323,48 +358,65 @@ bool ShadowTree::tryCommit( // Seal the shadow node so it can no longer be mutated newRootShadowNode->sealRecursive(); - auto revisionNumber = ShadowTreeRevision::Number{}; - { - // Updating `rootShadowNode_` in unique manner if it hasn't changed. + // Updating `currentRevision_` in unique manner if it hasn't changed. std::unique_lock lock(commitMutex_); - if (rootShadowNode_ != oldRootShadowNode) { - return false; + if (currentRevision_.number != oldRevision.number) { + return CommitStatus::Failed; } - rootShadowNode_ = newRootShadowNode; + auto newRevisionNumber = oldRevision.number + 1; + + newRootShadowNode = delegate_.shadowTreeWillCommit( + *this, oldRootShadowNode, newRootShadowNode); + + if (!newRootShadowNode || + (commitOptions.shouldYield && commitOptions.shouldYield())) { + return CommitStatus::Cancelled; + } { std::lock_guard dispatchLock(EventEmitter::DispatchMutex()); updateMountedFlag( - oldRootShadowNode->getChildren(), newRootShadowNode->getChildren()); + currentRevision_.rootShadowNode->getChildren(), + newRootShadowNode->getChildren()); } - revisionNumber_++; - revisionNumber = revisionNumber_; + telemetry.didCommit(); + telemetry.setRevisionNumber(newRevisionNumber); + + newRevision = + ShadowTreeRevision{newRootShadowNode, newRevisionNumber, telemetry}; + + currentRevision_ = newRevision; } emitLayoutEvents(affectedLayoutableNodes); - telemetry.didCommit(); - telemetry.setRevisionNumber(revisionNumber); + if (commitMode == CommitMode::Normal) { + mount(newRevision); + } - mountingCoordinator_->push( - ShadowTreeRevision{newRootShadowNode, revisionNumber, telemetry}); + return CommitStatus::Succeeded; +} - notifyDelegatesOfUpdates(); +ShadowTreeRevision ShadowTree::getCurrentRevision() const { + std::shared_lock lock(commitMutex_); + return currentRevision_; +} - return true; +void ShadowTree::mount(ShadowTreeRevision const &revision) const { + mountingCoordinator_->push(revision); + delegate_.shadowTreeDidFinishTransaction(*this, mountingCoordinator_); } void ShadowTree::commitEmptyTree() const { commit( - [](RootShadowNode::Shared const &oldRootShadowNode) - -> RootShadowNode::Unshared { + [](RootShadowNode const &oldRootShadowNode) -> RootShadowNode::Unshared { return std::make_shared( - *oldRootShadowNode, + oldRootShadowNode, ShadowNodeFragment{ /* .props = */ ShadowNodeFragment::propsPlaceholder(), /* .children = */ ShadowNode::emptySharedShadowNodeSharedList(), diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.h b/ReactCommon/react/renderer/mounting/ShadowTree.h index c4f6314b5b744f..c459380e41e77f 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.h +++ b/ReactCommon/react/renderer/mounting/ShadowTree.h @@ -24,13 +24,43 @@ namespace facebook { namespace react { using ShadowTreeCommitTransaction = std::function; + RootShadowNode const &oldRootShadowNode)>; /* * Represents the shadow tree and its lifecycle. */ class ShadowTree final { public: + /* + * Represents a result of a `commit` operation. + */ + enum class CommitStatus { + Succeeded, + Failed, + Cancelled, + }; + + /* + * Represents commits' side-effects propagation mode. + */ + enum class CommitMode { + // Commits' side-effects are observable via `MountingCoordinator`. + // The rendering pipeline fully works end-to-end. + Normal, + + // Commits' side-effects are *not* observable via `MountingCoordinator`. + // The mounting phase is skipped in the rendering pipeline. + Suspended, + }; + + struct CommitOptions { + bool enableStateReconciliation{false}; + + // Called during `tryCommit` phase. Returning true indicates current commit + // should yield to the next commit. + std::function shouldYield; + }; + /* * Creates a new shadow tree instance. */ @@ -38,10 +68,7 @@ class ShadowTree final { SurfaceId surfaceId, LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext, - RootComponentDescriptor const &rootComponentDescriptor, - ShadowTreeDelegate const &delegate, - std::weak_ptr mountingOverrideDelegate, - bool enableReparentingDetection = false); + ShadowTreeDelegate const &delegate); ~ShadowTree(); @@ -50,22 +77,35 @@ class ShadowTree final { */ SurfaceId getSurfaceId() const; + /* + * Sets and gets the commit mode. + * Changing commit mode from `Suspended` to `Normal` will flush all suspended + * changes to `MountingCoordinator`. + */ + void setCommitMode(CommitMode commitMode) const; + CommitMode getCommitMode() const; + /* * Performs commit calling `transaction` function with a `oldRootShadowNode` * and expecting a `newRootShadowNode` as a return value. - * The `transaction` function can abort commit returning `nullptr`. - * Returns `true` if the operation finished successfully. + * The `transaction` function can cancel commit returning `nullptr`. */ - bool tryCommit( + CommitStatus tryCommit( ShadowTreeCommitTransaction transaction, - bool enableStateReconciliation = false) const; + CommitOptions commitOptions = {false}) const; /* * Calls `tryCommit` in a loop until it finishes successfully. */ - void commit( + CommitStatus commit( ShadowTreeCommitTransaction transaction, - bool enableStateReconciliation = false) const; + CommitOptions commitOptions = {false}) const; + + /* + * Returns a `ShadowTreeRevision` representing the momentary state of + * the `ShadowTree`. + */ + ShadowTreeRevision getCurrentRevision() const; /* * Commit an empty tree (a new `RootShadowNode` with no children). @@ -81,19 +121,8 @@ class ShadowTree final { MountingCoordinator::Shared getMountingCoordinator() const; - /* - * Temporary. - * Do not use. - */ - void setEnableReparentingDetection(bool value) { - enableReparentingDetection_ = value; - } - private: - RootShadowNode::Unshared cloneRootShadowNode( - RootShadowNode::Shared const &oldRootShadowNode, - LayoutConstraints const &layoutConstraints, - LayoutContext const &layoutContext) const; + void mount(ShadowTreeRevision const &revision) const; void emitLayoutEvents( std::vector &affectedLayoutableNodes) const; @@ -101,12 +130,10 @@ class ShadowTree final { SurfaceId const surfaceId_; ShadowTreeDelegate const &delegate_; mutable better::shared_mutex commitMutex_; - mutable RootShadowNode::Shared - rootShadowNode_; // Protected by `commitMutex_`. - mutable ShadowTreeRevision::Number revisionNumber_{ - 0}; // Protected by `commitMutex_`. + mutable CommitMode commitMode_{ + CommitMode::Normal}; // Protected by `commitMutex_`. + mutable ShadowTreeRevision currentRevision_; // Protected by `commitMutex_`. MountingCoordinator::Shared mountingCoordinator_; - bool enableReparentingDetection_{false}; }; } // namespace react diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h b/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h index e7e5880e1de9cc..45e762c5314013 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h +++ b/ReactCommon/react/renderer/mounting/ShadowTreeDelegate.h @@ -19,6 +19,17 @@ class ShadowTree; */ class ShadowTreeDelegate { public: + /* + * Called right before a ShadowTree commits a new tree. + * The receiver can alter a new (proposed) shadow tree with another tree + * by returning the altered tree. + * Returning a `nullptr` cancels the commit. + */ + virtual RootShadowNode::Unshared shadowTreeWillCommit( + ShadowTree const &shadowTree, + RootShadowNode::Shared const &oldRootShadowNode, + RootShadowNode::Unshared const &newRootShadowNode) const = 0; + /* * Called right after Shadow Tree commit a new state of the tree. */ diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp index 6966870619bd73..38540ecfd738d5 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp @@ -21,13 +21,18 @@ void ShadowTreeRegistry::add(std::unique_ptr &&shadowTree) const { registry_.emplace(shadowTree->getSurfaceId(), std::move(shadowTree)); } -void ShadowTreeRegistry::remove(SurfaceId surfaceId) const { +std::unique_ptr ShadowTreeRegistry::remove( + SurfaceId surfaceId) const { std::unique_lock lock(mutex_); auto iterator = registry_.find(surfaceId); - if (iterator != registry_.end()) { - registry_.erase(iterator); + if (iterator == registry_.end()) { + return {}; } + + auto shadowTree = std::unique_ptr(iterator->second.release()); + registry_.erase(iterator); + return shadowTree; } bool ShadowTreeRegistry::visit( diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h index 21bcc0fca0729e..e2cee3d8c65b79 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h @@ -34,9 +34,11 @@ class ShadowTreeRegistry final { /* * Removes a `ShadowTree` instance with given `surfaceId` from the registry * and returns it as a result. + * The ownership of the instance is also transferred to the caller. + * Returns `nullptr` if a `ShadowTree` with given `surfaceId` was not found. * Can be called from any thread. */ - void remove(SurfaceId surfaceId) const; + std::unique_ptr remove(SurfaceId surfaceId) const; /* * Finds a `ShadowTree` instance with a given `surfaceId` in the registry and diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRevision.cpp b/ReactCommon/react/renderer/mounting/ShadowTreeRevision.cpp index 36108534f397b2..f56d03ec2023e0 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRevision.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRevision.cpp @@ -6,33 +6,3 @@ */ #include "ShadowTreeRevision.h" - -namespace facebook { -namespace react { - -using Number = ShadowTreeRevision::Number; - -ShadowTreeRevision::ShadowTreeRevision( - ShadowNode::Shared const &rootShadowNode, - Number number, - TransactionTelemetry telemetry) - : rootShadowNode_(rootShadowNode), number_(number), telemetry_(telemetry) {} - -TransactionTelemetry const &ShadowTreeRevision::getTelemetry() const { - return telemetry_; -} - -ShadowNode::Shared ShadowTreeRevision::getSharedRootShadowNode() { - return rootShadowNode_; -} - -ShadowNode const &ShadowTreeRevision::getRootShadowNode() { - return *rootShadowNode_; -} - -Number ShadowTreeRevision::getNumber() const { - return number_; -} - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRevision.h b/ReactCommon/react/renderer/mounting/ShadowTreeRevision.h index 3aa40d1657d98b..d58dbd643288d7 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRevision.h +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRevision.h @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -29,41 +30,12 @@ class ShadowTreeRevision final { */ using Number = int64_t; - /* - * Creates the object with given root shadow node, revision number and - * telemetry. - */ - ShadowTreeRevision( - ShadowNode::Shared const &rootShadowNode, - Number number, - TransactionTelemetry telemetry); - - /* - * Returns telemetry associated with this revision. - */ - TransactionTelemetry const &getTelemetry() const; - - /* - * Methods from this section are meant to be used by - * `MountingOverrideDelegate` only. - */ - public: - ShadowNode const &getRootShadowNode(); - ShadowNode::Shared getSharedRootShadowNode(); - - /* - * Methods from this section are meant to be used by `MountingCoordinator` - * only. - */ - private: + friend class ShadowTree; friend class MountingCoordinator; - Number getNumber() const; - - private: - ShadowNode::Shared rootShadowNode_; - Number number_; - TransactionTelemetry telemetry_; + RootShadowNode::Shared rootShadowNode; + Number number; + TransactionTelemetry telemetry; }; } // namespace react diff --git a/ReactCommon/react/renderer/mounting/ShadowView.cpp b/ReactCommon/react/renderer/mounting/ShadowView.cpp index f717a28fe669f6..32b84c8b26c036 100644 --- a/ReactCommon/react/renderer/mounting/ShadowView.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowView.cpp @@ -22,6 +22,7 @@ static LayoutMetrics layoutMetricsFromShadowNode(ShadowNode const &shadowNode) { ShadowView::ShadowView(const ShadowNode &shadowNode) : componentName(shadowNode.getComponentName()), componentHandle(shadowNode.getComponentHandle()), + surfaceId(shadowNode.getSurfaceId()), tag(shadowNode.getTag()), props(shadowNode.getProps()), eventEmitter(shadowNode.getEventEmitter()), @@ -30,6 +31,7 @@ ShadowView::ShadowView(const ShadowNode &shadowNode) bool ShadowView::operator==(const ShadowView &rhs) const { return std::tie( + this->surfaceId, this->tag, this->componentName, this->props, @@ -37,6 +39,7 @@ bool ShadowView::operator==(const ShadowView &rhs) const { this->layoutMetrics, this->state) == std::tie( + rhs.surfaceId, rhs.tag, rhs.componentName, rhs.props, @@ -59,6 +62,7 @@ std::vector getDebugProps( ShadowView const &object, DebugStringConvertibleOptions options) { return { + {"surfaceId", getDebugDescription(object.surfaceId, options)}, {"tag", getDebugDescription(object.tag, options)}, {"props", getDebugDescription(object.props, options)}, {"eventEmitter", getDebugDescription(object.eventEmitter, options)}, diff --git a/ReactCommon/react/renderer/mounting/ShadowView.h b/ReactCommon/react/renderer/mounting/ShadowView.h index a481941d7eba2f..7d0a7617a68a75 100644 --- a/ReactCommon/react/renderer/mounting/ShadowView.h +++ b/ReactCommon/react/renderer/mounting/ShadowView.h @@ -40,6 +40,7 @@ struct ShadowView final { ComponentName componentName{}; ComponentHandle componentHandle{}; + SurfaceId surfaceId{}; Tag tag{}; Props::Shared props{}; EventEmitter::Shared eventEmitter{}; @@ -70,7 +71,7 @@ struct ShadowViewNodePair final { bool flattened{false}; bool isConcreteView{true}; - int mountIndex{0}; + size_t mountIndex{0}; bool inOtherTree{false}; diff --git a/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp b/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp index 9b8d966a3c1129..dbf4afd227c935 100644 --- a/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp @@ -57,16 +57,14 @@ ShadowViewMutation ShadowViewMutation::RemoveMutation( } ShadowViewMutation ShadowViewMutation::UpdateMutation( - ShadowView parentShadowView, ShadowView oldChildShadowView, - ShadowView newChildShadowView, - int index) { + ShadowView newChildShadowView) { return { /* .type = */ Update, - /* .parentShadowView = */ parentShadowView, + /* .parentShadowView = */ {}, /* .oldChildShadowView = */ oldChildShadowView, /* .newChildShadowView = */ newChildShadowView, - /* .index = */ index, + /* .index = */ -1, }; } diff --git a/ReactCommon/react/renderer/mounting/ShadowViewMutation.h b/ReactCommon/react/renderer/mounting/ShadowViewMutation.h index 07ee6bcaf7e482..3bd0067d5fdcbc 100644 --- a/ReactCommon/react/renderer/mounting/ShadowViewMutation.h +++ b/ReactCommon/react/renderer/mounting/ShadowViewMutation.h @@ -55,10 +55,8 @@ struct ShadowViewMutation final { * Creates and returns an `Update` mutation. */ static ShadowViewMutation UpdateMutation( - ShadowView parentShadowView, ShadowView oldChildShadowView, - ShadowView newChildShadowView, - int index); + ShadowView newChildShadowView); #pragma mark - Type @@ -70,7 +68,7 @@ struct ShadowViewMutation final { ShadowView parentShadowView = {}; ShadowView oldChildShadowView = {}; ShadowView newChildShadowView = {}; - int index = {}; + int index = -1; }; using ShadowViewMutationList = std::vector; diff --git a/ReactCommon/react/renderer/mounting/StubView.cpp b/ReactCommon/react/renderer/mounting/StubView.cpp index f476de31184899..737fbb0286706f 100644 --- a/ReactCommon/react/renderer/mounting/StubView.cpp +++ b/ReactCommon/react/renderer/mounting/StubView.cpp @@ -10,9 +10,23 @@ namespace facebook { namespace react { +StubView::operator ShadowView() const { + auto shadowView = ShadowView{}; + shadowView.componentName = componentName; + shadowView.componentHandle = componentHandle; + shadowView.surfaceId = surfaceId; + shadowView.tag = tag; + shadowView.props = props; + shadowView.eventEmitter = eventEmitter; + shadowView.layoutMetrics = layoutMetrics; + shadowView.state = state; + return shadowView; +} + void StubView::update(ShadowView const &shadowView) { componentName = shadowView.componentName; componentHandle = shadowView.componentHandle; + surfaceId = shadowView.surfaceId; tag = shadowView.tag; props = shadowView.props; eventEmitter = shadowView.eventEmitter; @@ -33,14 +47,15 @@ bool operator!=(StubView const &lhs, StubView const &rhs) { std::string getDebugName(StubView const &stubView) { return std::string{"Stub"} + - std::string{stubView.componentHandle ? stubView.componentName - : "[invalid]"}; + std::string{ + stubView.componentHandle ? stubView.componentName : "[invalid]"}; } std::vector getDebugProps( StubView const &stubView, DebugStringConvertibleOptions options) { return { + {"surfaceId", getDebugDescription(stubView.surfaceId, options)}, {"tag", getDebugDescription(stubView.tag, options)}, {"props", getDebugDescription(stubView.props, options)}, {"eventEmitter", getDebugDescription(stubView.eventEmitter, options)}, diff --git a/ReactCommon/react/renderer/mounting/StubView.h b/ReactCommon/react/renderer/mounting/StubView.h index 8546baa157aee5..ca433c953b3020 100644 --- a/ReactCommon/react/renderer/mounting/StubView.h +++ b/ReactCommon/react/renderer/mounting/StubView.h @@ -25,10 +25,13 @@ class StubView final { StubView() = default; StubView(StubView const &stubView) = default; + operator ShadowView() const; + void update(ShadowView const &shadowView); ComponentName componentName; ComponentHandle componentHandle; + SurfaceId surfaceId; Tag tag; SharedProps props; SharedEventEmitter eventEmitter; diff --git a/ReactCommon/react/renderer/mounting/StubViewTree.cpp b/ReactCommon/react/renderer/mounting/StubViewTree.cpp index fc68777f349fda..481974997d1f53 100644 --- a/ReactCommon/react/renderer/mounting/StubViewTree.cpp +++ b/ReactCommon/react/renderer/mounting/StubViewTree.cpp @@ -38,30 +38,27 @@ StubView const &StubViewTree::getRootStubView() const { return *registry.at(rootTag); } -/** - * ignoreDuplicateCreates: when stubs generates "fake" mutation instructions, in - * some cases it can produce too many "create" instructions. We ignore - * duplicates and treat them as noops. In the case of verifying actual diffing, - * that assert is left on. - * - * @param mutations - * @param ignoreDuplicateCreates - */ -void StubViewTree::mutate( - ShadowViewMutationList const &mutations, - bool ignoreDuplicateCreates) { +StubView const &StubViewTree::getStubView(Tag tag) const { + return *registry.at(tag); +} + +size_t StubViewTree::size() const { + return registry.size(); +} + +void StubViewTree::mutate(ShadowViewMutationList const &mutations) { STUB_VIEW_LOG({ LOG(ERROR) << "StubView: Mutating Begin"; }); for (auto const &mutation : mutations) { switch (mutation.type) { case ShadowViewMutation::Create: { STUB_VIEW_ASSERT(mutation.parentShadowView == ShadowView{}); STUB_VIEW_ASSERT(mutation.oldChildShadowView == ShadowView{}); + STUB_VIEW_ASSERT(mutation.newChildShadowView.props); auto stubView = std::make_shared(); + stubView->update(mutation.newChildShadowView); auto tag = mutation.newChildShadowView.tag; STUB_VIEW_LOG({ LOG(ERROR) << "StubView: Create: " << tag; }); - if (!ignoreDuplicateCreates) { - STUB_VIEW_ASSERT(registry.find(tag) == registry.end()); - } + STUB_VIEW_ASSERT(registry.find(tag) == registry.end()); registry[tag] = stubView; break; } @@ -72,7 +69,12 @@ void StubViewTree::mutate( STUB_VIEW_ASSERT(mutation.parentShadowView == ShadowView{}); STUB_VIEW_ASSERT(mutation.newChildShadowView == ShadowView{}); auto tag = mutation.oldChildShadowView.tag; + /* Disable this assert until T76057501 is resolved. STUB_VIEW_ASSERT(registry.find(tag) != registry.end()); + auto stubView = registry[tag]; + STUB_VIEW_ASSERT( + (ShadowView)(*stubView) == mutation.oldChildShadowView); + */ registry.erase(tag); break; } @@ -83,13 +85,15 @@ void StubViewTree::mutate( STUB_VIEW_ASSERT(registry.find(parentTag) != registry.end()); auto parentStubView = registry[parentTag]; auto childTag = mutation.newChildShadowView.tag; - STUB_VIEW_LOG({ - LOG(ERROR) << "StubView: Insert: " << childTag << " into " - << parentTag << " at " << mutation.index; - }); STUB_VIEW_ASSERT(registry.find(childTag) != registry.end()); auto childStubView = registry[childTag]; childStubView->update(mutation.newChildShadowView); + STUB_VIEW_LOG({ + LOG(ERROR) << "StubView: Insert: " << childTag << " into " + << parentTag << " at " << mutation.index << "(" + << parentStubView->children.size() << " children)"; + }); + STUB_VIEW_ASSERT(parentStubView->children.size() >= mutation.index); parentStubView->children.insert( parentStubView->children.begin() + mutation.index, childStubView); break; @@ -106,6 +110,7 @@ void StubViewTree::mutate( << parentTag << " at index " << mutation.index << " with " << parentStubView->children.size() << " children"; }); + STUB_VIEW_ASSERT(parentStubView->children.size() > mutation.index); STUB_VIEW_ASSERT(registry.find(childTag) != registry.end()); auto childStubView = registry[childTag]; bool childIsCorrect = @@ -113,9 +118,13 @@ void StubViewTree::mutate( parentStubView->children[mutation.index]->tag == childStubView->tag; STUB_VIEW_LOG({ std::string strChildList = ""; + int i = 0; for (auto const &child : parentStubView->children) { + strChildList.append(std::to_string(i)); + strChildList.append(":"); strChildList.append(std::to_string(child->tag)); strChildList.append(", "); + i++; } LOG(ERROR) << "StubView: BEFORE REMOVE: Children of " << parentTag << ": " << strChildList; @@ -130,12 +139,18 @@ void StubViewTree::mutate( STUB_VIEW_LOG({ LOG(ERROR) << "StubView: Update: " << mutation.newChildShadowView.tag; }); + STUB_VIEW_ASSERT(mutation.oldChildShadowView.tag != 0); + STUB_VIEW_ASSERT(mutation.newChildShadowView.tag != 0); + STUB_VIEW_ASSERT(mutation.newChildShadowView.props); STUB_VIEW_ASSERT( mutation.newChildShadowView.tag == mutation.oldChildShadowView.tag); STUB_VIEW_ASSERT( registry.find(mutation.newChildShadowView.tag) != registry.end()); - auto stubView = registry[mutation.newChildShadowView.tag]; - stubView->update(mutation.newChildShadowView); + auto oldStubView = registry[mutation.newChildShadowView.tag]; + STUB_VIEW_ASSERT(oldStubView->tag != 0); + STUB_VIEW_ASSERT( + (ShadowView)(*oldStubView) == mutation.oldChildShadowView); + oldStubView->update(mutation.newChildShadowView); break; } } diff --git a/ReactCommon/react/renderer/mounting/StubViewTree.h b/ReactCommon/react/renderer/mounting/StubViewTree.h index 3dceaba3dc7e97..c3ce25c8fdf10e 100644 --- a/ReactCommon/react/renderer/mounting/StubViewTree.h +++ b/ReactCommon/react/renderer/mounting/StubViewTree.h @@ -21,14 +21,26 @@ class StubViewTree { StubViewTree() = default; StubViewTree(ShadowView const &shadowView); - void mutate( - ShadowViewMutationList const &mutations, - bool ignoreDuplicateCreates = false); + void mutate(ShadowViewMutationList const &mutations); StubView const &getRootStubView() const; + /* + * Returns a view with given tag. + */ + StubView const &getStubView(Tag tag) const; + + /* + * Returns the total amount of views in the tree. + */ + size_t size() const; + + private: Tag rootTag; std::unordered_map registry{}; + + friend bool operator==(StubViewTree const &lhs, StubViewTree const &rhs); + friend bool operator!=(StubViewTree const &lhs, StubViewTree const &rhs); }; bool operator==(StubViewTree const &lhs, StubViewTree const &rhs); diff --git a/ReactCommon/react/renderer/mounting/TelemetryController.cpp b/ReactCommon/react/renderer/mounting/TelemetryController.cpp index a39989cb69d5ef..b058bebcae8ae4 100644 --- a/ReactCommon/react/renderer/mounting/TelemetryController.cpp +++ b/ReactCommon/react/renderer/mounting/TelemetryController.cpp @@ -19,8 +19,7 @@ TelemetryController::TelemetryController( bool TelemetryController::pullTransaction( std::function willMount, std::function doMount, - std::function didMount) const - noexcept { + std::function didMount) const { auto optional = mountingCoordinator_.pullTransaction(); if (!optional.has_value()) { return false; diff --git a/ReactCommon/react/renderer/mounting/TelemetryController.h b/ReactCommon/react/renderer/mounting/TelemetryController.h index 3532072a155dd5..c0b3d28ddd2513 100644 --- a/ReactCommon/react/renderer/mounting/TelemetryController.h +++ b/ReactCommon/react/renderer/mounting/TelemetryController.h @@ -45,8 +45,7 @@ class TelemetryController final { bool pullTransaction( std::function willMount, std::function doMount, - std::function didMount) const - noexcept; + std::function didMount) const; private: MountingCoordinator const &mountingCoordinator_; diff --git a/ReactCommon/react/renderer/mounting/TransactionTelemetry.cpp b/ReactCommon/react/renderer/mounting/TransactionTelemetry.cpp index f1ac3f659feaa7..d81ed7c6bf44b1 100644 --- a/ReactCommon/react/renderer/mounting/TransactionTelemetry.cpp +++ b/ReactCommon/react/renderer/mounting/TransactionTelemetry.cpp @@ -12,18 +12,18 @@ namespace facebook { namespace react { -using ThreadLocalTransactionTelemetry = ThreadStorage; +thread_local TransactionTelemetry *threadLocalTransactionTelemetry = nullptr; TransactionTelemetry *TransactionTelemetry::threadLocalTelemetry() { - return ThreadLocalTransactionTelemetry::getInstance().get().value_or(nullptr); + return threadLocalTransactionTelemetry; } void TransactionTelemetry::setAsThreadLocal() { - ThreadLocalTransactionTelemetry::getInstance().set(this); + threadLocalTransactionTelemetry = this; } void TransactionTelemetry::unsetAsThreadLocal() { - ThreadLocalTransactionTelemetry::getInstance().set(nullptr); + threadLocalTransactionTelemetry = nullptr; } void TransactionTelemetry::willCommit() { diff --git a/ReactCommon/react/renderer/mounting/TransactionTelemetry.h b/ReactCommon/react/renderer/mounting/TransactionTelemetry.h index b71e10bae33e78..88ef2a23b0e3c4 100644 --- a/ReactCommon/react/renderer/mounting/TransactionTelemetry.h +++ b/ReactCommon/react/renderer/mounting/TransactionTelemetry.h @@ -11,7 +11,6 @@ #include #include -#include namespace facebook { namespace react { diff --git a/ReactCommon/react/renderer/mounting/stubs.cpp b/ReactCommon/react/renderer/mounting/stubs.cpp index 47ce20e9e2c400..9a87c4987dafca 100644 --- a/ReactCommon/react/renderer/mounting/stubs.cpp +++ b/ReactCommon/react/renderer/mounting/stubs.cpp @@ -14,6 +14,25 @@ namespace facebook { namespace react { +/* + * Sorting comparator for `reorderInPlaceIfNeeded`. + */ +static bool shouldFirstPairComesBeforeSecondOne( + ShadowViewNodePair const &lhs, + ShadowViewNodePair const &rhs) noexcept { + return lhs.shadowNode->getOrderIndex() < rhs.shadowNode->getOrderIndex(); +} + +/* + * Reorders pairs in-place based on `orderIndex` using a stable sort algorithm. + */ +static void reorderInPlaceIfNeeded(ShadowViewNodePair::List &pairs) noexcept { + // This is a simplified version of the function intentionally copied from + // `Differentiator.cpp`. + std::stable_sort( + pairs.begin(), pairs.end(), &shouldFirstPairComesBeforeSecondOne); +} + /* * Generates `create` and `insert` instructions recursively traversing a shadow * tree. @@ -23,7 +42,10 @@ namespace react { static void calculateShadowViewMutationsForNewTree( ShadowViewMutation::List &mutations, ShadowView const &parentShadowView, - ShadowViewNodePair::List const &newChildPairs) { + ShadowViewNodePair::List newChildPairs) { + // Sorting pairs based on `orderIndex` if needed. + reorderInPlaceIfNeeded(newChildPairs); + for (auto index = 0; index < newChildPairs.size(); index++) { auto const &newChildPair = newChildPairs[index]; @@ -32,29 +54,44 @@ static void calculateShadowViewMutationsForNewTree( mutations.push_back(ShadowViewMutation::InsertMutation( parentShadowView, newChildPair.shadowView, index)); - auto const newGrandChildPairs = - sliceChildShadowNodeViewPairs(*newChildPair.shadowNode); + auto newGrandChildPairs = + sliceChildShadowNodeViewPairsLegacy(*newChildPair.shadowNode); calculateShadowViewMutationsForNewTree( mutations, newChildPair.shadowView, newGrandChildPairs); } } -StubViewTree stubViewTreeFromShadowNode(ShadowNode const &rootShadowNode) { +StubViewTree buildStubViewTreeWithoutUsingDifferentiator( + ShadowNode const &rootShadowNode) { auto mutations = ShadowViewMutation::List{}; mutations.reserve(256); calculateShadowViewMutationsForNewTree( mutations, ShadowView(rootShadowNode), - sliceChildShadowNodeViewPairs(rootShadowNode)); + sliceChildShadowNodeViewPairsLegacy(rootShadowNode)); + + auto emptyRootShadowNode = rootShadowNode.clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + ShadowNode::emptySharedShadowNodeSharedList()}); + + auto stubViewTree = StubViewTree(ShadowView(*emptyRootShadowNode)); + stubViewTree.mutate(mutations); + return stubViewTree; +} + +StubViewTree buildStubViewTreeUsingDifferentiator( + ShadowNode const &rootShadowNode) { + auto emptyRootShadowNode = rootShadowNode.clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + ShadowNode::emptySharedShadowNodeSharedList()}); - auto emptyRootShadowNode = rootShadowNode.clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - ShadowNode::emptySharedShadowNodeSharedList()}); + auto mutations = + calculateShadowViewMutations(*emptyRootShadowNode, rootShadowNode); auto stubViewTree = StubViewTree(ShadowView(*emptyRootShadowNode)); - stubViewTree.mutate(mutations, true); + stubViewTree.mutate(mutations); return stubViewTree; } diff --git a/ReactCommon/react/renderer/mounting/stubs.h b/ReactCommon/react/renderer/mounting/stubs.h index 8a7b564c081073..73ac7b1d8ecccf 100644 --- a/ReactCommon/react/renderer/mounting/stubs.h +++ b/ReactCommon/react/renderer/mounting/stubs.h @@ -14,7 +14,19 @@ namespace facebook { namespace react { -StubViewTree stubViewTreeFromShadowNode(ShadowNode const &rootShadowNode); +/* + * Builds a ShadowView tree from given root ShadowNode using custom built-in + * implementation (*without* using Differentiator). + */ +StubViewTree buildStubViewTreeWithoutUsingDifferentiator( + ShadowNode const &rootShadowNode); + +/* + * Builds a ShadowView tree from given root ShadowNode using Differentiator by + * generating mutation instructions between empty and final trees. + */ +StubViewTree buildStubViewTreeUsingDifferentiator( + ShadowNode const &rootShadowNode); } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/mounting/tests/MountingTest.cpp b/ReactCommon/react/renderer/mounting/tests/MountingTest.cpp index 172134fa39c5e6..6a2d0034a27fc1 100644 --- a/ReactCommon/react/renderer/mounting/tests/MountingTest.cpp +++ b/ReactCommon/react/renderer/mounting/tests/MountingTest.cpp @@ -44,8 +44,8 @@ static ShadowNode::Shared makeNode( : nonFlattenedDefaultProps(componentDescriptor); return componentDescriptor.createShadowNode( - ShadowNodeFragment{props, - std::make_shared(children)}, + ShadowNodeFragment{ + props, std::make_shared(children)}, componentDescriptor.createFamily({tag, SurfaceId(1), nullptr}, nullptr)); } @@ -80,8 +80,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) { // Applying size constraints. emptyRootNode = emptyRootNode->clone( - LayoutConstraints{Size{512, 0}, - Size{512, std::numeric_limits::infinity()}}, + LayoutConstraints{ + Size{512, 0}, Size{512, std::numeric_limits::infinity()}}, LayoutContext{}); auto childA = makeNode(viewComponentDescriptor, 100, {}); @@ -101,22 +101,23 @@ TEST(MountingTest, testReorderingInstructionGeneration) { // Construct "identical" shadow nodes: they differ only in children. auto shadowNodeV1 = viewComponentDescriptor.createShadowNode( - ShadowNodeFragment{generateDefaultProps(viewComponentDescriptor), - std::make_shared( - SharedShadowNodeList{childB, childC, childD})}, + ShadowNodeFragment{ + generateDefaultProps(viewComponentDescriptor), + std::make_shared( + SharedShadowNodeList{childB, childC, childD})}, family); auto shadowNodeV2 = shadowNodeV1->clone(ShadowNodeFragment{ generateDefaultProps(viewComponentDescriptor), std::make_shared( SharedShadowNodeList{childA, childB, childC, childD})}); - auto shadowNodeV3 = shadowNodeV2->clone( - ShadowNodeFragment{generateDefaultProps(viewComponentDescriptor), - std::make_shared( - SharedShadowNodeList{childB, childC, childD})}); - auto shadowNodeV4 = shadowNodeV3->clone( - ShadowNodeFragment{generateDefaultProps(viewComponentDescriptor), - std::make_shared( - SharedShadowNodeList{childB, childD, childE})}); + auto shadowNodeV3 = shadowNodeV2->clone(ShadowNodeFragment{ + generateDefaultProps(viewComponentDescriptor), + std::make_shared( + SharedShadowNodeList{childB, childC, childD})}); + auto shadowNodeV4 = shadowNodeV3->clone(ShadowNodeFragment{ + generateDefaultProps(viewComponentDescriptor), + std::make_shared( + SharedShadowNodeList{childB, childD, childE})}); auto shadowNodeV5 = shadowNodeV4->clone(ShadowNodeFragment{ generateDefaultProps(viewComponentDescriptor), std::make_shared( @@ -127,52 +128,53 @@ TEST(MountingTest, testReorderingInstructionGeneration) { childB, childA, childD, childF, childE, childC})}); auto shadowNodeV7 = shadowNodeV6->clone(ShadowNodeFragment{ generateDefaultProps(viewComponentDescriptor), - std::make_shared(SharedShadowNodeList{childF, - childE, - childC, - childD, - childG, - childH, - childI, - childJ, - childK})}); + std::make_shared(SharedShadowNodeList{ + childF, + childE, + childC, + childD, + childG, + childH, + childI, + childJ, + childK})}); // Injecting a tree into the root node. auto rootNodeV1 = std::static_pointer_cast( - emptyRootNode->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV1})})); + emptyRootNode->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV1})})); auto rootNodeV2 = std::static_pointer_cast( - rootNodeV1->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV2})})); + rootNodeV1->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV2})})); auto rootNodeV3 = std::static_pointer_cast( - rootNodeV2->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV3})})); + rootNodeV2->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV3})})); auto rootNodeV4 = std::static_pointer_cast( - rootNodeV3->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV4})})); + rootNodeV3->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV4})})); auto rootNodeV5 = std::static_pointer_cast( - rootNodeV4->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV5})})); + rootNodeV4->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV5})})); auto rootNodeV6 = std::static_pointer_cast( - rootNodeV5->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV6})})); + rootNodeV5->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV6})})); auto rootNodeV7 = std::static_pointer_cast( - rootNodeV6->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV7})})); + rootNodeV6->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV7})})); // Layout std::vector affectedLayoutableNodesV1{}; @@ -240,8 +242,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { }*/ // Calculating mutations. - auto mutations1 = - calculateShadowViewMutations(*rootNodeV1, *rootNodeV2, false); + auto mutations1 = calculateShadowViewMutations(*rootNodeV1, *rootNodeV2); // The order and exact mutation instructions here may change at any time. // This test just ensures that any changes are intentional. @@ -257,8 +258,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { EXPECT_TRUE(mutations1[1].index == 0); // Calculating mutations. - auto mutations2 = - calculateShadowViewMutations(*rootNodeV2, *rootNodeV3, false); + auto mutations2 = calculateShadowViewMutations(*rootNodeV2, *rootNodeV3); // The order and exact mutation instructions here may change at any time. // This test just ensures that any changes are intentional. @@ -274,8 +274,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { EXPECT_TRUE(mutations2[1].oldChildShadowView.tag == 100); // Calculating mutations. - auto mutations3 = - calculateShadowViewMutations(*rootNodeV3, *rootNodeV4, false); + auto mutations3 = calculateShadowViewMutations(*rootNodeV3, *rootNodeV4); LOG(ERROR) << "Num mutations IN OLD TEST mutations3: " << mutations3.size(); // The order and exact mutation instructions here may change at any time. @@ -297,8 +296,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { EXPECT_TRUE(mutations3[3].index == 2); // Calculating mutations. - auto mutations4 = - calculateShadowViewMutations(*rootNodeV4, *rootNodeV5, false); + auto mutations4 = calculateShadowViewMutations(*rootNodeV4, *rootNodeV5); // The order and exact mutation instructions here may change at any time. // This test just ensures that any changes are intentional. @@ -323,8 +321,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { EXPECT_TRUE(mutations4[5].newChildShadowView.tag == 102); EXPECT_TRUE(mutations4[5].index == 3); - auto mutations5 = - calculateShadowViewMutations(*rootNodeV5, *rootNodeV6, false); + auto mutations5 = calculateShadowViewMutations(*rootNodeV5, *rootNodeV6); // The order and exact mutation instructions here may change at any time. // This test just ensures that any changes are intentional. @@ -343,8 +340,7 @@ TEST(MountingTest, testReorderingInstructionGeneration) { EXPECT_TRUE(mutations5[3].newChildShadowView.tag == 105); EXPECT_TRUE(mutations5[3].index == 3); - auto mutations6 = - calculateShadowViewMutations(*rootNodeV6, *rootNodeV7, false); + auto mutations6 = calculateShadowViewMutations(*rootNodeV6, *rootNodeV7); // The order and exact mutation instructions here may change at any time. // This test just ensures that any changes are intentional. @@ -389,8 +385,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { // Applying size constraints. emptyRootNode = emptyRootNode->clone( - LayoutConstraints{Size{512, 0}, - Size{512, std::numeric_limits::infinity()}}, + LayoutConstraints{ + Size{512, 0}, Size{512, std::numeric_limits::infinity()}}, LayoutContext{}); auto childA = makeNode(viewComponentDescriptor, 100, {}); @@ -541,30 +537,30 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { // Injecting a tree into the root node. auto rootNodeV1 = std::static_pointer_cast( - emptyRootNode->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV1})})); + emptyRootNode->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV1})})); auto rootNodeV2 = std::static_pointer_cast( - rootNodeV1->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV2})})); + rootNodeV1->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV2})})); auto rootNodeV3 = std::static_pointer_cast( - rootNodeV2->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV3})})); + rootNodeV2->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV3})})); auto rootNodeV4 = std::static_pointer_cast( - rootNodeV3->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV4})})); + rootNodeV3->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV4})})); auto rootNodeV5 = std::static_pointer_cast( - rootNodeV4->ShadowNode::clone( - ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(), - std::make_shared( - SharedShadowNodeList{shadowNodeV5})})); + rootNodeV4->ShadowNode::clone(ShadowNodeFragment{ + ShadowNodeFragment::propsPlaceholder(), + std::make_shared( + SharedShadowNodeList{shadowNodeV5})})); // Layout std::vector affectedLayoutableNodesV1{}; @@ -598,8 +594,7 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { rootNodeV5->sealRecursive(); // Calculating mutations. - auto mutations1 = - calculateShadowViewMutations(*rootNodeV1, *rootNodeV2, true); + auto mutations1 = calculateShadowViewMutations(*rootNodeV1, *rootNodeV2); EXPECT_EQ(mutations1.size(), 5); EXPECT_EQ(mutations1[0].type, ShadowViewMutation::Update); @@ -613,8 +608,7 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { EXPECT_EQ(mutations1[4].type, ShadowViewMutation::Insert); EXPECT_EQ(mutations1[4].newChildShadowView.tag, 1000); - auto mutations2 = - calculateShadowViewMutations(*rootNodeV2, *rootNodeV3, true); + auto mutations2 = calculateShadowViewMutations(*rootNodeV2, *rootNodeV3); EXPECT_EQ(mutations2.size(), 5); EXPECT_EQ(mutations2[0].type, ShadowViewMutation::Update); @@ -630,8 +624,7 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { EXPECT_EQ(mutations2[4].type, ShadowViewMutation::Insert); EXPECT_EQ(mutations2[4].newChildShadowView.tag, 1000); - auto mutations3 = - calculateShadowViewMutations(*rootNodeV3, *rootNodeV4, true); + auto mutations3 = calculateShadowViewMutations(*rootNodeV3, *rootNodeV4); // between these two trees, lots of new nodes are created and inserted - this // is all correct, and this is the minimal amount of mutations @@ -668,8 +661,7 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) { EXPECT_EQ(mutations3[14].type, ShadowViewMutation::Insert); EXPECT_EQ(mutations3[14].newChildShadowView.tag, 1000); - auto mutations4 = - calculateShadowViewMutations(*rootNodeV4, *rootNodeV5, true); + auto mutations4 = calculateShadowViewMutations(*rootNodeV4, *rootNodeV5); EXPECT_EQ(mutations4.size(), 9); EXPECT_EQ(mutations4[0].type, ShadowViewMutation::Update); diff --git a/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp b/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp index 851231da950841..865fa8e11cadaa 100644 --- a/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp +++ b/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp @@ -5,12 +5,15 @@ * LICENSE file in the root directory of this source tree. */ +#include + #include #include #include #include #include +#include #include #include "Entropy.h" @@ -23,8 +26,7 @@ static void testShadowNodeTreeLifeCycle( uint_fast32_t seed, int treeSize, int repeats, - int stages, - bool useFlattener) { + int stages) { auto entropy = seed == 0 ? Entropy() : Entropy(seed); auto eventDispatcher = EventDispatcher::Shared{}; @@ -55,8 +57,8 @@ static void testShadowNodeTreeLifeCycle( // Applying size constraints. emptyRootNode = emptyRootNode->clone( - LayoutConstraints{Size{512, 0}, - Size{512, std::numeric_limits::infinity()}}, + LayoutConstraints{ + Size{512, 0}, Size{512, std::numeric_limits::infinity()}}, LayoutContext{}); // Generation of a random tree. @@ -71,7 +73,7 @@ static void testShadowNodeTreeLifeCycle( SharedShadowNodeList{singleRootChildNode})})); // Building an initial view hierarchy. - auto viewTree = stubViewTreeFromShadowNode(*emptyRootNode); + auto viewTree = buildStubViewTreeWithoutUsingDifferentiator(*emptyRootNode); viewTree.mutate( calculateShadowViewMutations(*emptyRootNode, *currentRootNode)); @@ -99,14 +101,38 @@ static void testShadowNodeTreeLifeCycle( allNodes.push_back(nextRootNode); // Calculating mutations. - auto mutations = calculateShadowViewMutations( - *currentRootNode, *nextRootNode, useFlattener); + auto mutations = + calculateShadowViewMutations(*currentRootNode, *nextRootNode); + + // Make sure that in a single frame, a DELETE for a + // view is not followed by a CREATE for the same view. + { + std::vector deletedTags{}; + for (auto const &mutation : mutations) { + if (mutation.type == ShadowViewMutation::Type::Delete) { + deletedTags.push_back(mutation.oldChildShadowView.tag); + } + } + for (auto const &mutation : mutations) { + if (mutation.type == ShadowViewMutation::Type::Create) { + if (std::find( + deletedTags.begin(), + deletedTags.end(), + mutation.newChildShadowView.tag) != deletedTags.end()) { + LOG(ERROR) << "Deleted tag was recreated in mutations list: [" + << mutation.newChildShadowView.tag << "]"; + FAIL(); + } + } + } + } // Mutating the view tree. viewTree.mutate(mutations); // Building a view tree to compare with. - auto rebuiltViewTree = stubViewTreeFromShadowNode(*nextRootNode); + auto rebuiltViewTree = + buildStubViewTreeWithoutUsingDifferentiator(*nextRootNode); // Comparing the newly built tree with the updated one. if (rebuiltViewTree != viewTree) { @@ -148,31 +174,12 @@ static void testShadowNodeTreeLifeCycle( using namespace facebook::react; -TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMoves) { - testShadowNodeTreeLifeCycle( - /* seed */ 0, - /* size */ 512, - /* repeats */ 32, - /* stages */ 32, - false); -} - -TEST(MountingTest, stableSmallerTreeMoreIterationsOptimizedMoves) { - testShadowNodeTreeLifeCycle( - /* seed */ 0, - /* size */ 16, - /* repeats */ 512, - /* stages */ 32, - false); -} - TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMovesFlattener) { testShadowNodeTreeLifeCycle( /* seed */ 0, /* size */ 512, /* repeats */ 32, - /* stages */ 32, - true); + /* stages */ 32); } TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMovesFlattener2) { @@ -180,8 +187,7 @@ TEST(MountingTest, stableBiggerTreeFewerIterationsOptimizedMovesFlattener2) { /* seed */ 1, /* size */ 512, /* repeats */ 32, - /* stages */ 32, - true); + /* stages */ 32); } TEST(MountingTest, stableSmallerTreeMoreIterationsOptimizedMovesFlattener) { @@ -189,6 +195,5 @@ TEST(MountingTest, stableSmallerTreeMoreIterationsOptimizedMovesFlattener) { /* seed */ 0, /* size */ 16, /* repeats */ 512, - /* stages */ 32, - true); + /* stages */ 32); } diff --git a/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp new file mode 100644 index 00000000000000..521d3135d1311f --- /dev/null +++ b/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -0,0 +1,787 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +class StackingContextTest : public ::testing::Test { + protected: + ComponentBuilder builder_; + std::shared_ptr rootShadowNode_; + std::shared_ptr nodeA_; + std::shared_ptr nodeAA_; + std::shared_ptr nodeB_; + std::shared_ptr nodeBA_; + std::shared_ptr nodeBB_; + std::shared_ptr nodeBBA_; + std::shared_ptr nodeBBB_; + std::shared_ptr nodeBC_; + std::shared_ptr nodeBD_; + + std::shared_ptr currentRootShadowNode_; + StubViewTree currentStubViewTree_; + + StackingContextTest() : builder_(simpleComponentBuilder()) { + // ┌────────────── (Root) ──────────────┐ + // │ ┏━ A (tag: 2) ━━━━━━━━━━━━━━━━━━━┓ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┏━ AA (tag: 3) ━━━━━━━━━━━━━━┓ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┏━ B (tag: 4) ━━━━━━━━━━━━━━━━━━━┓ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┃ │ + // │ ┃ ┏━ BA (tag: 5) ━━━━━━━━━━━━━━┓ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ ┃ ┏━ BB (tag: 6) ━━━━━━━━━━━━━━┓ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┏━ BBA (tag: 7) ━━━━━━━━━┓ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ + // │ ┃ ┃ ┏━ BBB (tag: 8) ━━━━━━━━━┓ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ ┃ ┏━ BC (tag: 9) ━━━━━━━━━━━━━━┓ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ ┃ ┏━ BD (tag: 10) ━━━━━━━━━━━━━┓ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // └────────────────────────────────────┘ + + // clang-format off + auto element = + Element() + .reference(rootShadowNode_) + .tag(1) + .children({ + Element() + .tag(2) + .reference(nodeA_) + .children({ + Element() + .tag(3) + .reference(nodeAA_) + }), + Element() + .tag(4) + .reference(nodeB_) + .children({ + Element() + .tag(5) + .reference(nodeBA_), + Element() + .tag(6) + .reference(nodeBB_) + .children({ + Element() + .tag(7) + .reference(nodeBBA_), + Element() + .tag(8) + .reference(nodeBBB_) + }), + Element() + .tag(9) + .reference(nodeBC_), + Element() + .tag(10) + .reference(nodeBD_) + }) + }); + // clang-format on + + builder_.build(element); + + currentRootShadowNode_ = rootShadowNode_; + currentRootShadowNode_->layoutIfNeeded(); + currentStubViewTree_ = + buildStubViewTreeWithoutUsingDifferentiator(*currentRootShadowNode_); + } + + void mutateViewShadowNodeProps_( + std::shared_ptr node, + std::function callback) { + rootShadowNode_ = + std::static_pointer_cast(rootShadowNode_->cloneTree( + node->getFamily(), [&](ShadowNode const &oldShadowNode) { + auto viewProps = std::make_shared(); + callback(*viewProps); + return oldShadowNode.clone(ShadowNodeFragment{viewProps}); + })); + } + + void testViewTree_( + std::function callback) { + rootShadowNode_->layoutIfNeeded(); + + callback(buildStubViewTreeUsingDifferentiator(*rootShadowNode_)); + callback(buildStubViewTreeWithoutUsingDifferentiator(*rootShadowNode_)); + + auto mutations = + calculateShadowViewMutations(*currentRootShadowNode_, *rootShadowNode_); + currentRootShadowNode_ = rootShadowNode_; + currentStubViewTree_.mutate(mutations); + callback(currentStubViewTree_); + } +}; + +TEST_F(StackingContextTest, defaultPropsMakeEverythingFlattened) { + testViewTree_([](StubViewTree const &viewTree) { + // 1 view in total. + EXPECT_EQ(viewTree.size(), 1); + + // The root view has no subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 0); + }); +} + +TEST_F(StackingContextTest, mostPropsDoNotForceViewsToMaterialize) { + // ┌────────────── (Root) ──────────────┐ ┌────────── (Root) ───────────┐ + // │ ┏━ A (tag: 2) ━━━━━━━━━━━━━━━━━━━┓ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┏━ AA (tag: 3) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ padding: 10; ┃ ┃ │ │ │ + // │ ┃ ┃ margin: 9001; ┃ ┃ │ │ │ + // │ ┃ ┃ position: absolute; ┃ ┃ │ │ │ + // │ ┃ ┃ shadowRadius: 10; ┃ ┃ │ │ │ + // │ ┃ ┃ shadowOffset: [42, 42]; ┃ ┃ │ │ │ + // │ ┃ ┃ backgroundColor: clear; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ │ + // │ ┏━ B (tag: 4) ━━━━━━━━━━━━━━━━━━━┓ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┏━ BA (tag: 5) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ zIndex: 42; ┃ ┃ │ │ │ + // │ ┃ ┃ margin: 42; ┃ ┃ │ │ │ + // │ ┃ ┃ shadowColor: clear; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BB (tag: 6) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ No observable side-effects. │ + // │ ┃ ┃ ┃ ┃ │━━━▶│ No views are generated. │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBA (tag: 7) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ position: relative; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ borderRadii: 42; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ borderColor: black; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBB (tag: 8) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BC (tag: 9) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BD (tag: 10) ━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ onLayout: true; ┃ ┃ │ │ │ + // │ ┃ ┃ hitSlop: 42; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ │ + // └────────────────────────────────────┘ └─────────────────────────────┘ + + mutateViewShadowNodeProps_(nodeAA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.padding()[YGEdgeAll] = YGValue{42, YGUnitPoint}; + yogaStyle.margin()[YGEdgeAll] = YGValue{42, YGUnitPoint}; + yogaStyle.positionType() = YGPositionTypeAbsolute; + props.shadowRadius = 42; + props.shadowOffset = Size{42, 42}; + props.backgroundColor = clearColor(); + }); + + mutateViewShadowNodeProps_(nodeBA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + props.zIndex = 42; + yogaStyle.margin()[YGEdgeAll] = YGValue{42, YGUnitPoint}; + props.shadowColor = clearColor(); + props.shadowOpacity = 0.42; + }); + + mutateViewShadowNodeProps_(nodeBBA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + + props.borderRadii.all = 42; + props.borderColors.all = blackColor(); + }); + + mutateViewShadowNodeProps_(nodeBD_, [](ViewProps &props) { + props.onLayout = true; + props.hitSlop = EdgeInsets{42, 42, 42, 42}; + }); + + testViewTree_([](StubViewTree const &viewTree) { + // 1 view in total. + EXPECT_EQ(viewTree.size(), 1); + + // The root view has no subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 0); + }); +} + +TEST_F(StackingContextTest, somePropsForceViewsToMaterialize1) { + // ┌────────────── (Root) ──────────────┐ ┌─────────── (Root) ──────────┐ + // │ ┏━ A (tag: 2) ━━━━━━━━━━━━━━━━━━━┓ │ │ ┏━ AA (tag: 3) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┏━ AA (tag: 3) ━━━━━━━━━━━━━━┓ ┃ │ │ ┏━ BA (tag: 5) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ backgroundColor: black; ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ │ │ ┏━ BBA (tag: 7) ━━━━━━━━━━┓ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┃ ┃ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┏━ B (tag: 4) ━━━━━━━━━━━━━━━━━━━┓ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┃ │ │ │ + // │ ┃ ┏━ BA (tag: 5) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ backgroundColor: white; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BB (tag: 6) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │━━━▶│ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBA (tag: 7) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ shadowColor: black; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBB (tag: 8) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BC (tag: 9) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BD (tag: 10) ━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ │ + // └────────────────────────────────────┘ └─────────────────────────────┘ + + mutateViewShadowNodeProps_( + nodeAA_, [](ViewProps &props) { props.backgroundColor = blackColor(); }); + + mutateViewShadowNodeProps_( + nodeBA_, [](ViewProps &props) { props.backgroundColor = whiteColor(); }); + + mutateViewShadowNodeProps_( + nodeBBA_, [](ViewProps &props) { props.shadowColor = blackColor(); }); + + testViewTree_([](StubViewTree const &viewTree) { + // 4 views in total. + EXPECT_EQ(viewTree.size(), 4); + + // The root view has all 3 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 3); + + // The root view subviews are [3, 5, 7]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 3); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 7); + }); +} + +TEST_F(StackingContextTest, somePropsForceViewsToMaterialize2) { + // ┌────────────── (Root) ──────────────┐ ┌─────────── (Root) ──────────┐ + // │ ┏━ A (tag: 2) ━━━━━━━━━━━━━━━━━━━┓ │ │ ┏━ A (tag: 2) ━━━━━━━━━━━━┓ │ + // │ ┃ backgroundColor: black; ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┏━ AA (tag: 3) ━━━━━━━━━━━━━━┓ ┃ │ │ ┏━ AA (tag: 3) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ pointerEvents: none; ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ │ │ ┏━ B (tag: 4) ━━━━━━━━━━━━┓ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┃ ┃ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┏━ B (tag: 4) ━━━━━━━━━━━━━━━━━━━┓ │ │ ┏━ BA (tag: 5) ━━━━━━━━━━━┓ │ + // │ ┃ testId: "42" ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┏━ BA (tag: 5) ━━━━━━━━━━━━━━┓ ┃ │ │ ┏━ BB (tag: 6) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ nativeId: "42" ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┏━ BBA (tag: 7) ━━━━━━━━━━┓ │ + // │ ┃ ┏━ BB (tag: 6) ━━━━━━━━━━━━━━┓ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ foregroundColor: black; ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ │━━━▶│ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ │ │ ┏━ BBB (tag: 8) ━━━━━━━━━━┓ │ + // │ ┃ ┃ ┏━ BBA (tag: 7) ━━━━━━━━━┓ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ transform: scale(2); ┃ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ ┏━ BC (tag: 9) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┏━ BBB (tag: 8) ━━━━━━━━━┓ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ position: relative; ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ zIndex: 42; ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ ┏━ BD (tag: 10) ━━━━━━━━━━┓ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┃ ┃ │ + // │ ┃ ┏━ BC (tag: 9) ━━━━━━━━━━━━━━┓ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ shadowColor: black; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BD (tag: 10) ━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ opacity: 0.42; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ │ + // └────────────────────────────────────┘ └─────────────────────────────┘ + + mutateViewShadowNodeProps_( + nodeA_, [](ViewProps &props) { props.backgroundColor = blackColor(); }); + + mutateViewShadowNodeProps_(nodeAA_, [](ViewProps &props) { + props.pointerEvents = PointerEventsMode::None; + }); + + mutateViewShadowNodeProps_( + nodeB_, [](ViewProps &props) { props.testId = "42"; }); + + mutateViewShadowNodeProps_( + nodeBA_, [](ViewProps &props) { props.nativeId = "42"; }); + + mutateViewShadowNodeProps_( + nodeBB_, [](ViewProps &props) { props.foregroundColor = blackColor(); }); + + mutateViewShadowNodeProps_(nodeBBA_, [](ViewProps &props) { + props.transform = Transform::Scale(2, 2, 2); + }); + + mutateViewShadowNodeProps_(nodeBBB_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 42; + }); + + mutateViewShadowNodeProps_( + nodeBC_, [](ViewProps &props) { props.shadowColor = blackColor(); }); + + mutateViewShadowNodeProps_( + nodeBD_, [](ViewProps &props) { props.opacity = 0.42; }); + + testViewTree_([](StubViewTree const &viewTree) { + // 10 views in total. + EXPECT_EQ(viewTree.size(), 10); + + // The root view has all 9 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 9); + }); +} + +TEST_F(StackingContextTest, zIndexAndFlattenedNodes) { + // ┌────────────── (Root) ──────────────┐ ┌────────── (Root) ───────────┐ + // │ ┏━ A (tag: 2) ━━━━━━━━━━━━━━━━━━━┓ │ │ ┏━ BD (tag: 10) ━━━━━━━━━━┓ │ + // │ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┏━ AA (tag: 3) ━━━━━━━━━━━━━━┓ ┃ │ │ ┏━ BC (tag: 9) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ position: relative; ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ zIndex: 9001; ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ │ │ ┏━ BBB (tag: 8) ━━━━━━━━━━┓ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┃ ┃ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┏━ B (tag: 4) ━━━━━━━━━━━━━━━━━━━┓ │ │ ┏━ BBA (tag: 7) ━━━━━━━━━━┓ │ + // │ ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┏━ BA (tag: 5) ━━━━━━━━━━━━━━┓ ┃ │ │ ┏━ BA (tag: 5) ━━━━━━━━━━━┓ │ + // │ ┃ ┃ position: relative; ┃ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ zIndex: 9000; ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ ┏━ AA (tag: 3) ━━━━━━━━━━━┓ │ + // │ ┃ ┏━ BB (tag: 6) ━━━━━━━━━━━━━━┓ ┃ │ │ ┃ #FormsView ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┃ #FormsStackingContext ┃ │ + // │ ┃ ┃ ┃ ┃ │━━━▶│ ┃ ┃ │ + // │ ┃ ┃ ┃ ┃ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBA (tag: 7) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ position: relative; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ zIndex: 8999; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┃ ┏━ BBB (tag: 8) ━━━━━━━━━┓ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ position: relative; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ zIndex: 8998; ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BC (tag: 9) ━━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ position: relative; ┃ ┃ │ │ │ + // │ ┃ ┃ zIndex: 8997; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┃ ┏━ BD (tag: 10) ━━━━━━━━━━━━━┓ ┃ │ │ │ + // │ ┃ ┃ position: relative; ┃ ┃ │ │ │ + // │ ┃ ┃ zIndex: 8996; ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┃ ┃ ┃ │ │ │ + // │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ │ │ │ + // │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ │ │ │ + // └────────────────────────────────────┘ └─────────────────────────────┘ + + mutateViewShadowNodeProps_(nodeAA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 9001; + }); + + mutateViewShadowNodeProps_(nodeBA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 9000; + }); + + mutateViewShadowNodeProps_(nodeBBA_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 8999; + }); + + mutateViewShadowNodeProps_(nodeBBB_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 8998; + }); + + mutateViewShadowNodeProps_(nodeBC_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 8997; + }); + + mutateViewShadowNodeProps_(nodeBD_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 8996; + }); + + testViewTree_([](StubViewTree const &viewTree) { + // 7 views in total. + EXPECT_EQ(viewTree.size(), 7); + + // The root view has all 6 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 6); + + // The root view subviews are [10, 9, 8, 7, 5, 3]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 10); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 9); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 8); + EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 7); + EXPECT_EQ(viewTree.getRootStubView().children.at(4)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(5)->tag, 3); + }); + + // And now let's make BB to form a Stacking Context with small order-index. + + // ┌────────────── (Root) ──────────────┐ ┌────────── (Root) ──────────┐ + // │ ┌─ A (tag: 2) ───────────────────┐ │ │ ┏━ BB (tag: 6) ━━━━━━━━━━┓ │ + // │ │ │ │ │ ┃ #View ┃ │ + // │ │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ ┃ ┏━ BBB (tag: 8) ━━━━━┓ ┃ │ + // │ │ ┌─ AA (tag: 3) ──────────────┐ │ │ │ ┃ ┃ #View ┃ ┃ │ + // │ │ │ position: relative; │ │ │ │ ┃ ┃ #StackingContext ┃ ┃ │ + // │ │ │ zIndex: 9001; │ │ │ │ ┃ ┃ ┃ ┃ │ + // │ │ │ │ │ │ │ ┃ ┗━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ │ │ │ │ │ │ ┃ ┏━ BBA (tag: 7) ━━━━━┓ ┃ │ + // │ │ │ │ │ │ │ ┃ ┃ #View ┃ ┃ │ + // │ │ │ │ │ │ │ ┃ ┃ #StackingContext ┃ ┃ │ + // │ │ │ │ │ │ │ ┃ ┃ ┃ ┃ │ + // │ │ └────────────────────────────┘ │ │ │ ┃ ┗━━━━━━━━━━━━━━━━━━━━┛ ┃ │ + // │ └────────────────────────────────┘ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┌─ B (tag: 4) ───────────────────┐ │ │ ┏━ BD (tag: 10) ━━━━━━━━━┓ │ + // │ │ │ │ │ ┃ #View ┃ │ + // │ │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ ┌─ BA (tag: 5) ──────────────┐ │ │ │ ┏━ BC (tag: 9) ━━━━━━━━━━┓ │ + // │ │ │ position: relative; │ │ │ │ ┃ #View ┃ │ + // │ │ │ zIndex: 9000; │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ └────────────────────────────┘ │ │ │ ┏━ BA (tag: 5) ━━━━━━━━━━┓ │ + // │ │ ╔═ BB (tag: 6) ══════════════╗ │ │ │ ┃ #View ┃ │ + // │ │ ║ *** position: relative; ║ │ │ │ ┃ #StackingContext ┃ │ + // │ │ ║ *** zIndex: 42; ║ │ │━━━━▶│ ┃ ┃ │ + // │ │ ║ ║ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ ║ ║ │ │ │ ┏━ AA (tag: 3) ━━━━━━━━━━┓ │ + // │ │ ║ ┌─ BBA (tag: 7) ─────────┐ ║ │ │ │ ┃ #View ┃ │ + // │ │ ║ │ position: relative; │ ║ │ │ │ ┃ #StackingContext ┃ │ + // │ │ ║ │ zIndex: 8999; │ ║ │ │ │ ┃ ┃ │ + // │ │ ║ │ │ ║ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ └────────────────────────┘ ║ │ │ │ │ + // │ │ ║ ┌─ BBB (tag: 8) ─────────┐ ║ │ │ │ │ + // │ │ ║ │ position: relative; │ ║ │ │ │ │ + // │ │ ║ │ zIndex: 8998; │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ └────────────────────────┘ ║ │ │ │ │ + // │ │ ╚════════════════════════════╝ │ │ │ │ + // │ │ ┌─ BC (tag: 9) ──────────────┐ │ │ │ │ + // │ │ │ position: relative; │ │ │ │ │ + // │ │ │ zIndex: 8997; │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ └────────────────────────────┘ │ │ │ │ + // │ │ ┌─ BD (tag: 10) ─────────────┐ │ │ │ │ + // │ │ │ position: relative; │ │ │ │ │ + // │ │ │ zIndex: 8996; │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ └────────────────────────────┘ │ │ │ │ + // │ └────────────────────────────────┘ │ │ │ + // └────────────────────────────────────┘ └────────────────────────────┘ + + mutateViewShadowNodeProps_(nodeBB_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeRelative; + props.zIndex = 42; + }); + + testViewTree_([](StubViewTree const &viewTree) { + // 8 views in total. + EXPECT_EQ(viewTree.size(), 8); + + // The root view has 5 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 5); + + // The root view subviews are [6, 10, 9, 5, 3]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 6); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 10); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 9); + EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(4)->tag, 3); + + auto &view6 = viewTree.getStubView(6); + EXPECT_EQ(view6.children.size(), 2); + EXPECT_EQ(view6.children.at(0)->tag, 8); + EXPECT_EQ(view6.children.at(1)->tag, 7); + }); + + // And now, let's revert it back. + + mutateViewShadowNodeProps_(nodeBB_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.positionType() = YGPositionTypeStatic; + props.zIndex = {}; + }); + + testViewTree_([](StubViewTree const &viewTree) { + // 7 views in total. + EXPECT_EQ(viewTree.size(), 7); + + // The root view has all 6 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 6); + + // The root view subviews are [10, 9, 8, 7, 5, 3]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 10); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 9); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 8); + EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 7); + EXPECT_EQ(viewTree.getRootStubView().children.at(4)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(5)->tag, 3); + }); + + // And now, let's hide BB completety. + + // ┌────────────── (Root) ──────────────┐ ┌────────── (Root) ──────────┐ + // │ ┌─ A (tag: 2) ───────────────────┐ │ │ ┏━ BD (tag: 10) ━━━━━━━━━┓ │ + // │ │ │ │ │ ┃ #View ┃ │ + // │ │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ ┌─ AA (tag: 3) ──────────────┐ │ │ │ ┏━ BC (tag: 9) ━━━━━━━━━━┓ │ + // │ │ │ position: relative; │ │ │ │ ┃ #View ┃ │ + // │ │ │ zIndex: 9001; │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ │ │ │ │ │ ┏━ BA (tag: 5) ━━━━━━━━━━┓ │ + // │ │ │ │ │ │ │ ┃ #View ┃ │ + // │ │ │ │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ └────────────────────────────┘ │ │ │ ┃ ┃ │ + // │ └────────────────────────────────┘ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ ┌─ B (tag: 4) ───────────────────┐ │ │ ┏━ AA (tag: 3) ━━━━━━━━━━┓ │ + // │ │ │ │ │ ┃ #View ┃ │ + // │ │ │ │ │ ┃ #StackingContext ┃ │ + // │ │ │ │ │ ┃ ┃ │ + // │ │ │ │ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛ │ + // │ │ ┌─ BA (tag: 5) ──────────────┐ │ │ │ │ + // │ │ │ position: relative; │ │ │ │ │ + // │ │ │ zIndex: 9000; │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ └────────────────────────────┘ │ │ │ │ + // │ │ ╔═ BB (tag: 6) ══════════════╗ │ │ │ │ + // │ │ ║ *** display: none; ║ │ │ │ │ + // │ │ ║ ║ │ │━━━━▶│ │ + // │ │ ║ ║ │ │ │ │ + // │ │ ║ ║ │ │ │ │ + // │ │ ║ ┌─ BBA (tag: 7) ─────────┐ ║ │ │ │ │ + // │ │ ║ │ position: relative; │ ║ │ │ │ │ + // │ │ ║ │ zIndex: 8999; │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ └────────────────────────┘ ║ │ │ │ │ + // │ │ ║ ┌─ BBB (tag: 8) ─────────┐ ║ │ │ │ │ + // │ │ ║ │ position: relative; │ ║ │ │ │ │ + // │ │ ║ │ zIndex: 8998; │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ │ │ ║ │ │ │ │ + // │ │ ║ └────────────────────────┘ ║ │ │ │ │ + // │ │ ╚════════════════════════════╝ │ │ │ │ + // │ │ ┌─ BC (tag: 9) ──────────────┐ │ │ │ │ + // │ │ │ position: relative; │ │ │ │ │ + // │ │ │ zIndex: 8997; │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ └────────────────────────────┘ │ │ │ │ + // │ │ ┌─ BD (tag: 10) ─────────────┐ │ │ │ │ + // │ │ │ position: relative; │ │ │ │ │ + // │ │ │ zIndex: 8996; │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // │ │ └────────────────────────────┘ │ │ │ │ + // │ └────────────────────────────────┘ │ │ │ + // └────────────────────────────────────┘ └────────────────────────────┘ + + mutateViewShadowNodeProps_(nodeBB_, [](ViewProps &props) { + auto &yogaStyle = props.yogaStyle; + yogaStyle.display() = YGDisplayNone; + }); + + testViewTree_([](StubViewTree const &viewTree) { + // 5 views in total. + EXPECT_EQ(viewTree.size(), 5); + + // The root view has all 4 subviews. + EXPECT_EQ(viewTree.getRootStubView().children.size(), 4); + + // The root view subviews are [10, 9, 5, 3]. + EXPECT_EQ(viewTree.getRootStubView().children.at(0)->tag, 10); + EXPECT_EQ(viewTree.getRootStubView().children.at(1)->tag, 9); + EXPECT_EQ(viewTree.getRootStubView().children.at(2)->tag, 5); + EXPECT_EQ(viewTree.getRootStubView().children.at(3)->tag, 3); + }); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp b/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp index d32e1d69a5c42c..2b6ccfe7f1de67 100644 --- a/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp +++ b/ReactCommon/react/renderer/mounting/tests/StateReconciliationTest.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -24,6 +23,13 @@ using namespace facebook::react; class DummyShadowTreeDelegate : public ShadowTreeDelegate { public: + virtual RootShadowNode::Unshared shadowTreeWillCommit( + ShadowTree const &shadowTree, + RootShadowNode::Shared const &oldRootShadowNode, + RootShadowNode::Unshared const &newRootShadowNode) const override { + return newRootShadowNode; + }; + virtual void shadowTreeDidFinishTransaction( ShadowTree const &shadowTree, MountingCoordinator::Shared const &mountingCoordinator) const override{}; @@ -32,7 +38,7 @@ class DummyShadowTreeDelegate : public ShadowTreeDelegate { inline ShadowNode const *findDescendantNode( ShadowNode const &shadowNode, ShadowNodeFamily const &family) { - auto result = (ShadowNode const *){nullptr}; + ShadowNode const *result = nullptr; shadowNode.cloneTree(family, [&](ShadowNode const &oldShadowNode) { result = &oldShadowNode; return oldShadowNode.clone({}); @@ -43,16 +49,8 @@ inline ShadowNode const *findDescendantNode( inline ShadowNode const *findDescendantNode( ShadowTree const &shadowTree, ShadowNodeFamily const &family) { - auto result = (ShadowNode const *){nullptr}; - - shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - result = findDescendantNode(*oldRootShadowNode, family); - return nullptr; - }, - false); - - return result; + return findDescendantNode( + *shadowTree.getCurrentRevision().rootShadowNode, family); } TEST(StateReconciliationTest, testStateReconciliation) { @@ -96,21 +94,14 @@ TEST(StateReconciliationTest, testStateReconciliation) { auto &family = shadowNodeAB->getFamily(); auto state1 = shadowNodeAB->getState(); auto shadowTreeDelegate = DummyShadowTreeDelegate{}; - auto eventDispatcher = EventDispatcher::Shared{}; - auto rootComponentDescriptor = - ComponentDescriptorParameters{eventDispatcher, nullptr, nullptr}; - ShadowTree shadowTree{SurfaceId{11}, - LayoutConstraints{}, - LayoutContext{}, - rootComponentDescriptor, - shadowTreeDelegate, - {}}; + ShadowTree shadowTree{ + SurfaceId{11}, LayoutConstraints{}, LayoutContext{}, shadowTreeDelegate}; shadowTree.commit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::static_pointer_cast(rootShadowNodeState1); }, - true); + {true}); EXPECT_EQ(state1->getMostRecentState(), state1); @@ -122,19 +113,20 @@ TEST(StateReconciliationTest, testStateReconciliation) { auto rootShadowNodeState2 = shadowNode->cloneTree(family, [&](ShadowNode const &oldShadowNode) { - return oldShadowNode.clone({ShadowNodeFragment::propsPlaceholder(), - ShadowNodeFragment::childrenPlaceholder(), - state2}); + return oldShadowNode.clone( + {ShadowNodeFragment::propsPlaceholder(), + ShadowNodeFragment::childrenPlaceholder(), + state2}); }); EXPECT_EQ( findDescendantNode(*rootShadowNodeState2, family)->getState(), state2); shadowTree.commit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::static_pointer_cast(rootShadowNodeState2); }, - true); + {true}); EXPECT_EQ(state1->getMostRecentState(), state2); EXPECT_EQ(state2->getMostRecentState(), state2); @@ -144,19 +136,20 @@ TEST(StateReconciliationTest, testStateReconciliation) { auto rootShadowNodeState3 = rootShadowNodeState2->cloneTree( family, [&](ShadowNode const &oldShadowNode) { - return oldShadowNode.clone({ShadowNodeFragment::propsPlaceholder(), - ShadowNodeFragment::childrenPlaceholder(), - state3}); + return oldShadowNode.clone( + {ShadowNodeFragment::propsPlaceholder(), + ShadowNodeFragment::childrenPlaceholder(), + state3}); }); EXPECT_EQ( findDescendantNode(*rootShadowNodeState3, family)->getState(), state3); shadowTree.commit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::static_pointer_cast(rootShadowNodeState3); }, - true); + {true}); EXPECT_EQ(findDescendantNode(shadowTree, family)->getState(), state3); @@ -168,10 +161,10 @@ TEST(StateReconciliationTest, testStateReconciliation) { // Here we commit the old tree but we expect that the state associated with // the node will stay the same (newer that the old tree has). shadowTree.commit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::static_pointer_cast(rootShadowNodeState2); }, - true); + {true}); EXPECT_EQ(findDescendantNode(shadowTree, family)->getState(), state3); } diff --git a/ReactCommon/react/renderer/mounting/tests/shadowTreeGeneration.h b/ReactCommon/react/renderer/mounting/tests/shadowTreeGeneration.h index 8a2c326d157efe..093272090d1246 100644 --- a/ReactCommon/react/renderer/mounting/tests/shadowTreeGeneration.h +++ b/ReactCommon/react/renderer/mounting/tests/shadowTreeGeneration.h @@ -250,8 +250,9 @@ static inline ShadowNode::Shared generateShadowNodeTree( auto family = componentDescriptor.createFamily( {generateReactTag(), SurfaceId(1), nullptr}, nullptr); return componentDescriptor.createShadowNode( - ShadowNodeFragment{generateDefaultProps(componentDescriptor), - std::make_shared(children)}, + ShadowNodeFragment{ + generateDefaultProps(componentDescriptor), + std::make_shared(children)}, family); } diff --git a/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 359199b412a60f..3ca4efb45a0efd 100644 --- a/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,8 @@ namespace react { Scheduler::Scheduler( SchedulerToolbox schedulerToolbox, UIManagerAnimationDelegate *animationDelegate, - SchedulerDelegate *delegate) { + SchedulerDelegate *delegate) + : surfaceManager_(*this) { runtimeExecutor_ = schedulerToolbox.runtimeExecutor; reactNativeConfig_ = @@ -50,10 +52,12 @@ Scheduler::Scheduler( const EventTarget *eventTarget, const std::string &type, const ValueFactory &payloadFactory) { - uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) { - uiManagerBinding.dispatchEvent( - runtime, eventTarget, type, payloadFactory); - }); + uiManager->visitBinding( + [&](UIManagerBinding const &uiManagerBinding) { + uiManagerBinding.dispatchEvent( + runtime, eventTarget, type, payloadFactory); + }, + runtime); }; auto statePipe = [uiManager](StateUpdate const &stateUpdate) { @@ -76,11 +80,9 @@ Scheduler::Scheduler( componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory( eventDispatcher, schedulerToolbox.contextContainer); - rootComponentDescriptor_ = std::make_unique( - ComponentDescriptorParameters{eventDispatcher, nullptr, nullptr}); - uiManager->setBackgroundExecutor(schedulerToolbox.backgroundExecutor); uiManager->setDelegate(this); + uiManager->setRuntimeExecutor(runtimeExecutor_); uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_); runtimeExecutor_([=](jsi::Runtime &runtime) { @@ -97,8 +99,13 @@ Scheduler::Scheduler( componentDescriptorRegistry_)); delegate_ = delegate; + commitHooks_ = schedulerToolbox.commitHooks; uiManager_ = uiManager; + for (auto commitHook : commitHooks_) { + uiManager->registerCommitHook(*commitHook); + } + if (animationDelegate != nullptr) { animationDelegate->setComponentDescriptorRegistry( componentDescriptorRegistry_); @@ -106,22 +113,31 @@ Scheduler::Scheduler( uiManager_->setAnimationDelegate(animationDelegate); #ifdef ANDROID - enableReparentingDetection_ = reactNativeConfig_->getBool( - "react_fabric:enable_reparenting_detection_android"); removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool( "react_fabric:remove_outstanding_surfaces_on_destruction_android"); + Constants::setPropsForwardingEnabled(reactNativeConfig_->getBool( + "react_fabric:enable_props_forwarding_android")); + enableSurfaceManager_ = reactNativeConfig_->getBool( + "react_fabric:enable_surface_manager_android"); #else - enableReparentingDetection_ = reactNativeConfig_->getBool( - "react_fabric:enable_reparenting_detection_ios"); removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool( "react_fabric:remove_outstanding_surfaces_on_destruction_ios"); + enableSurfaceManager_ = + reactNativeConfig_->getBool("react_fabric:enable_surface_manager_ios"); #endif + + uiManager->extractUIManagerBindingOnDemand_ = reactNativeConfig_->getBool( + "react_fabric:extract_uimanagerbinding_on_demand"); } Scheduler::~Scheduler() { LOG(WARNING) << "Scheduler::~Scheduler() was called (address: " << this << ")."; + for (auto commitHook : commitHooks_) { + uiManager_->unregisterCommitHook(*commitHook); + } + // All Surfaces must be explicitly stopped before destroying `Scheduler`. // The idea is that `UIManager` is allowed to call `Scheduler` only if the // corresponding `ShadowTree` instance exists. @@ -169,34 +185,44 @@ Scheduler::~Scheduler() { } } +void Scheduler::registerSurface( + SurfaceHandler const &surfaceHandler) const noexcept { + surfaceHandler.setUIManager(uiManager_.get()); +} + +void Scheduler::unregisterSurface( + SurfaceHandler const &surfaceHandler) const noexcept { + surfaceHandler.setUIManager(nullptr); +} + void Scheduler::startSurface( SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints, - const LayoutContext &layoutContext, - std::weak_ptr mountingOverrideDelegate) - const { + const LayoutContext &layoutContext) const { SystraceSection s("Scheduler::startSurface"); + if (enableSurfaceManager_) { + surfaceManager_.startSurface( + surfaceId, moduleName, initialProps, layoutConstraints, layoutContext); + return; + } + auto shadowTree = std::make_unique( - surfaceId, - layoutConstraints, - layoutContext, - *rootComponentDescriptor_, - *uiManager_, - mountingOverrideDelegate, - enableReparentingDetection_); + surfaceId, layoutConstraints, layoutContext, *uiManager_); auto uiManager = uiManager_; uiManager->getShadowTreeRegistry().add(std::move(shadowTree)); runtimeExecutor_([=](jsi::Runtime &runtime) { - uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) { - uiManagerBinding.startSurface( - runtime, surfaceId, moduleName, initialProps); - }); + uiManager->visitBinding( + [&](UIManagerBinding const &uiManagerBinding) { + uiManagerBinding.startSurface( + runtime, surfaceId, moduleName, initialProps); + }, + runtime); }); } @@ -220,9 +246,9 @@ void Scheduler::renderTemplateToSurface( uiManager_->getShadowTreeRegistry().visit( surfaceId, [=](const ShadowTree &shadowTree) { return shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::make_shared( - *oldRootShadowNode, + oldRootShadowNode, ShadowNodeFragment{ /* .props = */ ShadowNodeFragment::propsPlaceholder(), /* .children = */ @@ -240,22 +266,24 @@ void Scheduler::renderTemplateToSurface( void Scheduler::stopSurface(SurfaceId surfaceId) const { SystraceSection s("Scheduler::stopSurface"); + if (enableSurfaceManager_) { + surfaceManager_.stopSurface(surfaceId); + return; + } + // Stop any ongoing animations. uiManager_->stopSurfaceForAnimationDelegate(surfaceId); - // Note, we have to do in inside `visit` function while the Shadow Tree - // is still being registered. - uiManager_->getShadowTreeRegistry().visit( - surfaceId, [](ShadowTree const &shadowTree) { - // As part of stopping a Surface, we need to properly destroy all - // mounted views, so we need to commit an empty tree to trigger all - // side-effects that will perform that. - shadowTree.commitEmptyTree(); - }); - // Waiting for all concurrent commits to be finished and unregistering the // `ShadowTree`. - uiManager_->getShadowTreeRegistry().remove(surfaceId); + auto shadowTree = uiManager_->getShadowTreeRegistry().remove(surfaceId); + + // As part of stopping a Surface, we need to properly destroy all + // mounted views, so we need to commit an empty tree to trigger all + // side-effects (including destroying and removing mounted views). + if (shadowTree) { + shadowTree->commitEmptyTree(); + } // We execute JavaScript/React part of the process at the very end to minimize // any visible side-effects of stopping the Surface. Any possible commits from @@ -263,9 +291,11 @@ void Scheduler::stopSurface(SurfaceId surfaceId) const { // fail silently. auto uiManager = uiManager_; runtimeExecutor_([=](jsi::Runtime &runtime) { - uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) { - uiManagerBinding.stopSurface(runtime, surfaceId); - }); + uiManager->visitBinding( + [&](UIManagerBinding const &uiManagerBinding) { + uiManagerBinding.stopSurface(runtime, surfaceId); + }, + runtime); }); } @@ -275,23 +305,29 @@ Size Scheduler::measureSurface( const LayoutContext &layoutContext) const { SystraceSection s("Scheduler::measureSurface"); - Size size; + if (enableSurfaceManager_) { + return surfaceManager_.measureSurface( + surfaceId, layoutConstraints, layoutContext); + } + + auto currentRootShadowNode = RootShadowNode::Shared{}; uiManager_->getShadowTreeRegistry().visit( surfaceId, [&](const ShadowTree &shadowTree) { - shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - auto rootShadowNode = - oldRootShadowNode->clone(layoutConstraints, layoutContext); - rootShadowNode->layoutIfNeeded(); - size = rootShadowNode->getLayoutMetrics().frame.size; - return nullptr; - }); + currentRootShadowNode = shadowTree.getCurrentRevision().rootShadowNode; }); - return size; + + auto rootShadowNode = + currentRootShadowNode->clone(layoutConstraints, layoutContext); + rootShadowNode->layoutIfNeeded(); + return rootShadowNode->getLayoutMetrics().frame.size; } MountingCoordinator::Shared Scheduler::findMountingCoordinator( SurfaceId surfaceId) const { + if (enableSurfaceManager_) { + return surfaceManager_.findMountingCoordinator(surfaceId); + } + MountingCoordinator::Shared mountingCoordinator = nullptr; uiManager_->getShadowTreeRegistry().visit( surfaceId, [&](const ShadowTree &shadowTree) { @@ -304,12 +340,17 @@ void Scheduler::constraintSurfaceLayout( SurfaceId surfaceId, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { + if (enableSurfaceManager_) { + return surfaceManager_.constraintSurfaceLayout( + surfaceId, layoutConstraints, layoutContext); + } + SystraceSection s("Scheduler::constraintSurfaceLayout"); uiManager_->getShadowTreeRegistry().visit( surfaceId, [&](ShadowTree const &shadowTree) { - shadowTree.commit([&](RootShadowNode::Shared const &oldRootShadowNode) { - return oldRootShadowNode->clone(layoutConstraints, layoutContext); + shadowTree.commit([&](RootShadowNode const &oldRootShadowNode) { + return oldRootShadowNode.clone(layoutConstraints, layoutContext); }); }); } @@ -370,6 +411,17 @@ void Scheduler::uiManagerDidDispatchCommand( } } +void Scheduler::uiManagerDidSendAccessibilityEvent( + const ShadowNode::Shared &shadowNode, + std::string const &eventType) { + SystraceSection s("Scheduler::uiManagerDidSendAccessibilityEvent"); + + if (delegate_) { + auto shadowView = ShadowView(*shadowNode); + delegate_->schedulerDidSendAccessibilityEvent(shadowView, eventType); + } +} + /* * Set JS responder for a view */ diff --git a/ReactCommon/react/renderer/scheduler/Scheduler.h b/ReactCommon/react/renderer/scheduler/Scheduler.h index 3b5693cb724093..9f75805ac70632 100644 --- a/ReactCommon/react/renderer/scheduler/Scheduler.h +++ b/ReactCommon/react/renderer/scheduler/Scheduler.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,14 +42,20 @@ class Scheduler final : public UIManagerDelegate { #pragma mark - Surface Management + /* + * Registers and unregisters a `SurfaceHandler` object in the `Scheduler`. + * All registered `SurfaceHandler` objects must be unregistered + * (with the same `Scheduler`) before their deallocation. + */ + void registerSurface(SurfaceHandler const &surfaceHandler) const noexcept; + void unregisterSurface(SurfaceHandler const &surfaceHandler) const noexcept; + void startSurface( SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints = {}, - const LayoutContext &layoutContext = {}, - std::weak_ptr mountingOverrideDelegate = - {}) const; + const LayoutContext &layoutContext = {}) const; void renderTemplateToSurface( SurfaceId surfaceId, @@ -75,7 +83,7 @@ class Scheduler final : public UIManagerDelegate { /* * This is broken. Please do not use. * `ComponentDescriptor`s are not designed to be used outside of `UIManager`, - * there is no any garantees about their lifetime. + * there is no any guarantees about their lifetime. */ ComponentDescriptor const * findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN( @@ -111,6 +119,9 @@ class Scheduler final : public UIManagerDelegate { const ShadowNode::Shared &shadowNode, std::string const &commandName, folly::dynamic const args) override; + void uiManagerDidSendAccessibilityEvent( + const ShadowNode::Shared &shadowNode, + std::string const &eventType) override; void uiManagerDidSetJSResponder( SurfaceId surfaceId, const ShadowNode::Shared &shadowView, @@ -118,13 +129,17 @@ class Scheduler final : public UIManagerDelegate { void uiManagerDidClearJSResponder() override; private: + friend class SurfaceHandler; + + SurfaceManager surfaceManager_; SchedulerDelegate *delegate_; SharedComponentDescriptorRegistry componentDescriptorRegistry_; - std::unique_ptr rootComponentDescriptor_; RuntimeExecutor runtimeExecutor_; std::shared_ptr uiManager_; std::shared_ptr reactNativeConfig_; + std::vector> commitHooks_; + /* * At some point, we have to have an owning shared pointer to something that * will become an `EventDispatcher` a moment later. That's why we have it as a @@ -137,8 +152,9 @@ class Scheduler final : public UIManagerDelegate { /* * Temporary flags. */ - bool enableReparentingDetection_{false}; bool removeOutstandingSurfacesOnDestruction_{false}; + + bool enableSurfaceManager_{false}; }; } // namespace react diff --git a/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h b/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h index 33be7dcb6e3d10..dabe3638b98ab3 100644 --- a/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h +++ b/ReactCommon/react/renderer/scheduler/SchedulerDelegate.h @@ -41,6 +41,10 @@ class SchedulerDelegate { std::string const &commandName, folly::dynamic const args) = 0; + virtual void schedulerDidSendAccessibilityEvent( + const ShadowView &shadowView, + std::string const &eventType) = 0; + /* * Set JS responder for a view */ diff --git a/ReactCommon/react/renderer/scheduler/SchedulerToolbox.h b/ReactCommon/react/renderer/scheduler/SchedulerToolbox.h index a98d450f37323a..816a979f88a924 100644 --- a/ReactCommon/react/renderer/scheduler/SchedulerToolbox.h +++ b/ReactCommon/react/renderer/scheduler/SchedulerToolbox.h @@ -7,9 +7,12 @@ #pragma once +#include + #include #include #include +#include #include #include #include @@ -60,6 +63,11 @@ struct SchedulerToolbox final { * the call back synchronously if the executor is invoked on the main thread. */ BackgroundExecutor backgroundExecutor; + + /* + * A list of `UIManagerCommitHook`s that should be registered in `UIManager`. + */ + std::vector> commitHooks; }; } // namespace react diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp new file mode 100644 index 00000000000000..b805dc54f02b2f --- /dev/null +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "SurfaceHandler.h" + +#include +#include + +namespace facebook { +namespace react { + +using Status = SurfaceHandler::Status; +using DisplayMode = SurfaceHandler::DisplayMode; + +SurfaceHandler::SurfaceHandler( + std::string const &moduleName, + SurfaceId surfaceId) noexcept { + parameters_.moduleName = moduleName; + parameters_.surfaceId = surfaceId; +} + +SurfaceHandler::SurfaceHandler(SurfaceHandler &&other) noexcept { + operator=(std::move(other)); +} + +SurfaceHandler &SurfaceHandler::operator=(SurfaceHandler &&other) noexcept { + std::unique_lock lock1(linkMutex_, std::defer_lock); + std::unique_lock lock2( + parametersMutex_, std::defer_lock); + std::unique_lock lock3( + other.linkMutex_, std::defer_lock); + std::unique_lock lock4( + other.parametersMutex_, std::defer_lock); + std::lock(lock1, lock2, lock3, lock4); + + link_ = other.link_; + parameters_ = other.parameters_; + + other.link_ = Link{}; + other.parameters_ = Parameters{}; + return *this; +} + +#pragma mark - Surface Life-Cycle Management + +Status SurfaceHandler::getStatus() const noexcept { + std::shared_lock lock(linkMutex_); + return link_.status; +} + +void SurfaceHandler::start() const noexcept { + { + std::unique_lock lock(linkMutex_); + assert(link_.status == Status::Registered && "Surface must be registered."); + + auto parameters = Parameters{}; + { + std::shared_lock parametersLock(parametersMutex_); + parameters = parameters_; + } + + link_.shadowTree = &link_.uiManager->startSurface( + parameters.surfaceId, + parameters.moduleName, + parameters.props, + parameters.layoutConstraints, + parameters.layoutContext); + + link_.status = Status::Running; + + applyDisplayMode(parameters.displayMode); + } +} + +void SurfaceHandler::stop() const noexcept { + std::unique_lock lock(linkMutex_); + assert(link_.status == Status::Running && "Surface must be running."); + + link_.status = Status::Registered; + link_.shadowTree = nullptr; + link_.uiManager->stopSurface(parameters_.surfaceId); +} + +void SurfaceHandler::setDisplayMode(DisplayMode displayMode) const noexcept { + { + std::unique_lock lock(parametersMutex_); + if (parameters_.displayMode == displayMode) { + return; + } + + parameters_.displayMode = displayMode; + } + + { + std::shared_lock lock(linkMutex_); + + if (link_.status != Status::Running) { + return; + } + + applyDisplayMode(displayMode); + } +} + +DisplayMode SurfaceHandler::getDisplayMode() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.displayMode; +} + +#pragma mark - Accessors + +SurfaceId SurfaceHandler::getSurfaceId() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.surfaceId; +} + +std::string SurfaceHandler::getModuleName() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.moduleName; +} + +void SurfaceHandler::setProps(folly::dynamic const &props) const noexcept { + std::unique_lock lock(parametersMutex_); + parameters_.props = props; +} + +folly::dynamic SurfaceHandler::getProps() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.props; +} + +std::shared_ptr +SurfaceHandler::getMountingCoordinator() const noexcept { + std::shared_lock lock(linkMutex_); + assert(link_.status != Status::Unregistered && "Surface must be registered."); + assert(link_.shadowTree && "`link_.shadowTree` must not be null."); + return link_.shadowTree->getMountingCoordinator(); +} + +#pragma mark - Layout + +Size SurfaceHandler::measure( + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept { + std::shared_lock lock(linkMutex_); + + if (link_.status != Status::Running) { + return layoutConstraints.clamp({0, 0}); + } + + assert(link_.shadowTree && "`link_.shadowTree` must not be null."); + + auto currentRootShadowNode = + link_.shadowTree->getCurrentRevision().rootShadowNode; + + auto rootShadowNode = + currentRootShadowNode->clone(layoutConstraints, layoutContext); + rootShadowNode->layoutIfNeeded(); + return rootShadowNode->getLayoutMetrics().frame.size; +} + +void SurfaceHandler::constraintLayout( + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept { + { + std::unique_lock lock(parametersMutex_); + + if (parameters_.layoutConstraints == layoutConstraints && + parameters_.layoutContext == layoutContext) { + return; + } + + parameters_.layoutConstraints = layoutConstraints; + parameters_.layoutContext = layoutContext; + } + + { + std::shared_lock lock(linkMutex_); + + if (link_.status != Status::Running) { + return; + } + + assert(link_.shadowTree && "`link_.shadowTree` must not be null."); + link_.shadowTree->commit([&](RootShadowNode const &oldRootShadowNode) { + return oldRootShadowNode.clone(layoutConstraints, layoutContext); + }); + } +} + +LayoutConstraints SurfaceHandler::getLayoutConstraints() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.layoutConstraints; +} + +LayoutContext SurfaceHandler::getLayoutContext() const noexcept { + std::shared_lock lock(parametersMutex_); + return parameters_.layoutContext; +} + +#pragma mark - Private + +void SurfaceHandler::applyDisplayMode(DisplayMode displayMode) const noexcept { + assert(link_.status == Status::Running && "Surface must be running."); + assert(link_.shadowTree && "`link_.shadowTree` must not be null."); + + switch (displayMode) { + case DisplayMode::Visible: + link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Normal); + break; + case DisplayMode::Suspended: + link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Suspended); + break; + case DisplayMode::Hidden: + link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Normal); + // Getting a current revision. + auto revision = link_.shadowTree->getCurrentRevision(); + // Committing an empty tree to force mounting to disassemble view + // hierarchy. + link_.shadowTree->commitEmptyTree(); + link_.shadowTree->setCommitMode(ShadowTree::CommitMode::Suspended); + // Committing the current revision back. It will be mounted only when + // `DisplayMode` is changed back to `Normal`. + link_.shadowTree->commit([&](RootShadowNode const &oldRootShadowNode) { + return std::static_pointer_cast( + revision.rootShadowNode->ShadowNode::clone(ShadowNodeFragment{})); + }); + break; + } +} + +void SurfaceHandler::setUIManager(UIManager const *uiManager) const noexcept { + std::unique_lock lock(linkMutex_); + + assert(link_.status != Status::Running && "Surface must not be running."); + + if (link_.uiManager == uiManager) { + return; + } + + link_.uiManager = uiManager; + link_.status = uiManager ? Status::Registered : Status::Unregistered; +} + +SurfaceHandler::~SurfaceHandler() noexcept { + assert( + link_.status == Status::Unregistered && + "`SurfaceHandler` must be unregistered (or moved-from) before deallocation."); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h new file mode 100644 index 00000000000000..4867608ddfcf89 --- /dev/null +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +class Scheduler; +class ShadowTree; +class MountingCoordinator; +class UIManager; + +/* + * Represents a running React Native surface and provides control over it. + * The instances of this class are movable only. + * The instances of this class can be safely deallocated only if `status` is + * `Unregistered`; this is a way to enforce internal consistency and + * deallocation ordering constraints the core relies on. + * + * + * Even though all methods of the class are thread-safe, the consumer side must + * ensure the logical consistency of some methods (e.g. calling `stop` for + * non-running surface will crash). + */ +class SurfaceHandler final { + public: + /* + * Represents a status of the `SurfaceHandler` instance. + */ + enum class Status { + /* + * Newly created, moved-from, or already-unregistered instances. The only + * state in which the object can be safely deallocated. + */ + Unregistered, + + /* + * Registered instances that have an internal reference to a `UIManager` + * instance and ready to start a surface. + */ + Registered, + + /* + * Registered and running instances. + */ + Running, + }; + + /* + * Defines how visual side effects (views, images, text, and so on) are + * mounted (on not) on the screen. + */ + enum class DisplayMode { + /* + * The surface is running normally. All visual side-effects will be rendered + * on the screen. + */ + Visible, + + /* + * The surface is `Suspended`. All new (committed after switching to the + * mode) visual side-effects will *not* be mounted on the screen (the screen + * will stop updating). + * + * The mode can be used for preparing a surface for possible future use. + * The surface will be prepared without spending computing resources + * on mounting, and then can be instantly mounted if needed. + */ + Suspended, + + /* + * The surface is `Hidden`. All previously mounted visual side-effects + * will be unmounted, and all new (committed after switching to the mode) + * visual side-effects will *not* be mounted on the screen until the mode is + * switched back to `normal`. + * + * The mode can be used for temporarily freeing computing resources of + * off-the-screen surfaces. + */ + Hidden, + }; + + /* + * Can be constructed anytime with a `moduleName` and a `surfaceId`. + */ + SurfaceHandler(std::string const &moduleName, SurfaceId surfaceId) noexcept; + ~SurfaceHandler() noexcept; + + /* + * Movable-only. + */ + SurfaceHandler(SurfaceHandler &&SurfaceHandler) noexcept; + SurfaceHandler(SurfaceHandler const &SurfaceHandler) noexcept = delete; + SurfaceHandler &operator=(SurfaceHandler &&other) noexcept; + SurfaceHandler &operator=(SurfaceHandler const &other) noexcept = delete; + +#pragma mark - Surface Life-Cycle Management + + /* + * Returns a momentum value of the status. + */ + Status getStatus() const noexcept; + + /* + * Starts or stops the surface. + * Can not be called when the status is `Unregistered`. + * `start()` must not be called for a running surface, and `stop()` must not + * be called for a not running surface. + */ + void start() const noexcept; + void stop() const noexcept; + + /* + * Sets (and gets) the runnnig mode. + * The running mode can be changed anytime (even for `Unregistered` surface). + */ + void setDisplayMode(DisplayMode displayMode) const noexcept; + DisplayMode getDisplayMode() const noexcept; + +#pragma mark - Accessors + + SurfaceId getSurfaceId() const noexcept; + std::string getModuleName() const noexcept; + + /* + * Provides access for surface props. + * Props can be changed anytime (even for `Unregistered` surface). + */ + void setProps(folly::dynamic const &props) const noexcept; + folly::dynamic getProps() const noexcept; + + /* + * Returns a `MountingCoordinator` instance associated with a running surface. + * Can be not be called when the status is `Unregistered`. + * The returning value cannot be `nullptr`. + */ + std::shared_ptr getMountingCoordinator() + const noexcept; + +#pragma mark - Layout + + /* + * Measures the surface with given layout constraints and layout context. + * Returns zero size if called on the stopped or unregistered surface. + */ + Size measure( + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept; + + /* + * Sets layout constraints and layout context for the surface. + */ + void constraintLayout( + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept; + + /* + * Returns layout constraints and layout context associated with the surface. + */ + LayoutConstraints getLayoutConstraints() const noexcept; + LayoutContext getLayoutContext() const noexcept; + + private: + friend class Scheduler; + + /* + * Must be called by `Scheduler` during registration process. + */ + void setUIManager(UIManager const *uiManager) const noexcept; + + void applyDisplayMode(DisplayMode displayMode) const noexcept; + +#pragma mark - Link & Parameters + + /* + * All data members of the class are split into two groups (`Link` and + * `Parameters`) that require separate synchronization. This way it's easier + * to see that proper lock is acquired. Separate synchronization is needed to + * prevent deadlocks. + */ + + /* + * Represents parameters of the surface. Parameters can be changed + * independently from controlling the running state + * (registering/unregistering, starting/stopping) of the surface. + * Changing parameters requires acquiring a unique lock; reading needs only + * a shared lock. + */ + struct Parameters { + std::string moduleName{}; + SurfaceId surfaceId{}; + DisplayMode displayMode{DisplayMode::Visible}; + folly::dynamic props{}; + LayoutConstraints layoutConstraints{}; + LayoutContext layoutContext{}; + }; + + /* + * Represents an underlying link to a `ShadowTree` and an `UIMananger`. + * Registering, unregistering, starting, and stopping the surface requires + * acquiring a unique lock; other access needs only a shared lock. + */ + struct Link { + Status status{Status::Unregistered}; + UIManager const *uiManager{}; + ShadowTree const *shadowTree{}; + }; + + /* + * `link_` and `linkMutex_` pair. + */ + mutable better::shared_mutex linkMutex_; + mutable Link link_; + + /* + * `parameters_` and `parametersMutex_` pair. + */ + mutable better::shared_mutex parametersMutex_; + mutable Parameters parameters_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp new file mode 100644 index 00000000000000..2cd0c6ed27a62d --- /dev/null +++ b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "SurfaceManager.h" + +#include + +namespace facebook { +namespace react { + +SurfaceManager::SurfaceManager(Scheduler const &scheduler) noexcept + : scheduler_(scheduler) {} + +void SurfaceManager::startSurface( + SurfaceId surfaceId, + std::string const &moduleName, + folly::dynamic const &props, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept { + { + std::unique_lock lock(mutex_); + auto surfaceHandler = SurfaceHandler{moduleName, surfaceId}; + registry_.emplace(surfaceId, std::move(surfaceHandler)); + } + + visit(surfaceId, [&](SurfaceHandler const &surfaceHandler) { + surfaceHandler.setProps(props); + surfaceHandler.constraintLayout(layoutConstraints, layoutContext); + + scheduler_.registerSurface(surfaceHandler); + + surfaceHandler.start(); + }); +} + +void SurfaceManager::stopSurface(SurfaceId surfaceId) const noexcept { + visit(surfaceId, [&](SurfaceHandler const &surfaceHandler) { + surfaceHandler.stop(); + scheduler_.unregisterSurface(surfaceHandler); + }); + + { + std::unique_lock lock(mutex_); + + auto iterator = registry_.find(surfaceId); + registry_.erase(iterator); + } +} + +Size SurfaceManager::measureSurface( + SurfaceId surfaceId, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept { + auto size = Size{}; + + visit(surfaceId, [&](SurfaceHandler const &surfaceHandler) { + size = surfaceHandler.measure(layoutConstraints, layoutContext); + }); + + return size; +} + +MountingCoordinator::Shared SurfaceManager::findMountingCoordinator( + SurfaceId surfaceId) const noexcept { + auto mountingCoordinator = MountingCoordinator::Shared{}; + + visit(surfaceId, [&](SurfaceHandler const &surfaceHandler) { + mountingCoordinator = surfaceHandler.getMountingCoordinator(); + }); + + return mountingCoordinator; +} + +void SurfaceManager::constraintSurfaceLayout( + SurfaceId surfaceId, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept { + visit(surfaceId, [=](SurfaceHandler const &surfaceHandler) { + surfaceHandler.constraintLayout(layoutConstraints, layoutContext); + }); +} + +void SurfaceManager::visit( + SurfaceId surfaceId, + std::function callback) + const noexcept { + std::shared_lock lock(mutex_); + + auto iterator = registry_.find(surfaceId); + + if (iterator == registry_.end()) { + return; + } + + callback(iterator->second); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/SurfaceManager.h b/ReactCommon/react/renderer/scheduler/SurfaceManager.h new file mode 100644 index 00000000000000..83052f1855d776 --- /dev/null +++ b/ReactCommon/react/renderer/scheduler/SurfaceManager.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +/* + * `SurfaceManager` allows controlling React Native Surfaces via + * `SurfaceHandler` without using `SurfaceHandler` directly. `SurfaceManager` + * maintains a registry of `SurfaceHandler`s and allows to reference to them via + * a `SurfaceId`. + * The is supposed to be used during the transition period only. + */ +class SurfaceManager final { + public: + SurfaceManager(Scheduler const &scheduler) noexcept; + +#pragma mark - Surface Management + + void startSurface( + SurfaceId surfaceId, + std::string const &moduleName, + folly::dynamic const &props, + LayoutConstraints const &layoutConstraints = {}, + LayoutContext const &layoutContext = {}) const noexcept; + + void stopSurface(SurfaceId surfaceId) const noexcept; + + Size measureSurface( + SurfaceId surfaceId, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept; + + void constraintSurfaceLayout( + SurfaceId surfaceId, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const noexcept; + + MountingCoordinator::Shared findMountingCoordinator( + SurfaceId surfaceId) const noexcept; + + private: + void visit( + SurfaceId surfaceId, + std::function callback) + const noexcept; + + Scheduler const &scheduler_; + mutable better::shared_mutex mutex_; // Protects `registry_`. + mutable better::map registry_{}; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/SynchronousEventBeat.cpp b/ReactCommon/react/renderer/scheduler/SynchronousEventBeat.cpp index a30552eb51c29e..245e07b463bcdf 100644 --- a/ReactCommon/react/renderer/scheduler/SynchronousEventBeat.cpp +++ b/ReactCommon/react/renderer/scheduler/SynchronousEventBeat.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#import "SynchronousEventBeat.h" +#include "SynchronousEventBeat.h" namespace facebook { namespace react { diff --git a/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp b/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp index 5c7220f52a44bf..add08294321f05 100644 --- a/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp +++ b/ReactCommon/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp @@ -89,8 +89,8 @@ TEST(UITemplateProcessorTest, testSimpleBytecode) { auto nativeModuleRegistry = buildNativeModuleRegistry(); auto bytecode = R"delim({"version":0.1,"commands":[ - ["createNode",2,"RCTView",-1,{"opacity": 0.5, "testId": "root"}], - ["createNode",4,"RCTView",2,{"testId": "child"}], + ["createNode",2,"RCTView",-1,{"opacity": 0.5, "testID": "root"}], + ["createNode",4,"RCTView",2,{"testID": "child"}], ["returnRoot",2] ]})delim"; @@ -124,11 +124,11 @@ TEST(UITemplateProcessorTest, testConditionalBytecode) { auto nativeModuleRegistry = buildNativeModuleRegistry(); auto bytecode = R"delim({"version":0.1,"commands":[ - ["createNode",2,"RCTView",-1,{"testId": "root"}], + ["createNode",2,"RCTView",-1,{"testID": "root"}], ["loadNativeBool",1,"MobileConfig","getBool",["qe:simple_test"]], ["conditional",1, - [["createNode",4,"RCTView",2,{"testId": "cond_true"}]], - [["createNode",4,"RCTView",2,{"testId": "cond_false"}]] + [["createNode",4,"RCTView",2,{"testID": "cond_true"}]], + [["createNode",4,"RCTView",2,{"testID": "cond_false"}]] ], ["returnRoot",2] ]})delim"; diff --git a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.cpp b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.cpp index 70904ed8b64de8..d3d9845f93c518 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.cpp +++ b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.cpp @@ -8,5 +8,58 @@ #include "TextMeasureCache.h" namespace facebook { -namespace react {} // namespace react +namespace react { + +static Rect rectFromDynamic(folly::dynamic const &data) { + Point origin; + origin.x = data.getDefault("x", 0).getDouble(); + origin.y = data.getDefault("y", 0).getDouble(); + Size size; + size.width = data.getDefault("width", 0).getDouble(); + size.height = data.getDefault("height", 0).getDouble(); + Rect frame; + frame.origin = origin; + frame.size = size; + return frame; +} + +LineMeasurement::LineMeasurement( + std::string text, + Rect frame, + Float descender, + Float capHeight, + Float ascender, + Float xHeight) + : text(text), + frame(frame), + descender(descender), + capHeight(capHeight), + ascender(ascender) {} + +LineMeasurement::LineMeasurement(folly::dynamic const &data) + : text(data.getDefault("text", "").getString()), + frame(rectFromDynamic(data)), + descender(data.getDefault("descender", 0).getDouble()), + capHeight(data.getDefault("capHeight", 0).getDouble()), + ascender(data.getDefault("ascender", 0).getDouble()), + xHeight(data.getDefault("xHeight", 0).getDouble()) {} + +bool LineMeasurement::operator==(LineMeasurement const &rhs) const { + return std::tie( + this->text, + this->frame, + this->descender, + this->capHeight, + this->ascender, + this->xHeight) == + std::tie( + rhs.text, + rhs.frame, + rhs.descender, + rhs.capHeight, + rhs.ascender, + rhs.xHeight); +} + +} // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h index 4a15c17925684b..d0e71872810d75 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h +++ b/ReactCommon/react/renderer/textlayoutmanager/TextMeasureCache.h @@ -23,6 +23,18 @@ struct LineMeasurement { Float capHeight; Float ascender; Float xHeight; + + LineMeasurement( + std::string text, + Rect frame, + Float descender, + Float capHeight, + Float ascender, + Float xHeight); + + LineMeasurement(folly::dynamic const &data); + + bool operator==(LineMeasurement const &rhs) const; }; using LinesMeasurements = std::vector; diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp b/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp index 86b26366874f35..83f8c930311316 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace facebook::jni; @@ -37,56 +38,33 @@ TextMeasurement TextLayoutManager::measure( } TextMeasurement TextLayoutManager::measureCachedSpannableById( - int cacheId, + int64_t cacheId, ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const { - const jni::global_ref &fabricUIManager = - contextContainer_->at>("FabricUIManager"); - auto env = Environment::current(); auto attachmentPositions = env->NewFloatArray(0); - - static auto measure = - jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod("measure"); - auto minimumSize = layoutConstraints.minimumSize; auto maximumSize = layoutConstraints.maximumSize; - local_ref componentName = make_jstring("RCTText"); - folly::dynamic cacheIdMap; + folly::dynamic cacheIdMap = folly::dynamic::object; cacheIdMap["cacheId"] = cacheId; - local_ref attributedStringRNM = - ReadableNativeMap::newObjectCxxArgs(cacheIdMap); - local_ref paragraphAttributesRNM = - ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes)); - local_ref attributedStringRM = make_local( - reinterpret_cast(attributedStringRNM.get())); - local_ref paragraphAttributesRM = make_local( - reinterpret_cast(paragraphAttributesRNM.get())); - auto size = yogaMeassureToSize(measure( - fabricUIManager, + auto size = measureAndroidComponent( + contextContainer_, -1, // TODO: we should pass rootTag in - componentName.get(), - attributedStringRM.get(), - paragraphAttributesRM.get(), + "RCTText", + cacheIdMap, + toDynamic(paragraphAttributes), nullptr, minimumSize.width, maximumSize.width, minimumSize.height, maximumSize.height, - attachmentPositions)); + attachmentPositions); + + // Clean up allocated ref - it still takes up space in the JNI ref table even + // though it's 0 length + env->DeleteLocalRef(attachmentPositions); // TODO: currently we do not support attachments for cached IDs - should we? auto attachments = TextMeasurement::Attachments{}; @@ -94,41 +72,22 @@ TextMeasurement TextLayoutManager::measureCachedSpannableById( return TextMeasurement{size, attachments}; } -TextMeasurement TextLayoutManager::doMeasure( +LinesMeasurements TextLayoutManager::measureLines( AttributedString attributedString, ParagraphAttributes paragraphAttributes, - LayoutConstraints layoutConstraints) const { + Size size) const { const jni::global_ref &fabricUIManager = contextContainer_->at>("FabricUIManager"); - - int attachmentsCount = 0; - for (auto fragment : attributedString.getFragments()) { - if (fragment.isAttachment()) { - attachmentsCount++; - } - } - auto env = Environment::current(); - auto attachmentPositions = env->NewFloatArray(attachmentsCount * 2); - - static auto measure = + static auto measureLines = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethodgetMethod("measure"); - - auto minimumSize = layoutConstraints.minimumSize; - auto maximumSize = layoutConstraints.maximumSize; + jfloat)>("measureLines"); auto serializedAttributedString = toDynamic(attributedString); - local_ref componentName = make_jstring("RCTText"); + local_ref attributedStringRNM = ReadableNativeMap::newObjectCxxArgs(serializedAttributedString); local_ref paragraphAttributesRNM = @@ -138,18 +97,60 @@ TextMeasurement TextLayoutManager::doMeasure( reinterpret_cast(attributedStringRNM.get())); local_ref paragraphAttributesRM = make_local( reinterpret_cast(paragraphAttributesRNM.get())); - auto size = yogaMeassureToSize(measure( + + auto array = measureLines( fabricUIManager, - -1, // TODO: we should pass rootTag in - componentName.get(), attributedStringRM.get(), paragraphAttributesRM.get(), + size.width, + size.height); + + auto dynamicArray = cthis(array)->consume(); + LinesMeasurements lineMeasurements; + lineMeasurements.reserve(dynamicArray.size()); + + for (auto const &data : dynamicArray) { + lineMeasurements.push_back(LineMeasurement(data)); + } + + // Explicitly release smart pointers to free up space faster in JNI tables + attributedStringRM.reset(); + attributedStringRNM.reset(); + paragraphAttributesRM.reset(); + paragraphAttributesRNM.reset(); + + return lineMeasurements; +} + +TextMeasurement TextLayoutManager::doMeasure( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + LayoutConstraints layoutConstraints) const { + int attachmentsCount = 0; + for (auto fragment : attributedString.getFragments()) { + if (fragment.isAttachment()) { + attachmentsCount++; + } + } + auto env = Environment::current(); + auto attachmentPositions = env->NewFloatArray(attachmentsCount * 2); + + auto minimumSize = layoutConstraints.minimumSize; + auto maximumSize = layoutConstraints.maximumSize; + + auto serializedAttributedString = toDynamic(attributedString); + auto size = measureAndroidComponent( + contextContainer_, + -1, // TODO: we should pass rootTag in + "RCTText", + serializedAttributedString, + toDynamic(paragraphAttributes), nullptr, minimumSize.width, maximumSize.width, minimumSize.height, maximumSize.height, - attachmentPositions)); + attachmentPositions); jfloat *attachmentData = env->GetFloatArrayElements(attachmentPositions, 0); @@ -165,15 +166,19 @@ TextMeasurement TextLayoutManager::doMeasure( float width = (float)fragment["width"].getDouble(); float height = (float)fragment["height"].getDouble(); - auto rect = facebook::react::Rect{{left, top}, - facebook::react::Size{width, height}}; + auto rect = facebook::react::Rect{ + {left, top}, facebook::react::Size{width, height}}; attachments.push_back(TextMeasurement::Attachment{rect, false}); attachmentIndex++; } } } - // DELETE REF + + // Clean up allocated ref + env->ReleaseFloatArrayElements( + attachmentPositions, attachmentData, JNI_ABORT); env->DeleteLocalRef(attachmentPositions); + return TextMeasurement{size, attachments}; } diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h b/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h index 926a9498f289b6..681c54e22fb793 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h @@ -42,10 +42,19 @@ class TextLayoutManager { * opaque cache ID. */ TextMeasurement measureCachedSpannableById( - int cacheId, + int64_t cacheId, ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const; + /* + * Measures lines of `attributedString` using native text rendering + * infrastructure. + */ + LinesMeasurements measureLines( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + Size size) const; + /* * Returns an opaque pointer to platform-specific TextLayoutManager. * Is used on a native views layer to delegate text rendering to the manager. diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp b/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp index ffdfeae66d547e..6d7f07ea6d1edb 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp @@ -13,15 +13,29 @@ namespace react { TextLayoutManager::~TextLayoutManager() {} void *TextLayoutManager::getNativeTextLayoutManager() const { - return self_; + return (void *)this; } TextMeasurement TextLayoutManager::measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const { - return TextMeasurement{{0, 0}, {}}; + TextMeasurement::Attachments attachments; + for (auto const &fragment : attributedStringBox.getValue().getFragments()) { + if (fragment.isAttachment()) { + attachments.push_back( + TextMeasurement::Attachment{{{0, 0}, {0, 0}}, false}); + } + } + return TextMeasurement{{0, 0}, attachments}; } +LinesMeasurements TextLayoutManager::measureLines( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + Size size) const { + return {}; +}; + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h b/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h index 7033cdeafe3b41..87c6fdf4bfeca7 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h @@ -28,8 +28,7 @@ using SharedTextLayoutManager = std::shared_ptr; */ class TextLayoutManager { public: - TextLayoutManager(const ContextContainer::Shared &contextContainer) - : contextContainer_(contextContainer){}; + TextLayoutManager(const ContextContainer::Shared &contextContainer) {} ~TextLayoutManager(); /* @@ -40,16 +39,20 @@ class TextLayoutManager { ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const; + /* + * Measures lines of `attributedString` using native text rendering + * infrastructure. + */ + LinesMeasurements measureLines( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + Size size) const; + /* * Returns an opaque pointer to platform-specific TextLayoutManager. * Is used on a native views layer to delegate text rendering to the manager. */ void *getNativeTextLayoutManager() const; - - private: - void *self_; - - ContextContainer::Shared contextContainer_; }; } // namespace react diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm index 0f23297ad4afb9..496ae69979b4a9 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm @@ -41,15 +41,16 @@ inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight) assert(fontWeight > 50); assert(fontWeight < 950); - static UIFontWeight weights[] = {/* ~100 */ UIFontWeightUltraLight, - /* ~200 */ UIFontWeightThin, - /* ~300 */ UIFontWeightLight, - /* ~400 */ UIFontWeightRegular, - /* ~500 */ UIFontWeightMedium, - /* ~600 */ UIFontWeightSemibold, - /* ~700 */ UIFontWeightBold, - /* ~800 */ UIFontWeightHeavy, - /* ~900 */ UIFontWeightBlack}; + static UIFontWeight weights[] = { + /* ~100 */ UIFontWeightUltraLight, + /* ~200 */ UIFontWeightThin, + /* ~300 */ UIFontWeightLight, + /* ~400 */ UIFontWeightRegular, + /* ~500 */ UIFontWeightMedium, + /* ~600 */ UIFontWeightSemibold, + /* ~700 */ UIFontWeightBold, + /* ~800 */ UIFontWeightHeavy, + /* ~900 */ UIFontWeightBlack}; // The expression is designed to convert something like 760 or 830 to 7. return weights[(fontWeight + 50) / 100 - 1]; } @@ -319,8 +320,9 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex if (fragment.isAttachment()) { auto layoutMetrics = fragment.parentShadowView.layoutMetrics; - CGRect bounds = {.origin = {.x = layoutMetrics.frame.origin.x, .y = layoutMetrics.frame.origin.y}, - .size = {.width = layoutMetrics.frame.size.width, .height = layoutMetrics.frame.size.height}}; + CGRect bounds = { + .origin = {.x = layoutMetrics.frame.origin.x, .y = layoutMetrics.frame.origin.y}, + .size = {.width = layoutMetrics.frame.size.width, .height = layoutMetrics.frame.size.height}}; NSTextAttachment *attachment = [NSTextAttachment new]; attachment.image = placeholderImage; diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm index 13ca3c5ae2cd58..3cd00abda54dac 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm @@ -75,12 +75,14 @@ - (TextMeasurement)measureNSAttributedString:(NSAttributedString *)attributedStr UIFont *font = [textStorage attribute:NSFontAttributeName atIndex:range.location effectiveRange:nil]; - CGRect frame = {{glyphRect.origin.x, - glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender}, - attachmentSize}; + CGRect frame = { + {glyphRect.origin.x, + glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender}, + attachmentSize}; - auto rect = facebook::react::Rect{facebook::react::Point{frame.origin.x, frame.origin.y}, - facebook::react::Size{frame.size.width, frame.size.height}}; + auto rect = facebook::react::Rect{ + facebook::react::Point{frame.origin.x, frame.origin.y}, + facebook::react::Size{frame.size.width, frame.size.height}}; attachments.push_back(TextMeasurement::Attachment{rect, false}); }]; @@ -156,12 +158,13 @@ - (LinesMeasurements)getLinesForAttributedString:(facebook::react::AttributedStr auto rect = facebook::react::Rect{ facebook::react::Point{usedRect.origin.x, usedRect.origin.y}, facebook::react::Size{usedRect.size.width, usedRect.size.height}}; - auto line = LineMeasurement{std::string([renderedString UTF8String]), - rect, - -font.descender, - font.capHeight, - font.ascender, - font.xHeight}; + auto line = LineMeasurement{ + std::string([renderedString UTF8String]), + rect, + -font.descender, + font.capHeight, + font.ascender, + font.xHeight}; blockParagraphLines->push_back(line); }]; return paragraphLines; diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h index fdfb6e2ce61c68..c78daec7b7a3d5 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h +++ b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h @@ -96,7 +96,24 @@ inline static NSUnderlineStyle RCTNSUnderlineStyleFromStyleAndPattern( return style; } -inline static UIColor *RCTUIColorFromSharedColor(const SharedColor &color) +inline static UIColor *RCTUIColorFromSharedColor(const SharedColor &sharedColor) { - return color ? [UIColor colorWithCGColor:color.get()] : nil; + if (!sharedColor) { + return nil; + } + + if (*facebook::react::clearColor() == *sharedColor) { + return [UIColor clearColor]; + } + + if (*facebook::react::blackColor() == *sharedColor) { + return [UIColor blackColor]; + } + + if (*facebook::react::whiteColor() == *sharedColor) { + return [UIColor whiteColor]; + } + + auto components = facebook::react::colorComponentsFromColor(sharedColor); + return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; } diff --git a/ReactCommon/react/renderer/uimanager/UIManager.cpp b/ReactCommon/react/renderer/uimanager/UIManager.cpp index 701e9e83ee435a..6b31bf8e99067c 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include @@ -33,9 +35,9 @@ SharedShadowNode UIManager::createNode( auto fallbackDescriptor = componentDescriptorRegistry_->getFallbackComponentDescriptor(); - auto family = componentDescriptor.createFamily( - ShadowNodeFamilyFragment{tag, surfaceId, nullptr}, - std::move(eventTarget)); + auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr}; + auto family = + componentDescriptor.createFamily(fragment, std::move(eventTarget)); auto const props = componentDescriptor.cloneProps(nullptr, rawProps); auto const state = componentDescriptor.createInitialState(ShadowNodeFragment{props}, family); @@ -92,20 +94,21 @@ void UIManager::appendChild( void UIManager::completeSurface( SurfaceId surfaceId, - const SharedShadowNodeUnsharedList &rootChildren) const { + SharedShadowNodeUnsharedList const &rootChildren, + ShadowTree::CommitOptions commitOptions) const { SystraceSection s("UIManager::completeSurface"); shadowTreeRegistry_.visit(surfaceId, [&](ShadowTree const &shadowTree) { shadowTree.commit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { + [&](RootShadowNode const &oldRootShadowNode) { return std::make_shared( - *oldRootShadowNode, + oldRootShadowNode, ShadowNodeFragment{ /* .props = */ ShadowNodeFragment::propsPlaceholder(), /* .children = */ rootChildren, }); }, - true); + commitOptions); }); } @@ -124,27 +127,68 @@ void UIManager::clearJSResponder() const { } } -ShadowNode::Shared UIManager::getNewestCloneOfShadowNode( - ShadowNode const &shadowNode) const { - auto findNewestChildInParent = - [&](auto const &parentNode) -> ShadowNode::Shared { - for (auto const &child : parentNode.getChildren()) { - if (ShadowNode::sameFamily(*child, shadowNode)) { - return child; - } +ShadowTree const &UIManager::startSurface( + SurfaceId surfaceId, + std::string const &moduleName, + folly::dynamic const &props, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const { + SystraceSection s("UIManager::startSurface"); + + auto shadowTree = std::make_unique( + surfaceId, layoutConstraints, layoutContext, *this); + auto shadowTreePointer = shadowTree.get(); + shadowTreeRegistry_.add(std::move(shadowTree)); + + runtimeExecutor_([=](jsi::Runtime &runtime) { + auto uiManagerBinding = UIManagerBinding::getBinding(runtime); + if (!uiManagerBinding) { + return; } - return nullptr; - }; + uiManagerBinding->startSurface(runtime, surfaceId, moduleName, props); + }); + + return *shadowTreePointer; +} + +void UIManager::stopSurface(SurfaceId surfaceId) const { + SystraceSection s("UIManager::stopSurface"); + + // Stop any ongoing animations. + stopSurfaceForAnimationDelegate(surfaceId); + + // Waiting for all concurrent commits to be finished and unregistering the + // `ShadowTree`. + auto shadowTree = getShadowTreeRegistry().remove(surfaceId); + + // As part of stopping a Surface, we need to properly destroy all + // mounted views, so we need to commit an empty tree to trigger all + // side-effects (including destroying and removing mounted views). + if (shadowTree) { + shadowTree->commitEmptyTree(); + } + + // We execute JavaScript/React part of the process at the very end to minimize + // any visible side-effects of stopping the Surface. Any possible commits from + // the JavaScript side will not be able to reference a `ShadowTree` and will + // fail silently. + runtimeExecutor_([=](jsi::Runtime &runtime) { + auto uiManagerBinding = UIManagerBinding::getBinding(runtime); + if (!uiManagerBinding) { + return; + } + + uiManagerBinding->stopSurface(runtime, surfaceId); + }); +} + +ShadowNode::Shared UIManager::getNewestCloneOfShadowNode( + ShadowNode const &shadowNode) const { auto ancestorShadowNode = ShadowNode::Shared{}; shadowTreeRegistry_.visit( shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) { - shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - ancestorShadowNode = oldRootShadowNode; - return nullptr; - }, - true); + ancestorShadowNode = shadowTree.getCurrentRevision().rootShadowNode; }); if (!ancestorShadowNode) { @@ -157,7 +201,8 @@ ShadowNode::Shared UIManager::getNewestCloneOfShadowNode( return nullptr; } - return findNewestChildInParent(ancestors.rbegin()->first.get()); + auto pair = ancestors.rbegin(); + return pair->first.get().getChildren().at(pair->second); } ShadowNode::Shared UIManager::findNodeAtPoint( @@ -167,31 +212,6 @@ ShadowNode::Shared UIManager::findNodeAtPoint( getNewestCloneOfShadowNode(*node), point); } -void UIManager::setNativeProps( - ShadowNode const &shadowNode, - RawProps const &rawProps) const { - SystraceSection s("UIManager::setNativeProps"); - - auto &componentDescriptor = shadowNode.getComponentDescriptor(); - auto props = componentDescriptor.cloneProps(shadowNode.getProps(), rawProps); - - shadowTreeRegistry_.visit( - shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) { - shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - return std::static_pointer_cast( - oldRootShadowNode->cloneTree( - shadowNode.getFamily(), - [&](ShadowNode const &oldShadowNode) { - return oldShadowNode.clone({ - /* .props = */ props, - }); - })); - }, - true); - }); -} - LayoutMetrics UIManager::getRelativeLayoutMetrics( ShadowNode const &shadowNode, ShadowNode const *ancestorShadowNode, @@ -205,13 +225,9 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics( if (!ancestorShadowNode) { shadowTreeRegistry_.visit( shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) { - shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - owningAncestorShadowNode = oldRootShadowNode; - ancestorShadowNode = oldRootShadowNode.get(); - return nullptr; - }, - true); + owningAncestorShadowNode = + shadowTree.getCurrentRevision().rootShadowNode; + ancestorShadowNode = owningAncestorShadowNode.get(); }); } else { // It is possible for JavaScript (or other callers) to have a reference @@ -239,27 +255,34 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const { shadowTreeRegistry_.visit( family->getSurfaceId(), [&](ShadowTree const &shadowTree) { - bool updateSucceeded = shadowTree.tryCommit( - [&](RootShadowNode::Shared const &oldRootShadowNode) { - return std::static_pointer_cast< - RootShadowNode>(oldRootShadowNode->cloneTree( - *family, [&](ShadowNode const &oldShadowNode) { - auto newData = - callback(oldShadowNode.getState()->getDataPointer()); - auto newState = - componentDescriptor.createState(*family, newData); - - return oldShadowNode.clone({ - /* .props = */ ShadowNodeFragment::propsPlaceholder(), - /* .children = */ - ShadowNodeFragment::childrenPlaceholder(), - /* .state = */ newState, - }); - })); - }); - if (!updateSucceeded && stateUpdate.failureCallback) { - stateUpdate.failureCallback(); - } + shadowTree.commit([&](RootShadowNode const &oldRootShadowNode) { + auto isValid = true; + + auto rootNode = oldRootShadowNode.cloneTree( + *family, [&](ShadowNode const &oldShadowNode) { + auto newData = + callback(oldShadowNode.getState()->getDataPointer()); + + if (!newData) { + isValid = false; + // Just return something, we will discard it anyway. + return oldShadowNode.clone({}); + } + + auto newState = + componentDescriptor.createState(*family, newData); + + return oldShadowNode.clone({ + /* .props = */ ShadowNodeFragment::propsPlaceholder(), + /* .children = */ + ShadowNodeFragment::childrenPlaceholder(), + /* .state = */ newState, + }); + }); + + return isValid ? std::static_pointer_cast(rootNode) + : nullptr; + }); }); } @@ -272,11 +295,19 @@ void UIManager::dispatchCommand( } } +void UIManager::sendAccessibilityEvent( + const ShadowNode::Shared &shadowNode, + std::string const &eventType) { + if (delegate_) { + delegate_->uiManagerDidSendAccessibilityEvent(shadowNode, eventType); + } +} + void UIManager::configureNextLayoutAnimation( jsi::Runtime &runtime, RawValue const &config, - const jsi::Value &successCallback, - const jsi::Value &failureCallback) const { + jsi::Value const &successCallback, + jsi::Value const &failureCallback) const { if (animationDelegate_) { animationDelegate_->uiManagerDidConfigureNextLayoutAnimation( runtime, @@ -304,9 +335,21 @@ void UIManager::setBackgroundExecutor( backgroundExecutor_ = backgroundExecutor; } +void UIManager::setRuntimeExecutor(RuntimeExecutor const &runtimeExecutor) { + runtimeExecutor_ = runtimeExecutor; +} + void UIManager::visitBinding( - std::function callback) - const { + std::function callback, + jsi::Runtime &runtime) const { + if (extractUIManagerBindingOnDemand_) { + auto uiManagerBinding = UIManagerBinding::getBinding(runtime); + if (uiManagerBinding) { + callback(*uiManagerBinding_); + } + return; + } + if (!uiManagerBinding_) { return; } @@ -318,8 +361,43 @@ ShadowTreeRegistry const &UIManager::getShadowTreeRegistry() const { return shadowTreeRegistry_; } +void UIManager::registerCommitHook( + UIManagerCommitHook const &commitHook) const { + std::unique_lock lock(commitHookMutex_); + assert( + std::find(commitHooks_.begin(), commitHooks_.end(), &commitHook) == + commitHooks_.end()); + commitHook.commitHookWasRegistered(*this); + commitHooks_.push_back(&commitHook); +} + +void UIManager::unregisterCommitHook( + UIManagerCommitHook const &commitHook) const { + std::unique_lock lock(commitHookMutex_); + auto iterator = + std::find(commitHooks_.begin(), commitHooks_.end(), &commitHook); + assert(iterator != commitHooks_.end()); + commitHooks_.erase(iterator); + commitHook.commitHookWasUnregistered(*this); +} + #pragma mark - ShadowTreeDelegate +RootShadowNode::Unshared UIManager::shadowTreeWillCommit( + ShadowTree const &shadowTree, + RootShadowNode::Shared const &oldRootShadowNode, + RootShadowNode::Unshared const &newRootShadowNode) const { + std::shared_lock lock(commitHookMutex_); + + auto resultRootShadowNode = newRootShadowNode; + for (auto const *commitHook : commitHooks_) { + resultRootShadowNode = commitHook->shadowTreeWillCommit( + shadowTree, oldRootShadowNode, resultRootShadowNode); + } + + return resultRootShadowNode; +} + void UIManager::shadowTreeDidFinishTransaction( ShadowTree const &shadowTree, MountingCoordinator::Shared const &mountingCoordinator) const { @@ -336,7 +414,7 @@ void UIManager::setAnimationDelegate(UIManagerAnimationDelegate *delegate) { animationDelegate_ = delegate; } -void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) { +void UIManager::stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const { if (animationDelegate_ != nullptr) { animationDelegate_->stopSurface(surfaceId); } diff --git a/ReactCommon/react/renderer/uimanager/UIManager.h b/ReactCommon/react/renderer/uimanager/UIManager.h index 1b3f5d73aa50e8..6dc8a44f968066 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/ReactCommon/react/renderer/uimanager/UIManager.h @@ -10,6 +10,8 @@ #include #include +#include + #include #include #include @@ -25,6 +27,7 @@ namespace facebook { namespace react { class UIManagerBinding; +class UIManagerCommitHook; class UIManager final : public ShadowTreeDelegate { public: @@ -41,6 +44,8 @@ class UIManager final : public ShadowTreeDelegate { void setDelegate(UIManagerDelegate *delegate); UIManagerDelegate *getDelegate(); + void setRuntimeExecutor(RuntimeExecutor const &runtimeExecutor); + void setBackgroundExecutor(BackgroundExecutor const &backgroundExecutor); /** @@ -53,7 +58,7 @@ class UIManager final : public ShadowTreeDelegate { /** * Execute stopSurface on any UIMAnagerAnimationDelegate. */ - void stopSurfaceForAnimationDelegate(SurfaceId surfaceId); + void stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const; void animationTick(); @@ -64,8 +69,28 @@ class UIManager final : public ShadowTreeDelegate { * The callback is called synchronously on the same thread. */ void visitBinding( - std::function callback) - const; + std::function callback, + jsi::Runtime &runtime) const; + + /* + * Registers and unregisters a commit hook. + */ + void registerCommitHook(UIManagerCommitHook const &commitHook) const; + void unregisterCommitHook(UIManagerCommitHook const &commitHook) const; + + ShadowNode::Shared getNewestCloneOfShadowNode( + ShadowNode const &shadowNode) const; + +#pragma mark - Surface Start & Stop + + ShadowTree const &startSurface( + SurfaceId surfaceId, + std::string const &moduleName, + folly::dynamic const &props, + LayoutConstraints const &layoutConstraints, + LayoutContext const &layoutContext) const; + + void stopSurface(SurfaceId surfaceId) const; #pragma mark - ShadowTreeDelegate @@ -73,9 +98,15 @@ class UIManager final : public ShadowTreeDelegate { ShadowTree const &shadowTree, MountingCoordinator::Shared const &mountingCoordinator) const override; + RootShadowNode::Unshared shadowTreeWillCommit( + ShadowTree const &shadowTree, + RootShadowNode::Shared const &oldRootShadowNode, + RootShadowNode::Unshared const &newRootShadowNode) const override; + private: friend class UIManagerBinding; friend class Scheduler; + friend class SurfaceHandler; ShadowNode::Shared createNode( Tag tag, @@ -95,10 +126,8 @@ class UIManager final : public ShadowTreeDelegate { void completeSurface( SurfaceId surfaceId, - const SharedShadowNodeUnsharedList &rootChildren) const; - - void setNativeProps(ShadowNode const &shadowNode, RawProps const &rawProps) - const; + SharedShadowNodeUnsharedList const &rootChildren, + ShadowTree::CommitOptions commitOptions) const; void setJSResponder( const ShadowNode::Shared &shadowNode, @@ -110,9 +139,6 @@ class UIManager final : public ShadowTreeDelegate { ShadowNode::Shared const &shadowNode, Point point) const; - ShadowNode::Shared getNewestCloneOfShadowNode( - ShadowNode const &shadowNode) const; - /* * Returns layout metrics of given `shadowNode` relative to * `ancestorShadowNode` (relative to the root node in case if provided @@ -134,6 +160,10 @@ class UIManager final : public ShadowTreeDelegate { std::string const &commandName, folly::dynamic const args) const; + void sendAccessibilityEvent( + const ShadowNode::Shared &shadowNode, + std::string const &eventType); + /** * Configure a LayoutAnimation to happen on the next commit. * This API configures a global LayoutAnimation starting from the root node. @@ -141,8 +171,8 @@ class UIManager final : public ShadowTreeDelegate { void configureNextLayoutAnimation( jsi::Runtime &runtime, RawValue const &config, - const jsi::Value &successCallback, - const jsi::Value &failureCallback) const; + jsi::Value const &successCallback, + jsi::Value const &failureCallback) const; ShadowTreeRegistry const &getShadowTreeRegistry() const; @@ -150,8 +180,14 @@ class UIManager final : public ShadowTreeDelegate { UIManagerDelegate *delegate_; UIManagerAnimationDelegate *animationDelegate_{nullptr}; UIManagerBinding *uiManagerBinding_; + RuntimeExecutor runtimeExecutor_{}; ShadowTreeRegistry shadowTreeRegistry_{}; BackgroundExecutor backgroundExecutor_{}; + + mutable better::shared_mutex commitHookMutex_; + mutable std::vector commitHooks_; + + bool extractUIManagerBindingOnDemand_{}; }; } // namespace react diff --git a/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h b/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h index cfbb0c00e558ea..9e55d1f3862e91 100644 --- a/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h +++ b/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h @@ -26,8 +26,8 @@ class UIManagerAnimationDelegate { virtual void uiManagerDidConfigureNextLayoutAnimation( jsi::Runtime &runtime, RawValue const &config, - const jsi::Value &successCallback, - const jsi::Value &failureCallback) const = 0; + jsi::Value const &successCallback, + jsi::Value const &failureCallback) const = 0; /** * Set ComponentDescriptor registry. diff --git a/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 10a9dce3cdaa86..3dc2495bf7ff19 100644 --- a/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -7,17 +7,17 @@ #include "UIManagerBinding.h" -#include - #include #include +#include +#include namespace facebook { namespace react { static jsi::Object getModule( jsi::Runtime &runtime, - const std::string &moduleName) { + std::string const &moduleName) { auto batchedBridge = runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge"); auto getCallableModule = @@ -55,6 +55,20 @@ std::shared_ptr UIManagerBinding::createAndInstallIfNeeded( return uiManagerObject.getHostObject(runtime); } +std::shared_ptr UIManagerBinding::getBinding( + jsi::Runtime &runtime) { + auto uiManagerModuleName = "nativeFabricUIManager"; + + auto uiManagerValue = + runtime.global().getProperty(runtime, uiManagerModuleName); + if (uiManagerValue.isUndefined()) { + return nullptr; + } + + auto uiManagerObject = uiManagerValue.asObject(runtime); + return uiManagerObject.getHostObject(runtime); +} + UIManagerBinding::~UIManagerBinding() { LOG(WARNING) << "UIManagerBinding::~UIManagerBinding() was called (address: " << this << ")."; @@ -82,8 +96,8 @@ void UIManagerBinding::attach(std::shared_ptr const &uiManager) { void UIManagerBinding::startSurface( jsi::Runtime &runtime, SurfaceId surfaceId, - const std::string &moduleName, - const folly::dynamic &initalProps) const { + std::string const &moduleName, + folly::dynamic const &initalProps) const { folly::dynamic parameters = folly::dynamic::object(); parameters["rootTag"] = surfaceId; parameters["initialProps"] = initalProps; @@ -113,10 +127,15 @@ void UIManagerBinding::startSurface( void UIManagerBinding::stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId) const { - if (runtime.global().hasProperty(runtime, "RN$stopSurface")) { - auto method = - runtime.global().getPropertyAsFunction(runtime, "RN$stopSurface"); - method.call(runtime, {jsi::Value{surfaceId}}); + auto global = runtime.global(); + if (global.hasProperty(runtime, "RN$Bridgeless")) { + if (!global.hasProperty(runtime, "RN$stopSurface")) { + // ReactFabric module has not been loaded yet; there's no surface to stop. + return; + } + // Bridgeless mode uses a custom JSI binding instead of callable module. + global.getPropertyAsFunction(runtime, "RN$stopSurface") + .call(runtime, {jsi::Value{surfaceId}}); } else { auto module = getModule(runtime, "ReactFabric"); auto method = @@ -128,13 +147,18 @@ void UIManagerBinding::stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId) void UIManagerBinding::dispatchEvent( jsi::Runtime &runtime, - const EventTarget *eventTarget, - const std::string &type, - const ValueFactory &payloadFactory) const { + EventTarget const *eventTarget, + std::string const &type, + ValueFactory const &payloadFactory) const { SystraceSection s("UIManagerBinding::dispatchEvent"); auto payload = payloadFactory(runtime); + // If a payload is null, the factory has decided to cancel the event + if (payload.isNull()) { + return; + } + auto instanceHandle = eventTarget ? [&]() { auto instanceHandle = eventTarget->getInstanceHandle(runtime); @@ -153,7 +177,7 @@ void UIManagerBinding::dispatchEvent( : jsi::Value::null(); auto &eventHandlerWrapper = - static_cast(*eventHandler_); + static_cast(*eventHandler_); eventHandlerWrapper.callback.call( runtime, @@ -168,7 +192,7 @@ void UIManagerBinding::invalidate() const { jsi::Value UIManagerBinding::get( jsi::Runtime &runtime, - const jsi::PropNameID &name) { + jsi::PropNameID const &name) { auto methodName = name.utf8(runtime); // Convert shared_ptr to a raw ptr @@ -208,9 +232,9 @@ jsi::Value UIManagerBinding::get( 5, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { return valueFromShadowNode( runtime, uiManager->createNode( @@ -230,9 +254,9 @@ jsi::Value UIManagerBinding::get( 1, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { return valueFromShadowNode( runtime, uiManager->cloneNode(shadowNodeFromValue(runtime, arguments[0]))); @@ -246,9 +270,9 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { uiManager->setJSResponder( shadowNodeFromValue(runtime, arguments[0]), arguments[1].getBool()); @@ -264,9 +288,9 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto node = shadowNodeFromValue(runtime, arguments[0]); auto locationX = (Float)arguments[1].getNumber(); auto locationY = (Float)arguments[2].getNumber(); @@ -294,9 +318,9 @@ jsi::Value UIManagerBinding::get( 0, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { uiManager->clearJSResponder(); return jsi::Value::undefined(); @@ -311,9 +335,9 @@ jsi::Value UIManagerBinding::get( 1, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { return valueFromShadowNode( runtime, uiManager->cloneNode( @@ -330,10 +354,10 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { - const auto &rawProps = RawProps(runtime, arguments[1]); + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { + auto const &rawProps = RawProps(runtime, arguments[1]); return valueFromShadowNode( runtime, uiManager->cloneNode( @@ -351,10 +375,10 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { - const auto &rawProps = RawProps(runtime, arguments[1]); + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { + auto const &rawProps = RawProps(runtime, arguments[1]); return valueFromShadowNode( runtime, uiManager->cloneNode( @@ -371,9 +395,9 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { uiManager->appendChild( shadowNodeFromValue(runtime, arguments[0]), shadowNodeFromValue(runtime, arguments[1])); @@ -387,9 +411,9 @@ jsi::Value UIManagerBinding::get( name, 1, [](jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto shadowNodeList = std::make_shared(SharedShadowNodeList({})); return valueFromShadowNodeList(runtime, shadowNodeList); @@ -402,9 +426,9 @@ jsi::Value UIManagerBinding::get( name, 2, [](jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto shadowNodeList = shadowNodeListFromValue(runtime, arguments[0]); auto shadowNode = shadowNodeFromValue(runtime, arguments[1]); shadowNodeList->push_back(shadowNode); @@ -420,34 +444,30 @@ jsi::Value UIManagerBinding::get( runtime, name, 2, - [uiManager, sharedUIManager = uiManager_]( + [sharedUIManager = uiManager_]( jsi::Runtime &runtime, jsi::Value const &thisValue, jsi::Value const *arguments, - size_t count) -> jsi::Value { - try { - auto surfaceId = surfaceIdFromValue(runtime, arguments[0]); - auto shadowNodeList = - shadowNodeListFromValue(runtime, arguments[1]); - - if (sharedUIManager->backgroundExecutor_) { - sharedUIManager->backgroundExecutor_( - [sharedUIManager, surfaceId, shadowNodeList] { - sharedUIManager->completeSurface( - surfaceId, shadowNodeList); - }); - } else { - uiManager->completeSurface(surfaceId, shadowNodeList); - } - } catch (std::exception const &e) { - LOG(ERROR) << "Exception in UIManagerBinding::completeRoot(): " - << e.what(); - abort(); - } catch (...) { - LOG(ERROR) - << "Exception in UIManagerBinding::completeRoot(): Unknown."; - abort(); - } + size_t count) noexcept -> jsi::Value { + auto surfaceId = surfaceIdFromValue(runtime, arguments[0]); + auto shadowNodeList = + shadowNodeListFromValue(runtime, arguments[1]); + static std::atomic_uint_fast8_t completeRootEventCounter{0}; + static std::atomic_uint_fast32_t mostRecentSurfaceId{0}; + completeRootEventCounter += 1; + mostRecentSurfaceId = surfaceId; + sharedUIManager->backgroundExecutor_( + [=, eventCount = completeRootEventCounter.load()] { + auto shouldYield = [=]() -> bool { + // If `completeRootEventCounter` was incremented, another + // `completeSurface` call has been scheduled and current + // `completeSurface` should yield to it. + return completeRootEventCounter > eventCount && + mostRecentSurfaceId == surfaceId; + }; + sharedUIManager->completeSurface( + surfaceId, shadowNodeList, {true, shouldYield}); + }); return jsi::Value::undefined(); }); @@ -462,20 +482,11 @@ jsi::Value UIManagerBinding::get( jsi::Runtime &runtime, jsi::Value const &thisValue, jsi::Value const *arguments, - size_t count) -> jsi::Value { - try { - uiManager->completeSurface( - surfaceIdFromValue(runtime, arguments[0]), - shadowNodeListFromValue(runtime, arguments[1])); - } catch (std::exception const &e) { - LOG(ERROR) << "Exception in UIManagerBinding::completeRoot(): " - << e.what(); - abort(); - } catch (...) { - LOG(ERROR) - << "Exception in UIManagerBinding::completeRoot(): Unknown."; - abort(); - } + size_t count) noexcept -> jsi::Value { + uiManager->completeSurface( + surfaceIdFromValue(runtime, arguments[0]), + shadowNodeListFromValue(runtime, arguments[1]), + {true, {}}); return jsi::Value::undefined(); }); @@ -489,9 +500,9 @@ jsi::Value UIManagerBinding::get( 1, [this]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto eventHandler = arguments[0].getObject(runtime).getFunction(runtime); eventHandler_ = @@ -507,9 +518,9 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto layoutMetrics = uiManager->getRelativeLayoutMetrics( *shadowNodeFromValue(runtime, arguments[0]), shadowNodeFromValue(runtime, arguments[1]).get(), @@ -531,9 +542,9 @@ jsi::Value UIManagerBinding::get( 3, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { uiManager->dispatchCommand( shadowNodeFromValue(runtime, arguments[0]), stringFromValue(runtime, arguments[1]), @@ -551,9 +562,9 @@ jsi::Value UIManagerBinding::get( 4, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto layoutMetrics = uiManager->getRelativeLayoutMetrics( *shadowNodeFromValue(runtime, arguments[0]), shadowNodeFromValue(runtime, arguments[1]).get(), @@ -587,13 +598,12 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { + auto shadowNode = shadowNodeFromValue(runtime, arguments[0]); auto layoutMetrics = uiManager->getRelativeLayoutMetrics( - *shadowNodeFromValue(runtime, arguments[0]), - nullptr, - {/* .includeTransform = */ true}); + *shadowNode, nullptr, {/* .includeTransform = */ true}); auto onSuccessFunction = arguments[1].getObject(runtime).getFunction(runtime); @@ -601,12 +611,20 @@ jsi::Value UIManagerBinding::get( onSuccessFunction.call(runtime, {0, 0, 0, 0, 0, 0}); return jsi::Value::undefined(); } + auto newestCloneOfShadowNode = + uiManager->getNewestCloneOfShadowNode(*shadowNode); + + auto layoutableShadowNode = traitCast( + newestCloneOfShadowNode.get()); + Point originRelativeToParent = layoutableShadowNode + ? layoutableShadowNode->getLayoutMetrics().frame.origin + : Point(); auto frame = layoutMetrics.frame; onSuccessFunction.call( runtime, - {0, - 0, + {jsi::Value{runtime, (double)originRelativeToParent.x}, + jsi::Value{runtime, (double)originRelativeToParent.y}, jsi::Value{runtime, (double)frame.size.width}, jsi::Value{runtime, (double)frame.size.height}, jsi::Value{runtime, (double)frame.origin.x}, @@ -622,9 +640,9 @@ jsi::Value UIManagerBinding::get( 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { auto layoutMetrics = uiManager->getRelativeLayoutMetrics( *shadowNodeFromValue(runtime, arguments[0]), nullptr, @@ -650,19 +668,19 @@ jsi::Value UIManagerBinding::get( }); } - if (methodName == "setNativeProps") { + if (methodName == "sendAccessibilityEvent") { return jsi::Function::createFromHostFunction( runtime, name, 2, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { - uiManager->setNativeProps( - *shadowNodeFromValue(runtime, arguments[0]), - RawProps(runtime, arguments[1])); + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { + uiManager->sendAccessibilityEvent( + shadowNodeFromValue(runtime, arguments[0]), + stringFromValue(runtime, arguments[1])); return jsi::Value::undefined(); }); @@ -675,9 +693,9 @@ jsi::Value UIManagerBinding::get( 3, [uiManager]( jsi::Runtime &runtime, - const jsi::Value &thisValue, - const jsi::Value *arguments, - size_t count) -> jsi::Value { + jsi::Value const &thisValue, + jsi::Value const *arguments, + size_t count) noexcept -> jsi::Value { uiManager->configureNextLayoutAnimation( runtime, // TODO: pass in JSI value instead of folly::dynamic to RawValue diff --git a/ReactCommon/react/renderer/uimanager/UIManagerBinding.h b/ReactCommon/react/renderer/uimanager/UIManagerBinding.h index d4e133f59d38d4..aeb98d3289de38 100644 --- a/ReactCommon/react/renderer/uimanager/UIManagerBinding.h +++ b/ReactCommon/react/renderer/uimanager/UIManagerBinding.h @@ -31,6 +31,12 @@ class UIManagerBinding : public jsi::HostObject { static std::shared_ptr createAndInstallIfNeeded( jsi::Runtime &runtime); + /* + * Returns a pointer to UIManagerBinding previously installed into a runtime. + * Thread synchronization must be enforced externally. + */ + static std::shared_ptr getBinding(jsi::Runtime &runtime); + ~UIManagerBinding(); /* @@ -47,8 +53,8 @@ class UIManagerBinding : public jsi::HostObject { void startSurface( jsi::Runtime &runtime, SurfaceId surfaceId, - const std::string &moduleName, - const folly::dynamic &initalProps) const; + std::string const &moduleName, + folly::dynamic const &initalProps) const; /* * Stops React Native Surface with given id. @@ -62,9 +68,9 @@ class UIManagerBinding : public jsi::HostObject { */ void dispatchEvent( jsi::Runtime &runtime, - const EventTarget *eventTarget, - const std::string &type, - const ValueFactory &payloadFactory) const; + EventTarget const *eventTarget, + std::string const &type, + ValueFactory const &payloadFactory) const; /* * Invalidates the binding and underlying UIManager. @@ -78,11 +84,11 @@ class UIManagerBinding : public jsi::HostObject { /* * `jsi::HostObject` specific overloads. */ - jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override; + jsi::Value get(jsi::Runtime &runtime, jsi::PropNameID const &name) override; private: std::shared_ptr uiManager_; - std::unique_ptr eventHandler_; + std::unique_ptr eventHandler_; }; } // namespace react diff --git a/ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h b/ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h new file mode 100644 index 00000000000000..296e9733aa55b2 --- /dev/null +++ b/ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook { +namespace react { + +class ShadowTree; +class UIManager; + +/* + * Implementing a commit hook allows to observe and alter Shadow Tree commits. + */ +class UIManagerCommitHook { + public: + /* + * Called right after the commit hook is registered or unregistered. + */ + virtual void commitHookWasRegistered( + UIManager const &uiManager) const noexcept = 0; + virtual void commitHookWasUnregistered( + UIManager const &uiManager) const noexcept = 0; + + /* + * Called right before a `ShadowTree` commits a new tree. + * The semantic of the method corresponds to a method of the same name + * from `ShadowTreeDelegate`. + */ + virtual RootShadowNode::Unshared shadowTreeWillCommit( + ShadowTree const &shadowTree, + RootShadowNode::Shared const &oldRootShadowNode, + RootShadowNode::Unshared const &newRootShadowNode) const noexcept = 0; + + virtual ~UIManagerCommitHook() noexcept = default; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h b/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h index ad0c9e27f5b54a..5062158f60d551 100644 --- a/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h +++ b/ReactCommon/react/renderer/uimanager/UIManagerDelegate.h @@ -42,6 +42,15 @@ class UIManagerDelegate { std::string const &commandName, folly::dynamic const args) = 0; + /* + * Called when UIManager wants to dispatch some accessibility event + * to the mounting layer. eventType is platform-specific and not all + * platforms will necessarily implement the same set of events. + */ + virtual void uiManagerDidSendAccessibilityEvent( + const ShadowNode::Shared &shadowNode, + std::string const &eventType) = 0; + /* * Set JS responder for a view */ diff --git a/ReactCommon/react/renderer/uimanager/primitives.h b/ReactCommon/react/renderer/uimanager/primitives.h index cd9dde4a662c69..9fb2ea92786844 100644 --- a/ReactCommon/react/renderer/uimanager/primitives.h +++ b/ReactCommon/react/renderer/uimanager/primitives.h @@ -42,7 +42,7 @@ struct ShadowNodeListWrapper : public jsi::HostObject { inline static ShadowNode::Shared shadowNodeFromValue( jsi::Runtime &runtime, - const jsi::Value &value) { + jsi::Value const &value) { return value.getObject(runtime) .getHostObject(runtime) ->shadowNode; @@ -57,7 +57,7 @@ inline static jsi::Value valueFromShadowNode( inline static SharedShadowNodeUnsharedList shadowNodeListFromValue( jsi::Runtime &runtime, - const jsi::Value &value) { + jsi::Value const &value) { return value.getObject(runtime) .getHostObject(runtime) ->shadowNodeList; @@ -72,31 +72,31 @@ inline static jsi::Value valueFromShadowNodeList( inline static SharedEventTarget eventTargetFromValue( jsi::Runtime &runtime, - const jsi::Value &eventTargetValue, - const jsi::Value &tagValue) { + jsi::Value const &eventTargetValue, + jsi::Value const &tagValue) { return std::make_shared( runtime, eventTargetValue, tagValue.getNumber()); } -inline static Tag tagFromValue(jsi::Runtime &runtime, const jsi::Value &value) { +inline static Tag tagFromValue(jsi::Runtime &runtime, jsi::Value const &value) { return (Tag)value.getNumber(); } inline static SurfaceId surfaceIdFromValue( jsi::Runtime &runtime, - const jsi::Value &value) { + jsi::Value const &value) { return (SurfaceId)value.getNumber(); } inline static std::string stringFromValue( jsi::Runtime &runtime, - const jsi::Value &value) { + jsi::Value const &value) { return value.getString(runtime).utf8(runtime); } inline static folly::dynamic commandArgsFromValue( jsi::Runtime &runtime, - const jsi::Value &value) { + jsi::Value const &value) { return jsi::dynamicFromValue(runtime, value); } diff --git a/ReactCommon/react/utils/LayoutManager.h b/ReactCommon/react/utils/LayoutManager.h new file mode 100644 index 00000000000000..9789fc87d997ce --- /dev/null +++ b/ReactCommon/react/utils/LayoutManager.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +#ifdef ANDROID + +using namespace facebook::jni; + +Size measureAndroidComponent( + const ContextContainer::Shared &contextContainer, + Tag rootTag, + std::string componentName, + folly::dynamic localData, + folly::dynamic props, + folly::dynamic state, + float minWidth, + float maxWidth, + float minHeight, + float maxHeight, + jfloatArray attachmentPositions) { + const jni::global_ref &fabricUIManager = + contextContainer->at>("FabricUIManager"); + + static auto measure = + jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") + ->getMethod("measure"); + + auto componentNameRef = make_jstring(componentName); + local_ref localDataRNM = + ReadableNativeMap::newObjectCxxArgs(localData); + local_ref propsRNM = + ReadableNativeMap::newObjectCxxArgs(props); + local_ref stateRNM = + ReadableNativeMap::newObjectCxxArgs(state); + + local_ref localDataRM = + make_local(reinterpret_cast(localDataRNM.get())); + local_ref propsRM = + make_local(reinterpret_cast(propsRNM.get())); + local_ref stateRM = + make_local(reinterpret_cast(stateRNM.get())); + + auto size = yogaMeassureToSize(measure( + fabricUIManager, + rootTag, + componentNameRef.get(), + localDataRM.get(), + propsRM.get(), + stateRM.get(), + minWidth, + maxWidth, + minHeight, + maxHeight, + attachmentPositions)); + + // Explicitly release smart pointers to free up space faster in JNI tables + componentNameRef.reset(); + localDataRM.reset(); + localDataRNM.reset(); + propsRM.reset(); + propsRNM.reset(); + stateRM.reset(); + stateRNM.reset(); + + return size; +} + +#endif + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/utils/ThreadStorage.h b/ReactCommon/react/utils/ThreadStorage.h deleted file mode 100644 index 6b391549b9c908..00000000000000 --- a/ReactCommon/react/utils/ThreadStorage.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -/* - * ThreadStorage is a class designed to store data for specific thread. - * When data is inserted from thread 1, it can only be retrieved from thread 1. - */ -template -class ThreadStorage { - /* - * Private default constructor. This class has to be used as a singleton. - */ - ThreadStorage() = default; - - public: - static ThreadStorage &getInstance() { - static ThreadStorage threadStorage; - return threadStorage; - } - - better::optional get() const { - std::lock_guard lock(mutex_); - auto iterator = storage_.find(std::this_thread::get_id()); - - if (iterator != storage_.end()) { - return iterator->second; - } else { - return {}; - } - } - - void set(DataT data) { - std::lock_guard lock(mutex_); - storage_[std::this_thread::get_id()] = data; - } - - private: - mutable std::mutex mutex_; - better::map storage_; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/reactperflogger/React-perflogger.podspec b/ReactCommon/reactperflogger/React-perflogger.podspec index 43d795d08e3ad0..b66d7a2a2224d5 100644 --- a/ReactCommon/reactperflogger/React-perflogger.podspec +++ b/ReactCommon/reactperflogger/React-perflogger.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "**/*.{cpp,h}" s.header_dir = "reactperflogger" diff --git a/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.cpp b/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.cpp index 9192889c1d482d..f23256bf5cef24 100644 --- a/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.cpp +++ b/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.cpp @@ -17,6 +17,10 @@ void enableLogging(std::unique_ptr &&newPerfLogger) { g_perfLogger = std::move(newPerfLogger); } +void disableLogging() { + g_perfLogger = nullptr; +} + void moduleDataCreateStart(const char *moduleName, int32_t id) { NativeModulePerfLogger *logger = g_perfLogger.get(); if (logger != nullptr) { diff --git a/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.h b/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.h index c2fa24550119fe..9ac83b9615e837 100644 --- a/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.h +++ b/ReactCommon/reactperflogger/reactperflogger/BridgeNativeModulePerfLogger.h @@ -14,6 +14,7 @@ namespace react { namespace BridgeNativeModulePerfLogger { void enableLogging(std::unique_ptr &&logger); +void disableLogging(); void moduleDataCreateStart(const char *moduleName, int32_t id); void moduleDataCreateEnd(const char *moduleName, int32_t id); diff --git a/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec b/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec index e7fc8d2d2a3319..537020a16672f7 100644 --- a/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec +++ b/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec @@ -27,7 +27,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0" } s.source = source s.source_files = "**/*.{cpp,h}" s.header_dir = "ReactCommon" diff --git a/ReactCommon/yoga/Yoga.podspec b/ReactCommon/yoga/Yoga.podspec index b0a69cbb9b603a..20b8344304a886 100644 --- a/ReactCommon/yoga/Yoga.podspec +++ b/ReactCommon/yoga/Yoga.podspec @@ -43,7 +43,7 @@ Pod::Spec.new do |spec| ] # Pinning to the same version as React.podspec. - spec.platforms = { :ios => "10.0", :tvos => "10.0" } + spec.platforms = { :ios => "11.0" } # Set this environment variable when *not* using the `:path` option to install the pod. # E.g. when publishing this spec to a spec repo. @@ -51,7 +51,7 @@ Pod::Spec.new do |spec| source_files = File.join('ReactCommon/yoga', source_files) if ENV['INSTALL_YOGA_WITHOUT_PATH_OPTION'] spec.source_files = source_files - header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h' + header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h' header_files = File.join('ReactCommon/yoga', header_files) if ENV['INSTALL_YOGA_WITHOUT_PATH_OPTION'] spec.public_header_files = header_files end diff --git a/ReactCommon/yoga/yoga/CompactValue.h b/ReactCommon/yoga/yoga/CompactValue.h index be933a16eab858..f398668e2e1389 100644 --- a/ReactCommon/yoga/yoga/CompactValue.h +++ b/ReactCommon/yoga/yoga/CompactValue.h @@ -125,8 +125,8 @@ class YOGA_EXPORT CompactValue { data.repr &= ~PERCENT_BIT; data.repr += BIAS; - return YGValue{data.value, - payload_.repr & 0x40000000 ? YGUnitPercent : YGUnitPoint}; + return YGValue{ + data.value, payload_.repr & 0x40000000 ? YGUnitPercent : YGUnitPoint}; } bool isUndefined() const noexcept { diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index 97e640754d89f1..2db6be21d9a04f 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -3531,8 +3531,8 @@ static void YGNodelayoutImpl( YGNodeBoundAxisWithinMinAndMax( node, crossAxis, - YGFloatOptional{totalLineCrossDim + - paddingAndBorderAxisCross}, + YGFloatOptional{ + totalLineCrossDim + paddingAndBorderAxisCross}, crossAxisownerSize) .unwrap()), paddingAndBorderAxisCross), diff --git a/bots/README.md b/bots/README.md index d108148033d413..884a2ab55c6e36 100644 --- a/bots/README.md +++ b/bots/README.md @@ -15,7 +15,7 @@ DANGER_GITHUB_API_TOKEN=[ENV_ABOVE] yarn danger pr https://github.com/facebook/r The code analysis bot provides lint and other results as inline reviews on GitHub. It runs as part of the Circle CI analysis workflow. If you want to test changes to the Code Analysis Bot, I'd recommend checking out an existing PR and then running the `analyze pr` command. -You'll need a GitHub token. You can re-use this one: `78a72af35445ca3f8180` `b1a98e0bbd56ff1ccba1` (just remove the space). +You'll need a GitHub token. You can re-use this one: `312d354b5c36f082cfe9` `07973d757026bdd9f196` (just remove the space). So, for example: ``` diff --git a/bots/code-analysis-bot.js b/bots/code-analysis-bot.js index 55a80a9edecc30..5da10c52175f31 100644 --- a/bots/code-analysis-bot.js +++ b/bots/code-analysis-bot.js @@ -34,6 +34,8 @@ const converterSummary = { '`flow` found some issues. Run `yarn flow check` to analyze your code and address any errors.', shellcheck: '`shellcheck` found some issues. Run `yarn shellcheck` to analyze shell scripts.', + 'google-java-format': + '`google-java-format` found some issues. See https://github.com/google/google-java-format', }; /** @@ -57,6 +59,24 @@ const converters = { } }, + 'google-java-format': function(output, input) { + if (!input) { + return; + } + + input.forEach(function(change) { + push(output, change.file, { + message: `\`google-java-format\` suggested changes: +\`\`\`diff +${change.description} +\`\`\` +`, + line: change.line, + converter: 'google-java-format', + }); + }); + }, + flow: function(output, input) { if (!input || !input.errors) { return; @@ -113,30 +133,6 @@ const converters = { }, }; -function getShaFromPullRequest(octokit, owner, repo, number, callback) { - octokit.pullRequests.get({owner, repo, number}, (error, res) => { - if (error) { - console.error(error); - return; - } - - callback(res.data.head.sha); - }); -} - -function getFilesFromPullRequest(octokit, owner, repo, number, callback) { - octokit.pullRequests.listFiles( - {owner, repo, number, per_page: 100}, - (error, res) => { - if (error) { - console.error(error); - return; - } - callback(res.data); - }, - ); -} - /** * Sadly we can't just give the line number to github, we have to give the * line number relative to the patch file which is super annoying. This @@ -166,7 +162,15 @@ function getLineMapFromPatch(patchString) { return lineMap; } -function sendReview(octokit, owner, repo, number, commit_id, body, comments) { +async function sendReview( + octokit, + owner, + repo, + pull_number, + commit_id, + body, + comments, +) { if (process.env.GITHUB_TOKEN) { if (comments.length === 0) { // Do not leave an empty review. @@ -181,19 +185,14 @@ function sendReview(octokit, owner, repo, number, commit_id, body, comments) { const opts = { owner, repo, - number, + pull_number, commit_id, body, event, comments, }; - octokit.pullRequests.createReview(opts, function(error, res) { - if (error) { - console.error(error); - return; - } - }); + await octokit.pulls.createReview(opts); } else { if (comments.length === 0) { console.log('No issues found.'); @@ -216,7 +215,7 @@ function sendReview(octokit, owner, repo, number, commit_id, body, comments) { } } -function main(messages, owner, repo, number) { +async function main(messages, owner, repo, pull_number) { // No message, we don't need to do anything :) if (Object.keys(messages).length === 0) { return; @@ -234,40 +233,54 @@ function main(messages, owner, repo, number) { auth: process.env.GITHUB_TOKEN, }); - getShaFromPullRequest(octokit, owner, repo, number, sha => { - getFilesFromPullRequest(octokit, owner, repo, number, files => { - let comments = []; - let convertersUsed = []; - files - .filter(file => messages[file.filename]) - .forEach(file => { - // github api sometimes does not return a patch on large commits - if (!file.patch) { - return; - } - const lineMap = getLineMapFromPatch(file.patch); - messages[file.filename].forEach(message => { - if (lineMap[message.line]) { - const comment = { - path: file.filename, - position: lineMap[message.line], - body: message.message, - }; - convertersUsed.push(message.converter); - comments.push(comment); - } - }); // forEach - }); // filter - - let body = '**Code analysis results:**\n\n'; - const uniqueconvertersUsed = [...new Set(convertersUsed)]; - uniqueconvertersUsed.forEach(converter => { - body += '* ' + converterSummary[converter] + '\n'; - }); + const opts = { + owner, + repo, + pull_number, + }; - sendReview(octokit, owner, repo, number, sha, body, comments); - }); // getFilesFromPullRequest - }); // getShaFromPullRequest + const {data: pull} = await octokit.pulls.get(opts); + const {data: files} = await octokit.pulls.listFiles(opts); + + const comments = []; + const convertersUsed = []; + + files + .filter(file => messages[file.filename]) + .forEach(file => { + // github api sometimes does not return a patch on large commits + if (!file.patch) { + return; + } + const lineMap = getLineMapFromPatch(file.patch); + messages[file.filename].forEach(message => { + if (lineMap[message.line]) { + const comment = { + path: file.filename, + position: lineMap[message.line], + body: message.message, + }; + convertersUsed.push(message.converter); + comments.push(comment); + } + }); // forEach + }); // filter + + let body = '**Code analysis results:**\n\n'; + const uniqueconvertersUsed = [...new Set(convertersUsed)]; + uniqueconvertersUsed.forEach(converter => { + body += '* ' + converterSummary[converter] + '\n'; + }); + + await sendReview( + octokit, + owner, + repo, + pull_number, + pull.head.sha, + body, + comments, + ); } let content = ''; @@ -331,6 +344,7 @@ process.stdin.on('end', function() { const number = process.env.GITHUB_PR_NUMBER; - // intentional lint warning to make sure that the bot is working :) - main(messages, owner, repo, number); + (async () => { + await main(messages, owner, repo, number); + })(); }); diff --git a/build.gradle.kts b/build.gradle.kts index 571f2db36b6c0f..532c996c131dc4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ buildscript { jcenter() } dependencies { - classpath("com.android.tools.build:gradle:3.6.4") + classpath("com.android.tools.build:gradle:4.1.0") classpath("de.undercouch:gradle-download-task:4.0.2") // NOTE: Do not place your application dependencies here; they belong @@ -34,4 +34,9 @@ allprojects { google() jcenter() } + + // used to override ndk path on CI + if (System.getenv("LOCAL_ANDROID_NDK_VERSION") != null) { + setProperty("ANDROID_NDK_VERSION", System.getenv("LOCAL_ANDROID_NDK_VERSION")) + } } diff --git a/flow-typed/npm/base64-js_v1.x.x.js b/flow-typed/npm/base64-js_v1.x.x.js index 8653866fdba324..209a577e2adbd8 100644 --- a/flow-typed/npm/base64-js_v1.x.x.js +++ b/flow-typed/npm/base64-js_v1.x.x.js @@ -1,6 +1,4 @@ /** - * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. - * * @flow strict * @format */ diff --git a/flow-typed/npm/pretty-format_v26.x.x.js b/flow-typed/npm/pretty-format_v26.x.x.js index 181d7909b34c8c..bd2c68334cffb3 100644 --- a/flow-typed/npm/pretty-format_v26.x.x.js +++ b/flow-typed/npm/pretty-format_v26.x.x.js @@ -1,6 +1,4 @@ /** - * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. - * * @flow strict * @format */ diff --git a/flow-typed/npm/promise_v8.x.x.js b/flow-typed/npm/promise_v8.x.x.js index 580f98cdd6303e..f7eb92e4d12d22 100644 --- a/flow-typed/npm/promise_v8.x.x.js +++ b/flow-typed/npm/promise_v8.x.x.js @@ -1,20 +1,18 @@ /** - * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. - * * @flow strict * @format */ declare module 'promise/setimmediate/es6-extensions' { - declare module.exports: Class; + declare module.exports: typeof Promise; } declare module 'promise/setimmediate/done' { - declare module.exports: Class; + declare module.exports: typeof Promise; } declare module 'promise/setimmediate/finally' { - declare module.exports: Class; + declare module.exports: typeof Promise; } declare module 'promise/setimmediate/rejection-tracking' { diff --git a/flow-typed/npm/prop-types_v15.x.x.js b/flow-typed/npm/prop-types_v15.x.x.js index 45f83f922b9baf..f5f6dba9e23852 100644 --- a/flow-typed/npm/prop-types_v15.x.x.js +++ b/flow-typed/npm/prop-types_v15.x.x.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * * @flow strict * @nolint * @format diff --git a/flow-typed/npm/react-dom_v16.x.x.js b/flow-typed/npm/react-dom_v16.x.x.js index b99617dd74d89a..01da4d0f52a8d6 100644 --- a/flow-typed/npm/react-dom_v16.x.x.js +++ b/flow-typed/npm/react-dom_v16.x.x.js @@ -1,7 +1,4 @@ /** - * Copyright (c) 2013-present, Facebook, Inc. - * All rights reserved. - * * react-dom v16.x.x libdefs from flow-typed * * @noformat diff --git a/flow-typed/npm/stacktrace-parser_v0.1.x.js b/flow-typed/npm/stacktrace-parser_v0.1.x.js index 9e99014453138f..51dd691b259a8b 100644 --- a/flow-typed/npm/stacktrace-parser_v0.1.x.js +++ b/flow-typed/npm/stacktrace-parser_v0.1.x.js @@ -1,6 +1,4 @@ /** - * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. - * * @flow strict * @format */ diff --git a/gradle.properties b/gradle.properties index f0a3fdf5d79fed..dd6698ad75bd27 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,3 +3,5 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.parallel=true + +ANDROID_NDK_VERSION=20.1.5948944 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bca17f36566b30..14e30f7416a55e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/index.js b/index.js index 63c1d5f96fd29f..65ee685b46f0f6 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,7 @@ 'use strict'; +// Components import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo'; import typeof ActivityIndicator from './Libraries/Components/ActivityIndicator/ActivityIndicator'; import typeof Button from './Libraries/Components/Button'; @@ -27,14 +28,14 @@ import typeof PickerIOS from './Libraries/Components/Picker/PickerIOS'; import typeof Pressable from './Libraries/Components/Pressable/Pressable'; import typeof ProgressBarAndroid from './Libraries/Components/ProgressBarAndroid/ProgressBarAndroid'; import typeof ProgressViewIOS from './Libraries/Components/ProgressViewIOS/ProgressViewIOS'; +import typeof RefreshControl from './Libraries/Components/RefreshControl/RefreshControl'; import typeof SafeAreaView from './Libraries/Components/SafeAreaView/SafeAreaView'; import typeof ScrollView from './Libraries/Components/ScrollView/ScrollView'; import typeof SectionList from './Libraries/Lists/SectionList'; import typeof SegmentedControlIOS from './Libraries/Components/SegmentedControlIOS/SegmentedControlIOS'; import typeof Slider from './Libraries/Components/Slider/Slider'; -import typeof Switch from './Libraries/Components/Switch/Switch'; -import typeof RefreshControl from './Libraries/Components/RefreshControl/RefreshControl'; import typeof StatusBar from './Libraries/Components/StatusBar/StatusBar'; +import typeof Switch from './Libraries/Components/Switch/Switch'; import typeof Text from './Libraries/Text/Text'; import typeof TextInput from './Libraries/Components/TextInput/TextInput'; import typeof Touchable from './Libraries/Components/Touchable/Touchable'; @@ -45,6 +46,8 @@ import typeof TouchableWithoutFeedback from './Libraries/Components/Touchable/To import typeof View from './Libraries/Components/View/View'; import typeof VirtualizedList from './Libraries/Lists/VirtualizedList'; import typeof VirtualizedSectionList from './Libraries/Lists/VirtualizedSectionList'; + +// APIs import typeof ActionSheetIOS from './Libraries/ActionSheetIOS/ActionSheetIOS'; import typeof Alert from './Libraries/Alert/Alert'; import typeof Animated from './Libraries/Animated/Animated'; @@ -66,6 +69,7 @@ import typeof InteractionManager from './Libraries/Interaction/InteractionManage import typeof Keyboard from './Libraries/Components/Keyboard/Keyboard'; import typeof LayoutAnimation from './Libraries/LayoutAnimation/LayoutAnimation'; import typeof Linking from './Libraries/Linking/Linking'; +import typeof LogBox from './Libraries/LogBox/LogBox'; import typeof NativeDialogManagerAndroid from './Libraries/NativeModules/specs/NativeDialogManagerAndroid'; import typeof NativeEventEmitter from './Libraries/EventEmitter/NativeEventEmitter'; import typeof Networking from './Libraries/Network/RCTNetworking'; @@ -80,22 +84,24 @@ import typeof StyleSheet from './Libraries/StyleSheet/StyleSheet'; import typeof Systrace from './Libraries/Performance/Systrace'; import typeof ToastAndroid from './Libraries/Components/ToastAndroid/ToastAndroid'; import typeof * as TurboModuleRegistry from './Libraries/TurboModule/TurboModuleRegistry'; -import typeof TVEventHandler from './Libraries/Components/AppleTV/TVEventHandler'; import typeof UIManager from './Libraries/ReactNative/UIManager'; import typeof useColorScheme from './Libraries/Utilities/useColorScheme'; import typeof useWindowDimensions from './Libraries/Utilities/useWindowDimensions'; import typeof UTFSequence from './Libraries/UTFSequence'; import typeof Vibration from './Libraries/Vibration/Vibration'; import typeof YellowBox from './Libraries/YellowBox/YellowBoxDeprecated'; -import typeof LogBox from './Libraries/LogBox/LogBox'; -import typeof RCTDeviceEventEmitter from './Libraries/EventEmitter/RCTDeviceEventEmitter'; -import typeof RCTNativeAppEventEmitter from './Libraries/EventEmitter/RCTNativeAppEventEmitter'; + +// Plugins +import typeof {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; import typeof NativeModules from './Libraries/BatchedBridge/NativeModules'; import typeof Platform from './Libraries/Utilities/Platform'; -import typeof processColor from './Libraries/StyleSheet/processColor'; import typeof {PlatformColor} from './Libraries/StyleSheet/PlatformColorValueTypes'; -import typeof {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; +import typeof processColor from './Libraries/StyleSheet/processColor'; +import typeof RCTDeviceEventEmitter from './Libraries/EventEmitter/RCTDeviceEventEmitter'; +import typeof RCTNativeAppEventEmitter from './Libraries/EventEmitter/RCTNativeAppEventEmitter'; import typeof {RootTagContext} from './Libraries/ReactNative/RootTag'; + +// Prop Types import typeof DeprecatedColorPropType from './Libraries/DeprecatedPropTypes/DeprecatedColorPropType'; import typeof DeprecatedEdgeInsetsPropType from './Libraries/DeprecatedPropTypes/DeprecatedEdgeInsetsPropType'; import typeof DeprecatedPointPropType from './Libraries/DeprecatedPropTypes/DeprecatedPointPropType'; @@ -125,7 +131,7 @@ module.exports = { 'DatePickerIOS-merged', 'DatePickerIOS has been merged with DatePickerAndroid and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + - 'See https://github.com/react-native-community/datetimepicker', + 'See https://github.com/react-native-datetimepicker/datetimepicker', ); return require('./Libraries/Components/DatePicker/DatePickerIOS'); }, @@ -152,8 +158,8 @@ module.exports = { warnOnce( 'maskedviewios-moved', 'MaskedViewIOS has been extracted from react-native core and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-masked-view', + "It can now be installed and imported from '@react-native-masked-view/masked-view' instead of 'react-native'. " + + 'See https://github.com/react-native-masked-view/react-native-masked-view', ); return require('./Libraries/Components/MaskedView/MaskedViewIOS'); }, @@ -164,8 +170,8 @@ module.exports = { warnOnce( 'picker-moved', 'Picker has been extracted from react-native core and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/picker' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-picker', + "It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " + + 'See https://github.com/react-native-picker/react-native-picker', ); return require('./Libraries/Components/Picker/Picker'); }, @@ -174,8 +180,8 @@ module.exports = { warnOnce( 'pickerios-moved', 'PickerIOS has been extracted from react-native core and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/picker' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-picker', + "It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " + + 'See https://github.com/react-native-picker/react-native-picker', ); return require('./Libraries/Components/Picker/PickerIOS'); }, @@ -188,7 +194,7 @@ module.exports = { 'progress-bar-android-moved', 'ProgressBarAndroid has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/progress-bar-android' instead of 'react-native'. " + - 'See https://github.com/react-native-community/progress-bar-android', + 'See https://github.com/react-native-progress-view/progress-bar-android', ); return require('./Libraries/Components/ProgressBarAndroid/ProgressBarAndroid'); }, @@ -198,10 +204,13 @@ module.exports = { 'progress-view-ios-moved', 'ProgressViewIOS has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/progress-view' instead of 'react-native'. " + - 'See https://github.com/react-native-community/progress-view', + 'See https://github.com/react-native-progress-view/progress-view', ); return require('./Libraries/Components/ProgressViewIOS/ProgressViewIOS'); }, + get RefreshControl(): RefreshControl { + return require('./Libraries/Components/RefreshControl/RefreshControl'); + }, get SafeAreaView(): SafeAreaView { return require('./Libraries/Components/SafeAreaView/SafeAreaView'); }, @@ -217,7 +226,7 @@ module.exports = { 'segmented-control-ios-moved', 'SegmentedControlIOS has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/segmented-control' instead of 'react-native'. " + - 'See https://github.com/react-native-community/segmented-control', + 'See https://github.com/react-native-segmented-control/segmented-control', ); return require('./Libraries/Components/SegmentedControlIOS/SegmentedControlIOS'); }, @@ -226,19 +235,16 @@ module.exports = { 'slider-moved', 'Slider has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-slider', + 'See https://github.com/callstack/react-native-slider', ); return require('./Libraries/Components/Slider/Slider'); }, - get Switch(): Switch { - return require('./Libraries/Components/Switch/Switch'); - }, - get RefreshControl(): RefreshControl { - return require('./Libraries/Components/RefreshControl/RefreshControl'); - }, get StatusBar(): StatusBar { return require('./Libraries/Components/StatusBar/StatusBar'); }, + get Switch(): Switch { + return require('./Libraries/Components/Switch/Switch'); + }, get Text(): Text { return require('./Libraries/Text/Text'); }, @@ -294,8 +300,8 @@ module.exports = { warnOnce( 'async-storage-moved', 'AsyncStorage has been extracted from react-native core and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. " + - 'See https://github.com/react-native-community/async-storage', + "It can now be installed and imported from '@react-native-async-storage/async-storage' instead of 'react-native'. " + + 'See https://github.com/react-native-async-storage/async-storage', ); return require('./Libraries/Storage/AsyncStorage'); }, @@ -307,7 +313,7 @@ module.exports = { 'clipboard-moved', 'Clipboard has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/clipboard' instead of 'react-native'. " + - 'See https://github.com/react-native-community/clipboard', + 'See https://github.com/react-native-clipboard/clipboard', ); return require('./Libraries/Components/Clipboard/Clipboard'); }, @@ -316,7 +322,7 @@ module.exports = { 'DatePickerAndroid-merged', 'DatePickerAndroid has been merged with DatePickerIOS and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + - 'See https://github.com/react-native-community/datetimepicker', + 'See https://github.com/react-native-datetimepicker/datetimepicker', ); return require('./Libraries/Components/DatePickerAndroid/DatePickerAndroid'); }, @@ -344,7 +350,7 @@ module.exports = { 'ImagePickerIOS has been extracted from react-native core and will be removed in a future release. ' + "Please upgrade to use either '@react-native-community/react-native-image-picker' or 'expo-image-picker'. " + "If you cannot upgrade to a different library, please install the deprecated '@react-native-community/image-picker-ios' package. " + - 'See https://github.com/react-native-community/react-native-image-picker-ios', + 'See https://github.com/rnc-archive/react-native-image-picker-ios', ); return require('./Libraries/Image/ImagePickerIOS'); }, @@ -387,7 +393,7 @@ module.exports = { 'pushNotificationIOS-moved', 'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' + "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " + - 'See https://github.com/react-native-community/push-notification-ios', + 'See https://github.com/react-native-push-notification-ios/push-notification-ios', ); return require('./Libraries/PushNotificationIOS/PushNotificationIOS'); }, @@ -417,9 +423,6 @@ module.exports = { get TurboModuleRegistry(): TurboModuleRegistry { return require('./Libraries/TurboModule/TurboModuleRegistry'); }, - get TVEventHandler(): TVEventHandler { - return require('./Libraries/Components/AppleTV/TVEventHandler'); - }, get UIManager(): UIManager { return require('./Libraries/ReactNative/UIManager'); }, @@ -450,6 +453,10 @@ module.exports = { get DeviceEventEmitter(): RCTDeviceEventEmitter { return require('./Libraries/EventEmitter/RCTDeviceEventEmitter').default; }, + get DynamicColorIOS(): DynamicColorIOS { + return require('./Libraries/StyleSheet/PlatformColorValueTypesIOS') + .DynamicColorIOS; + }, get NativeAppEventEmitter(): RCTNativeAppEventEmitter { return require('./Libraries/EventEmitter/RCTNativeAppEventEmitter'); }, @@ -459,16 +466,12 @@ module.exports = { get Platform(): Platform { return require('./Libraries/Utilities/Platform'); }, - get processColor(): processColor { - return require('./Libraries/StyleSheet/processColor'); - }, get PlatformColor(): PlatformColor { return require('./Libraries/StyleSheet/PlatformColorValueTypes') .PlatformColor; }, - get DynamicColorIOS(): DynamicColorIOS { - return require('./Libraries/StyleSheet/PlatformColorValueTypesIOS') - .DynamicColorIOS; + get processColor(): processColor { + return require('./Libraries/StyleSheet/processColor'); }, get requireNativeComponent(): ( uiViewClassName: string, @@ -509,7 +512,7 @@ if (__DEV__) { false, 'ART has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/art' instead of 'react-native'. " + - 'See https://github.com/react-native-community/art', + 'See https://github.com/react-native-art/art', ); }, }); @@ -548,7 +551,7 @@ if (__DEV__) { false, 'WebView has been removed from React Native. ' + "It can now be installed and imported from 'react-native-webview' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-webview', + 'See https://github.com/react-native-webview/react-native-webview', ); }, }); @@ -561,7 +564,7 @@ if (__DEV__) { false, 'NetInfo has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/netinfo' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-netinfo', + 'See https://github.com/react-native-netinfo/react-native-netinfo', ); }, }); @@ -574,7 +577,7 @@ if (__DEV__) { false, 'CameraRoll has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/cameraroll' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-cameraroll', + 'See https://github.com/react-native-cameraroll/react-native-cameraroll', ); }, }); @@ -601,7 +604,7 @@ if (__DEV__) { false, 'ImageEditor has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/image-editor' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-image-editor', + 'See https://github.com/callstack/react-native-image-editor', ); }, }); @@ -614,7 +617,7 @@ if (__DEV__) { false, 'TimePickerAndroid has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/datetimepicker' instead of 'react-native'. " + - 'See https://github.com/react-native-community/datetimepicker', + 'See https://github.com/react-native-datetimepicker/datetimepicker', ); }, }); @@ -627,7 +630,7 @@ if (__DEV__) { false, 'ToolbarAndroid has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/toolbar-android' instead of 'react-native'. " + - 'See https://github.com/react-native-community/toolbar-android', + 'See https://github.com/react-native-toolbar-android/toolbar-android', ); }, }); @@ -640,7 +643,7 @@ if (__DEV__) { false, 'ViewPagerAndroid has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/viewpager' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-viewpager', + 'See https://github.com/callstack/react-native-viewpager', ); }, }); @@ -653,7 +656,7 @@ if (__DEV__) { false, 'CheckBox has been removed from React Native. ' + "It can now be installed and imported from '@react-native-community/checkbox' instead of 'react-native'. " + - 'See https://github.com/react-native-community/react-native-checkbox', + 'See https://github.com/react-native-checkbox/react-native-checkbox', ); }, }); diff --git a/interface.js b/interface.js index a5e7987fe744ee..22337a98731be1 100644 --- a/interface.js +++ b/interface.js @@ -15,11 +15,3 @@ declare var __DEV__: boolean; declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: any; /*?{ inject: ?((stuff: Object) => void) };*/ - -declare var fetch: any; -declare var Headers: any; -declare var Request: any; -declare var Response: any; -declare module requestAnimationFrame { - declare module.exports: (callback: any) => any; -} diff --git a/jest/assetFileTransformer.js b/jest/assetFileTransformer.js index cdc477c7d37dbd..03b018ffb7c053 100644 --- a/jest/assetFileTransformer.js +++ b/jest/assetFileTransformer.js @@ -12,7 +12,8 @@ /* eslint-env node */ const path = require('path'); -const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction'); +const createCacheKeyFunction = require('@jest/create-cache-key-function') + .default; module.exports = { // Mocks asset requires to return the filename. Makes it possible to test that @@ -21,7 +22,7 @@ module.exports = { // the Jest snapshot. process: (_, filename) => `module.exports = { - testUri: + testUri: ${JSON.stringify( path.relative(__dirname, filename).replace(/\\/g, '/'), )} diff --git a/jest/mockNativeComponent.js b/jest/mockNativeComponent.js new file mode 100644 index 00000000000000..e6080b7d1498e7 --- /dev/null +++ b/jest/mockNativeComponent.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const React = require('react'); + +module.exports = viewName => { + const Component = class extends React.Component { + render() { + return React.createElement(viewName, this.props, this.props.children); + } + + // The methods that exist on host components + blur = jest.fn(); + focus = jest.fn(); + measure = jest.fn(); + measureInWindow = jest.fn(); + measureLayout = jest.fn(); + setNativeProps = jest.fn(); + }; + + if (viewName === 'RCTView') { + Component.displayName = 'View'; + } else { + Component.displayName = viewName; + } + + return Component; +}; diff --git a/jest/preprocessor.js b/jest/preprocessor.js index b08da26a396822..e9d12710ddf4ed 100644 --- a/jest/preprocessor.js +++ b/jest/preprocessor.js @@ -13,7 +13,8 @@ 'use strict'; const babelRegisterOnly = require('metro-babel-register'); -const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction'); +const createCacheKeyFunction = require('@jest/create-cache-key-function') + .default; const {transformSync: babelTransformSync} = require('@babel/core'); const generate = require('@babel/generator').default; @@ -100,6 +101,7 @@ module.exports = { return generate( ast, + // $FlowFixMe[prop-missing] Error found when improving flow typing for libs { code: true, comments: false, diff --git a/jest/setup.js b/jest/setup.js index bc27b00e23abf0..c5b829374cff8f 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -69,6 +69,9 @@ jest }; } }), + hasViewManagerConfig: jest.fn(name => { + return true; + }), measure: jest.fn(), manageChildren: jest.fn(), removeSubviewsFromContainerWithID: jest.fn(), @@ -124,6 +127,7 @@ jest isScreenReaderEnabled: jest.fn(() => Promise.resolve(false)), removeEventListener: jest.fn(), setAccessibilityFocus: jest.fn(), + sendAccessibilityEvent_unstable: jest.fn(), })) .mock('../Libraries/Components/RefreshControl/RefreshControl', () => jest.requireActual( @@ -325,33 +329,20 @@ jest }), }, })) - .mock('../Libraries/ReactNative/requireNativeComponent', () => { - const React = require('react'); - - return viewName => { - const Component = class extends React.Component { - render() { - return React.createElement(viewName, this.props, this.props.children); - } - - // The methods that exist on host components - blur = jest.fn(); - focus = jest.fn(); - measure = jest.fn(); - measureInWindow = jest.fn(); - measureLayout = jest.fn(); - setNativeProps = jest.fn(); - }; - - if (viewName === 'RCTView') { - Component.displayName = 'View'; - } else { - Component.displayName = viewName; - } - - return Component; + .mock('../Libraries/NativeComponent/NativeComponentRegistry', () => { + return { + get: jest.fn((name, viewConfigProvider) => { + return jest.requireActual('./mockNativeComponent')(name); + }), + getWithFallback_DEPRECATED: jest.fn((name, viewConfigProvider) => { + return jest.requireActual('./mockNativeComponent')(name); + }), + setRuntimeConfigProvider: jest.fn(), }; }) + .mock('../Libraries/ReactNative/requireNativeComponent', () => { + return jest.requireActual('./mockNativeComponent'); + }) .mock( '../Libraries/Utilities/verifyComponentAttributeEquivalence', () => function() {}, diff --git a/metro.config.js b/metro.config.js index a58484221c19b5..a868d504fc3935 100644 --- a/metro.config.js +++ b/metro.config.js @@ -18,6 +18,8 @@ const getPolyfills = require('./rn-get-polyfills'); */ module.exports = { resolver: { + // $FlowFixMe[signature-verification-failure] Can't infer RegExp type. + blacklistRE: /buck-out/, extraNodeModules: { 'react-native': __dirname, }, diff --git a/package.json b/package.json index 34260b816a895d..516c8831bb7b3d 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,9 @@ "bin": "./cli.js", "description": "A framework for building native apps using React", "license": "MIT", - "repository": { - "type": "git", - "url": "git@github.com:facebook/react-native.git" - }, + "repository": "github:facebook/react-native", "engines": { - "node": ">=10" + "node": ">=12" }, "jest-junit": { "outputDirectory": "reports/junit", @@ -20,8 +17,10 @@ "!template/node_modules", "!template/package-lock.json", "!template/yarn.lock", + "android", "cli.js", "flow", + "flow-typed", "index.js", "interface.js", "jest-preset.js", @@ -39,6 +38,8 @@ "README.md", "rn-get-polyfills.js", "scripts/compose-source-maps.js", + "scripts/generate-specs.sh", + "scripts/generate-specs-cli.js", "scripts/ios-configure-glog.sh", "scripts/launchPackager.bat", "scripts/launchPackager.command", @@ -59,12 +60,14 @@ "flow-check-android": "flow check --flowconfig-name .flowconfig.android", "lint": "eslint .", "lint-ci": "./scripts/circleci/analyze_code.sh && yarn shellcheck", + "lint-java": "node ./scripts/lint-java.js", "shellcheck": "./scripts/circleci/analyze_scripts.sh", "clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}", "format": "npm run prettier && npm run clang-format", "prettier": "prettier --write \"./**/*.{js,md,yml}\"", "format-check": "prettier --list-different \"./**/*.{js,md,yml}\"", - "docker-setup-android": "docker pull reactnativecommunity/react-native-android", + "update-lock": "npx yarn-deduplicate", + "docker-setup-android": "docker pull reactnativecommunity/react-native-android:2.1", "docker-build-android": "docker build -t reactnativeci/android -f .circleci/Dockerfiles/Dockerfile.android .", "test-android-run-instrumentation": "docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-instrumentation-tests.sh", "test-android-run-unit": "docker run --cap-add=SYS_ADMIN -it reactnativeci/android bash .circleci/Dockerfiles/scripts/run-android-docker-unit-tests.sh", @@ -82,12 +85,13 @@ "repo-config" ], "peerDependencies": { - "react": "16.13.1" + "react": "17.0.1" }, "dependencies": { - "@react-native-community/cli": "^4.10.0", - "@react-native-community/cli-platform-android": "^4.10.0", - "@react-native-community/cli-platform-ios": "^4.10.0", + "@jest/create-cache-key-function": "^26.5.0", + "@react-native-community/cli": "^5.0.1-alpha.0", + "@react-native-community/cli-platform-android": "^5.0.1-alpha.0", + "@react-native-community/cli-platform-ios": "^5.0.1-alpha.0", "@react-native/assets": "1.0.0", "@react-native/normalize-color": "1.0.0", "@react-native/polyfills": "1.0.0", @@ -95,31 +99,29 @@ "anser": "^1.4.9", "base64-js": "^1.1.2", "event-target-shim": "^5.0.1", - "fbjs-scripts": "^1.1.0", - "hermes-engine": "~0.6.0", + "hermes-engine": "~0.7.0", "invariant": "^2.2.4", "jsc-android": "^245459.0.0", - "metro-babel-register": "0.63.0", - "metro-react-native-babel-transformer": "0.63.0", - "metro-runtime": "0.63.0", - "metro-source-map": "0.63.0", + "metro-babel-register": "0.64.0", + "metro-react-native-babel-transformer": "0.64.0", + "metro-runtime": "0.64.0", + "metro-source-map": "0.64.0", "nullthrows": "^1.1.1", - "pretty-format": "^26.0.1", + "pretty-format": "^26.5.2", "promise": "^8.0.3", "prop-types": "^15.7.2", - "qs": "^6.5.1", "react-devtools-core": "^4.6.0", "react-refresh": "^0.4.0", "regenerator-runtime": "^0.13.2", - "scheduler": "0.19.1", + "scheduler": "^0.20.1", "stacktrace-parser": "^0.1.3", "use-subscription": "^1.0.0", "whatwg-fetch": "^3.0.0", "ws": "^6.1.4" }, "devDependencies": { - "flow-bin": "^0.133.0", - "react": "16.13.1" + "flow-bin": "^0.143.1", + "react": "17.0.1" }, "detox": { "test-runner": "jest", diff --git a/packages/assets/BUCK b/packages/assets/BUCK index fa6f04f440ac24..424f33a0003ce6 100644 --- a/packages/assets/BUCK +++ b/packages/assets/BUCK @@ -11,7 +11,6 @@ rn_library( labels = ["supermodule:xplat/default/public.react_native.core"], skip_processors = True, visibility = ["PUBLIC"], - worker = "//xplat/js:experimental-packager", ) yarn_workspace( diff --git a/packages/assets/package.json b/packages/assets/package.json index 13064909c99bb9..885e7175338867 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -4,7 +4,8 @@ "description": "Asset support code for React Native.", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/assets" }, "license": "MIT" } diff --git a/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap b/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap index 85c8e4580aa169..7018db249d9a9d 100644 --- a/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap +++ b/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap @@ -22,13 +22,14 @@ interface NativeCommands { +scrollTo: (viewRef: React.ElementRef, y: Int32, animated: boolean) => void, } -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); const { dispatchCommand } = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); -const ModuleViewConfig = { +let nativeComponentName = 'RCTModule'; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'RCTModule', bubblingEventTypes: { topBubblingEventDefinedInlineNull: { @@ -48,11 +49,7 @@ const ModuleViewConfig = { onDirectEventDefinedInlineNull: true, onBubblingEventDefinedInlineNull: true } -}; -let nativeComponentName = 'RCTModule'; -registerGeneratedViewConfig(nativeComponentName, ModuleViewConfig); -export const __INTERNAL_VIEW_CONFIG = ModuleViewConfig; -export default nativeComponentName; +})); export const Commands = { hotspotUpdate(ref, x, y) { dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]); @@ -87,13 +84,14 @@ interface NativeCommands { +scrollTo: (viewRef: React.ElementRef, y: Int32, animated: boolean) => void, } -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); const { dispatchCommand } = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); -const ModuleViewConfig = { +let nativeComponentName = 'RCTModule'; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'RCTModule', bubblingEventTypes: { topBubblingEventDefinedInlineNull: { @@ -113,11 +111,7 @@ const ModuleViewConfig = { onDirectEventDefinedInlineNull: true, onBubblingEventDefinedInlineNull: true } -}; -let nativeComponentName = 'RCTModule'; -registerGeneratedViewConfig(nativeComponentName, ModuleViewConfig); -export const __INTERNAL_VIEW_CONFIG = ModuleViewConfig; -export default nativeComponentName; +})); export const Commands = { hotspotUpdate(ref, x, y) { dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]); diff --git a/packages/babel-plugin-codegen/index.js b/packages/babel-plugin-codegen/index.js index 1a80f9c60b4580..3b3ee570946806 100644 --- a/packages/babel-plugin-codegen/index.js +++ b/packages/babel-plugin-codegen/index.js @@ -53,7 +53,7 @@ function isCodegenDeclaration(declaration) { return false; } -module.exports = function(context) { +module.exports = function({parse, types: t}) { return { pre(state) { this.code = state.code; @@ -118,12 +118,13 @@ module.exports = function(context) { this.defaultExport = path; } }, + Program: { - exit() { + exit(path) { if (this.defaultExport) { const viewConfig = generateViewConfig(this.filename, this.code); this.defaultExport.replaceWithMultiple( - context.parse(viewConfig).program.body, + parse(viewConfig).program.body, ); if (this.commandsExport != null) { this.commandsExport.remove(); diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index ee2f27f894d54b..e5176600ae0476 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,10 +1,11 @@ { - "version": "0.0.5", + "version": "0.0.6", "name": "@react-native/babel-plugin-codegen", "description": "Babel plugin to generate native module and view manager code for React Native.", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/babel-plugin-codegen" }, "dependencies": { "react-native-codegen": "*" diff --git a/packages/eslint-config-react-native-community/index.js b/packages/eslint-config-react-native-community/index.js index 3302717db60fcb..9f03ade38b7d0c 100644 --- a/packages/eslint-config-react-native-community/index.js +++ b/packages/eslint-config-react-native-community/index.js @@ -81,6 +81,7 @@ module.exports = { __DEV__: true, __dirname: false, __fbBatchedBridgeConfig: false, + AbortController: false, alert: false, cancelAnimationFrame: false, cancelIdleCallback: false, @@ -285,7 +286,7 @@ module.exports = { 'react/display-name': 0, 'react/jsx-boolean-value': 0, - 'react/jsx-no-comment-textnodes': 1, + 'react/jsx-no-comment-textnodes': 2, 'react/jsx-no-duplicate-props': 2, 'react/jsx-no-undef': 2, 'react/jsx-sort-props': 0, diff --git a/packages/eslint-config-react-native-community/package.json b/packages/eslint-config-react-native-community/package.json index a05f990d388fcc..ec1a217296bf7c 100644 --- a/packages/eslint-config-react-native-community/package.json +++ b/packages/eslint-config-react-native-community/package.json @@ -6,7 +6,8 @@ "license": "MIT", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/eslint-config-react-native-community" }, "homepage": "https://github.com/facebook/react-native/tree/master/packages/eslint-config-react-native-community#readme", "dependencies": { @@ -21,13 +22,13 @@ "eslint-plugin-prettier": "3.1.2", "eslint-plugin-react": "^7.20.0", "eslint-plugin-react-hooks": "^4.0.7", - "eslint-plugin-react-native": "^3.8.1", + "eslint-plugin-react-native": "^3.10.0", "prettier": "^2.0.2" }, "peerDependencies": { - "eslint": ">=6" + "eslint": ">=7" }, "devDependencies": { - "eslint": "^6.5.1" + "eslint": "7.12.0" } } diff --git a/packages/eslint-config-react-native-community/yarn.lock b/packages/eslint-config-react-native-community/yarn.lock index b4d6255c4cd3f0..e87360ec0c7797 100644 --- a/packages/eslint-config-react-native-community/yarn.lock +++ b/packages/eslint-config-react-native-community/yarn.lock @@ -2,80 +2,63 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== +"@babel/generator@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.10.tgz#2b188fc329fb8e4f762181703beffc0fe6df3460" + integrity sha512-6mCdfhWgmqLdtTkhXjnIz0LcdVCd26wS2JXRtj2XY0u5klDsXBREA/pG5NVOuVnF2LUrBGNFtQkIqqTbblg0ww== dependencies: - "@babel/highlight" "^7.8.3" - -"@babel/generator@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce" - integrity sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA== - dependencies: - "@babel/types" "^7.9.0" + "@babel/types" "^7.12.10" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" - integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== +"@babel/helper-get-function-arity@^7.10.4": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.12.10" -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-validator-identifier@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" - integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== + "@babel/types" "^7.11.0" -"@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== -"@babel/highlight@^7.8.3": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" - integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: - "@babel/helper-validator-identifier" "^7.9.0" + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" - integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== +"@babel/parser@^7.12.10", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.10.tgz#824600d59e96aea26a5a2af5a9d812af05c3ae81" + integrity sha512-PJdRPwyoOqFAWfLytxrWwGrAxghCgh/yTNCYciOz8QgjflA7aZhECPZAa2VUedKg2+QMWkI0L9lynh2SNmNEgA== "@babel/runtime-corejs3@^7.8.3": version "7.9.2" @@ -85,39 +68,55 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/template@^7.8.3": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/traverse@^7.7.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" - integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.0" +"@babel/template@^7.10.4": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.7.0", "@babel/traverse@^7.7.4": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.10.tgz#2d1f4041e8bf42ea099e5b2dc48d6a594c00017a" + integrity sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.10" + "@babel/types" "^7.12.10" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" - integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng== +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.10", "@babel/types@^7.12.7", "@babel/types@^7.7.0": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260" + integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw== dependencies: - "@babel/helper-validator-identifier" "^7.9.0" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" +"@eslint/eslintrc@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" + integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@react-native-community/eslint-plugin@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.1.0.tgz#e42b1bef12d2415411519fd528e64b593b1363dc" @@ -187,37 +186,25 @@ acorn-jsx@^5.2.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== -acorn@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" - integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -ajv@^6.10.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" - integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== +ajv@^6.10.0, ajv@^6.12.4, ajv@^6.9.1: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.9.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^4.1.0: version "4.1.0" @@ -251,15 +238,7 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" - -array-includes@^3.1.1: +array-includes@^3.0.3, array-includes@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== @@ -303,7 +282,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== -chalk@^2.0.0, chalk@^2.1.0: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -312,31 +291,14 @@ chalk@^2.0.0, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -371,16 +333,14 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" @@ -389,7 +349,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -420,10 +380,12 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: version "1.17.5" @@ -442,27 +404,6 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" -es-abstract@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -521,11 +462,12 @@ eslint-plugin-react-native-globals@^0.1.1: resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== -eslint-plugin-react-native@^3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.8.1.tgz#92811e37191ecb0d29c0f0a0c9e5c943ee573821" - integrity sha512-6Z4s4nvgFRdda/1s1+uu4a6EMZwEjjJ9Bk/1yBImv0fd9U2CsGu2cUakAtV83cZKhizbWhSouXoaK4JtlScdFg== +eslint-plugin-react-native@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.10.0.tgz#240f7e6979a908af3dfd9ba9652434c33f4d64cd" + integrity sha512-4f5+hHYYq5wFhB5eptkPEAR7FfvqbS7AzScUOANfAMZtYw5qgnCxRq45bpfBaQF+iyPMim5Q8pubcpvLv75NAg== dependencies: + "@babel/traverse" "^7.7.4" eslint-plugin-react-native-globals "^0.1.1" eslint-plugin-react@^7.20.0: @@ -545,54 +487,49 @@ eslint-plugin-react@^7.20.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint@7.12.0: + version "7.12.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.0.tgz#7b6a85f87a9adc239e979bb721cde5ce0dc27da6" + integrity sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.0" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" @@ -601,77 +538,66 @@ eslint@^6.5.1: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash "^4.17.19" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" table "^5.2.3" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== dependencies: - acorn "^7.1.1" + acorn "^7.4.0" acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= -external-editor@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - fast-deep-equal@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" @@ -687,18 +613,11 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -747,19 +666,7 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.6: +glob@^7.1.3, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -793,30 +700,18 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-symbols@^1.0.1: +has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -827,10 +722,10 @@ ignore@^5.0.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== -import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -853,25 +748,6 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -inquirer@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - internal-slot@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" @@ -881,12 +757,7 @@ internal-slot@^1.0.2: has "^1.0.3" side-channel "^1.0.2" -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-callable@^1.1.5: +is-callable@^1.1.4, is-callable@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== @@ -906,11 +777,6 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -918,18 +784,6 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - is-regex@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" @@ -990,23 +844,18 @@ jsx-ast-utils@^2.2.3: array-includes "^3.0.3" object.assign "^4.1.0" -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + prelude-ls "^1.2.1" + type-check "~0.4.0" -lodash@^4.17.10, lodash@^4.17.11: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== - -lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== loose-envify@^1.4.0: version "1.4.0" @@ -1015,11 +864,6 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -1044,21 +888,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -1069,16 +903,11 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-keys@^1.0.11, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@^1.0.12: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== - object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" @@ -1126,29 +955,17 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" parent-module@^1.0.0: version "1.0.0" @@ -1162,20 +979,20 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" @@ -1226,43 +1043,23 @@ regexp.prototype.flags@^1.3.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" - integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -resolve@^1.15.1: +resolve@^1.12.0, resolve@^1.15.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== dependencies: path-parse "^1.0.6" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -1270,51 +1067,22 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -run-async@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" - integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== - dependencies: - is-promise "^2.1.0" - -rxjs@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== - dependencies: - tslib "^1.9.0" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^5.5.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - -semver@^6.1.2: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2: +semver@^7.2.1, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - shebang-regex "^1.0.0" + shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== side-channel@^1.0.2: version "1.0.2" @@ -1324,11 +1092,6 @@ side-channel@^1.0.2: es-abstract "^1.17.0-next.1" object-inspect "^1.7.0" -signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -1357,15 +1120,6 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - string.prototype.matchall@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" @@ -1401,13 +1155,6 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -1415,10 +1162,10 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== supports-color@^5.3.0: version "5.5.0" @@ -1449,24 +1196,12 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== @@ -1478,17 +1213,12 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" - -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + prelude-ls "^1.2.1" type-fest@^0.8.1: version "0.8.1" @@ -1507,14 +1237,14 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== diff --git a/packages/eslint-plugin-codegen/BUCK b/packages/eslint-plugin-codegen/BUCK new file mode 100644 index 00000000000000..8fd38289431bdb --- /dev/null +++ b/packages/eslint-plugin-codegen/BUCK @@ -0,0 +1,23 @@ +load("@fbsource//tools/build_defs/third_party:yarn_defs.bzl", "yarn_workspace") + +yarn_workspace( + name = "yarn-workspace", + srcs = glob( + ["**/*.js"], + exclude = [ + "**/__fixtures__/**", + "**/__flowtests__/**", + "**/__mocks__/**", + "**/__server_snapshot_tests__/**", + "**/__tests__/**", + "**/node_modules/**", + "**/node_modules/.bin/**", + "**/.*", + "**/.*/**", + "**/.*/.*", + "**/*.xcodeproj/**", + "**/*.xcworkspace/**", + ], + ), + visibility = ["PUBLIC"], +) diff --git a/packages/eslint-plugin-codegen/__tests__/eslint-tester.js b/packages/eslint-plugin-codegen/__tests__/eslint-tester.js new file mode 100644 index 00000000000000..ea767a705b790f --- /dev/null +++ b/packages/eslint-plugin-codegen/__tests__/eslint-tester.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const ESLintTester = require('eslint').RuleTester; + +ESLintTester.setDefaultConfig({ + parser: require.resolve('babel-eslint'), + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, +}); + +module.exports = ESLintTester; diff --git a/packages/eslint-plugin-codegen/__tests__/react-native-modules-test.js b/packages/eslint-plugin-codegen/__tests__/react-native-modules-test.js new file mode 100644 index 00000000000000..7591ffb86a8d82 --- /dev/null +++ b/packages/eslint-plugin-codegen/__tests__/react-native-modules-test.js @@ -0,0 +1,58 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react_native + * @format + */ + +'use strict'; + +const ESLintTester = require('./eslint-tester.js'); + +const rule = require('../react-native-modules'); + +const NATIVE_MODULES_DIR = __dirname; + +const eslintTester = new ESLintTester(); + +const VALID_SPECS = [ + { + code: ` +import {TurboModuleRegistry, type TurboModule} from 'react-native'; +import type {UnsafeObject} from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + func1(a: string): UnsafeObject, +} +export default TurboModuleRegistry.get('XYZ'); + `, + filename: `${NATIVE_MODULES_DIR}/NativeXYZ.js`, + }, +]; + +const INVALID_SPECS = [ + // Untyped NativeModule require + { + code: ` +import {TurboModuleRegistry, type TurboModule} from 'react-native'; +export interface Spec extends TurboModule { + func1(a: string): {||}, +} +export default TurboModuleRegistry.get('XYZ'); + `, + filename: `${NATIVE_MODULES_DIR}/XYZ.js`, + errors: [ + { + message: rule.errors.misnamedHasteModule('XYZ'), + }, + ], + }, +]; + +eslintTester.run('../react-native-modules', rule, { + valid: VALID_SPECS, + invalid: INVALID_SPECS, +}); diff --git a/packages/eslint-plugin-codegen/index.js b/packages/eslint-plugin-codegen/index.js new file mode 100644 index 00000000000000..60a5f864f7ac42 --- /dev/null +++ b/packages/eslint-plugin-codegen/index.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react_native + * @format + */ + +'use strict'; + +const reactNativeModules = require('./react-native-modules'); + +module.exports = { + rules: { + 'react-native-modules': reactNativeModules, + }, +}; diff --git a/packages/eslint-plugin-codegen/package.json b/packages/eslint-plugin-codegen/package.json new file mode 100644 index 00000000000000..bb0c49d193183f --- /dev/null +++ b/packages/eslint-plugin-codegen/package.json @@ -0,0 +1,21 @@ +{ + "name": "@react-native/eslint-plugin-codegen", + "version": "0.0.1", + "description": "ESLint rules to validate NativeModule and Component Specs", + "main": "index.js", + "repository": { + "type": "git", + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/eslint-plugin-codegen" + }, + "dependencies": { + "@babel/core": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "flow-parser": "^0.121.0", + "make-dir": "^2.1.0", + "pirates":"^4.0.1", + "react-native-codegen": "*", + "source-map-support": "0.5.0" + }, + "license": "MIT" +} diff --git a/packages/eslint-plugin-codegen/react-native-modules.js b/packages/eslint-plugin-codegen/react-native-modules.js new file mode 100644 index 00000000000000..476624d024b705 --- /dev/null +++ b/packages/eslint-plugin-codegen/react-native-modules.js @@ -0,0 +1,158 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react_native + * @format + */ + +'use strict'; + +const path = require('path'); +const withBabelRegister = require('./with-babel-register'); + +const ERRORS = { + misnamedHasteModule(hasteModuleName) { + return `Module ${hasteModuleName}: All files using TurboModuleRegistry must start with Native.`; + }, +}; + +let RNModuleParser; +let RNParserUtils; + +function requireModuleParser() { + if (RNModuleParser == null || RNParserUtils == null) { + const config = { + only: [/react-native-codegen\/src\//], + plugins: [require('@babel/plugin-transform-flow-strip-types').default], + }; + + withBabelRegister(config, () => { + RNModuleParser = require('react-native-codegen/src/parsers/flow/modules'); + RNParserUtils = require('react-native-codegen/src/parsers/flow/utils'); + }); + } + + return { + buildModuleSchema: RNModuleParser.buildModuleSchema, + createParserErrorCapturer: RNParserUtils.createParserErrorCapturer, + }; +} + +const VALID_SPEC_NAMES = /^Native\S+$/; + +function isModuleRequire(node) { + if (node.type !== 'CallExpression') { + return false; + } + + const callExpression = node; + + if (callExpression.callee.type !== 'MemberExpression') { + return false; + } + + const memberExpression = callExpression.callee; + if ( + !( + memberExpression.object.type === 'Identifier' && + memberExpression.object.name === 'TurboModuleRegistry' + ) + ) { + return false; + } + + if ( + !( + memberExpression.property.type === 'Identifier' && + (memberExpression.property.name === 'get' || + memberExpression.property.name === 'getEnforcing') + ) + ) { + return false; + } + return true; +} + +function isGeneratedFile(context) { + return ( + context + .getSourceCode() + .getText() + .indexOf('@' + 'generated SignedSource<<') !== -1 + ); +} + +/** + * A lint rule to guide best practices in writing type safe React NativeModules. + */ +function rule(context) { + const filename = context.getFilename(); + const hasteModuleName = path.basename(filename).replace(/\.js$/, ''); + + if (isGeneratedFile(context)) { + return {}; + } + + let isModule = false; + + return { + 'Program:exit': function(node) { + if (!isModule) { + return; + } + + // Report invalid file names + if (!VALID_SPEC_NAMES.test(hasteModuleName)) { + context.report({ + node, + message: ERRORS.misnamedHasteModule(hasteModuleName), + }); + } + + const { + buildModuleSchema, + createParserErrorCapturer, + } = requireModuleParser(); + const flowParser = require('flow-parser'); + + const [parsingErrors, tryParse] = createParserErrorCapturer(); + + const sourceCode = context.getSourceCode().getText(); + const ast = flowParser.parse(sourceCode); + + tryParse(() => { + buildModuleSchema(hasteModuleName, ast, tryParse); + }); + + parsingErrors.forEach(error => { + error.nodes.forEach(flowNode => { + context.report({ + loc: flowNode.loc, + message: error.message, + }); + }); + }); + }, + CallExpression(node) { + if (!isModuleRequire(node)) { + return; + } + + isModule = true; + }, + InterfaceExtends(node) { + if (node.id.name !== 'TurboModule') { + return; + } + + isModule = true; + }, + }; +} + +rule.errors = ERRORS; + +module.exports = rule; diff --git a/packages/eslint-plugin-codegen/with-babel-register/disk-cache.js b/packages/eslint-plugin-codegen/with-babel-register/disk-cache.js new file mode 100644 index 00000000000000..9d318a39bf6a39 --- /dev/null +++ b/packages/eslint-plugin-codegen/with-babel-register/disk-cache.js @@ -0,0 +1,131 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react_native + * @format + */ + +const path = require('path'); +const fs = require('fs'); +const os = require('os'); +const {sync: makeDirSync} = require('make-dir'); + +const packageJson = JSON.parse( + fs.readFileSync(require.resolve('../package.json'), 'utf8'), +); + +/** + * This file is a fork of + * https://github.com/babel/babel/blob/2782a549e99d2ef1816332d23d7dfd5190f58a0f/packages/babel-register/src/cache.js#L1 + */ + +const FILENAME = path.join( + os.tmpdir(), + `.eslint-plugin-codegen.${packageJson.version}.disk-cache.json`, +); + +let data = {}; + +let cacheDisabled = process.env.NODE_ENV === 'test'; + +function isCacheDisabled() { + return cacheDisabled; +} + +/** + * Write stringified cache to disk. + */ +function save() { + if (isCacheDisabled()) { + return; + } + + let serialised = '{}'; + + try { + serialised = JSON.stringify(data, null, ' '); + } catch (err) { + if (err.message === 'Invalid string length') { + err.message = "Cache too large so it's been cleared."; + console.error(err.stack); + } else { + throw err; + } + } + + try { + makeDirSync(path.dirname(FILENAME)); + fs.writeFileSync(FILENAME, serialised); + } catch (e) { + switch (e.code) { + // workaround https://github.com/nodejs/node/issues/31481 + // todo: remove the ENOENT error check when we drop node.js 13 support + case 'ENOENT': + case 'EACCES': + case 'EPERM': + console.warn( + `Could not write cache to file: ${FILENAME} due to a permission issue. Cache is disabled.`, + ); + cacheDisabled = true; + break; + case 'EROFS': + console.warn( + `Could not write cache to file: ${FILENAME} because it resides in a readonly filesystem. Cache is disabled.`, + ); + cacheDisabled = true; + break; + default: + throw e; + } + } +} + +/** + * Load cache from disk and parse. + */ + +function load() { + if (isCacheDisabled()) { + data = {}; + return; + } + + process.on('exit', save); + process.nextTick(save); + + let cacheContent; + + try { + cacheContent = fs.readFileSync(FILENAME); + } catch (e) { + switch (e.code) { + // check EACCES only as fs.readFileSync will never throw EPERM on Windows + // https://github.com/libuv/libuv/blob/076df64dbbda4320f93375913a728efc40e12d37/src/win/fs.c#L735 + case 'EACCES': + console.warn( + `Babel could not read cache file: ${FILENAME} due to a permission issue. Cache is disabled.`, + ); + cacheDisabled = true; + /* fall through */ + default: + return; + } + } + + try { + data = JSON.parse(cacheContent); + } catch {} +} + +/** + * Retrieve data from cache. + */ + +function get() { + return data; +} + +module.exports = {load, get}; diff --git a/packages/eslint-plugin-codegen/with-babel-register/index.js b/packages/eslint-plugin-codegen/with-babel-register/index.js new file mode 100644 index 00000000000000..c8b2484e5fa5ef --- /dev/null +++ b/packages/eslint-plugin-codegen/with-babel-register/index.js @@ -0,0 +1,110 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react_native + * @format + */ + +const babel = require('@babel/core'); +const {OptionManager, DEFAULT_EXTENSIONS} = require('@babel/core'); +const sourceMapSupport = require('source-map-support'); +const {addHook} = require('pirates'); +const path = require('path'); +const fs = require('fs'); +const diskCache = require('./disk-cache'); + +function compile(sourceMapManager, cache, options, code, filename) { + const opts = new OptionManager().init({ + sourceRoot: path.dirname(filename) + path.sep, + ...options, + filename, + }); + + // Bail out ASAP if the file has been ignored. + if (opts === null) { + return code; + } + + let output = cache[filename]; + + if (!output || output.mtime !== mtime(filename)) { + output = babel.transformSync(code, { + ...opts, + sourceMaps: opts.sourceMaps === undefined ? 'both' : opts.sourceMaps, + ast: false, + }); + + cache[filename] = output; + output.mtime = mtime(filename); + } + + if (!sourceMapManager.isInstalled) { + sourceMapManager.install(); + } + + if (output.map) { + sourceMapManager.maps[filename] = output.map; + } + + return output.code; +} + +function mtime(filename) { + return +fs.statSync(filename).mtime; +} + +function withBabelRegister(options, fn) { + let revertHook; + /** + * TODO: Do source maps break when we use a require hook + * to before we initialize the ESLint plugin? + */ + const sourceMapManager = { + isInstalled: false, + maps: {}, + install() { + if (sourceMapManager.isInstalled) { + return; + } + sourceMapManager.isInstalled = true; + sourceMapSupport.install({ + handleUncaughtExceptions: true, + environment: 'node', + retrieveSourceMap(filename) { + const map = sourceMapManager.maps && sourceMapManager.maps[filename]; + if (map) { + return { + url: null, + map: map, + }; + } else { + return null; + } + }, + }); + }, + }; + + diskCache.load(); + const cache = diskCache.get(); + + try { + revertHook = addHook( + (code, filename) => { + return compile(sourceMapManager, cache, options, code, filename); + }, + { + exts: DEFAULT_EXTENSIONS, + ignoreNodeModules: false, + }, + ); + return fn(); + } finally { + revertHook(); + } +} + +module.exports = withBabelRegister; diff --git a/packages/eslint-plugin-react-native-community/package.json b/packages/eslint-plugin-react-native-community/package.json index dad503b7c0e447..947d62498461b2 100644 --- a/packages/eslint-plugin-react-native-community/package.json +++ b/packages/eslint-plugin-react-native-community/package.json @@ -5,7 +5,8 @@ "main": "index.js", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/eslint-plugin-react-native-community" }, "license": "MIT" } diff --git a/packages/normalize-color/BUCK b/packages/normalize-color/BUCK index 50fab1d885b8ab..e99164634de048 100644 --- a/packages/normalize-color/BUCK +++ b/packages/normalize-color/BUCK @@ -11,7 +11,6 @@ rn_library( labels = ["supermodule:xplat/default/public.react_native.core"], skip_processors = True, visibility = ["PUBLIC"], - worker = "//xplat/js:experimental-packager", ) yarn_workspace( diff --git a/packages/normalize-color/package.json b/packages/normalize-color/package.json index a9fd8fcef1b23d..9ff2e8a0733d9f 100644 --- a/packages/normalize-color/package.json +++ b/packages/normalize-color/package.json @@ -4,7 +4,8 @@ "description": "Color normalization code for React Native.", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/normalize-color" }, "license": "MIT" } diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index ed96b9f671dea5..6f00c64c7fca72 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -4,7 +4,8 @@ "description": "Polyfills for React Native.", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/polyfills" }, "license": "MIT" } diff --git a/packages/react-native-codegen/.babelrc b/packages/react-native-codegen/.babelrc index b8ac81899b77e0..7a6194fbaa55d8 100644 --- a/packages/react-native-codegen/.babelrc +++ b/packages/react-native-codegen/.babelrc @@ -5,6 +5,7 @@ "@babel/plugin-transform-destructuring", "@babel/plugin-transform-flow-strip-types", "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining" ] diff --git a/packages/react-native-codegen/BUCK b/packages/react-native-codegen/BUCK index ca38d2bb4dc7ef..d25c4ac87ea24a 100644 --- a/packages/react-native-codegen/BUCK +++ b/packages/react-native-codegen/BUCK @@ -1,55 +1,13 @@ -load("@fbsource//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("@fbsource//tools/build_defs:fb_xplat_cxx_binary.bzl", "fb_xplat_cxx_binary") -load("@fbsource//tools/build_defs:platform_defs.bzl", "ANDROID", "APPLE", "IOS") -load("@fbsource//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_xplat_cxx_library") -load("@fbsource//tools/build_defs/third_party:yarn_defs.bzl", "yarn_workspace") -load("@fbsource//xplat/js/react-native-github/packages/react-native-codegen:DEFS.bzl", "rn_codegen_components", "rn_codegen_modules") -load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target") +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "IOS", "IS_OSS_BUILD", "react_native_root_target", "react_native_target", "rn_android_library", "rn_xplat_cxx_library") +load("//tools/build_defs/third_party:yarn_defs.bzl", "yarn_workspace") +load(":DEFS.bzl", "rn_codegen_cli", "rn_codegen_components", "rn_codegen_modules") -fb_native.sh_binary( - name = "codegen_rn_modules_tests", - main = "src/cli/verify_with_old_codegen.sh", - visibility = ["PUBLIC"], - resources = [ - "src/cli/verify_with_old_codegen.js", - "src/cli/verify_with_old_codegen.sh", - "//xplat/js:setup_env", - ], -) +rn_codegen_cli() -fb_native.sh_test( - name = "verify_all_modules_with_old_codegen", - test = "src/cli/verify_all_modules_with_old_codegen.sh", - visibility = ["PUBLIC"], -) - -fb_native.sh_binary( - name = "write_to_json", - main = "src/cli/combine/combine_js_to_schema.sh", - resources = [ - "src/cli/combine/combine-js-to-schema.js", - "src/cli/combine/combine_js_to_schema.sh", - ":yarn-workspace", - "//xplat/js:setup_env", - ], - visibility = ["PUBLIC"], -) - -fb_native.sh_binary( - name = "rn_codegen", - main = "buck_tests/generate-tests.sh", - resources = glob( - [ - "buck_tests/**/*.js", - "src/**/*.js", - ], - ) + [ - "buck_tests/generate-tests.js", - "package.json", - "//xplat/js:setup_env", - ], - visibility = ["PUBLIC"], -) +SETUP_ENV_DEPS = [] if IS_OSS_BUILD else [ + "//xplat/js:setup_env", +] fb_native.genrule( name = "codegen_tests_schema", @@ -59,7 +17,7 @@ fb_native.genrule( "**/e2e/__test_fixtures__/modules/Native*.js", ], ), - cmd = "$(exe //xplat/js/react-native-github/packages/react-native-codegen:write_to_json) $OUT $SRCS", + cmd = "$(exe {}) $OUT $SRCS".format(react_native_root_target("packages/react-native-codegen:write_to_json")), out = "schema-codegen_tests.json", ) @@ -69,37 +27,18 @@ rn_codegen_components( ) rn_codegen_modules( - name = "codegen_tests", - native_module_spec_name = "FBReactNativeTestSpec", + name = "FBReactNativeTestSpec", + android_package_name = "com.facebook.fbreact.specs", schema_target = ":codegen_tests_schema", ) -fb_xplat_cxx_binary( - name = "rn_codegen_binary", - srcs = ["buck_tests/emptyFile.cpp"], - compiler_flags = [ - "-fexceptions", - "-frtti", - "-std=c++14", - "-Wall", - ], - platforms = (ANDROID, APPLE), - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - visibility = ["PUBLIC"], - deps = [ - ":generated_components-codegen_tests", - ], -) - rn_android_library( name = "rn_codegen_library_java", srcs = glob( ["**/*.java"], exclude = ["android/gradlePlugin-build/**/*"], ), + autoglob = False, visibility = [ "PUBLIC", ], @@ -155,8 +94,8 @@ rn_xplat_cxx_library( "PUBLIC", ], deps = [ + ":FBReactNativeTestSpec", ":generated_components-codegen_tests", - ":generated_objcpp_modules-codegen_tests", ], ) diff --git a/packages/react-native-codegen/DEFS.bzl b/packages/react-native-codegen/DEFS.bzl index da49dac7fbdb32..3652e494556cba 100644 --- a/packages/react-native-codegen/DEFS.bzl +++ b/packages/react-native-codegen/DEFS.bzl @@ -1,90 +1,270 @@ -load("@fbsource//tools/build_defs:buckconfig.bzl", "read_bool") -load("@fbsource//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("@fbsource//tools/build_defs:platform_defs.bzl", "IOS", "MACOSX") -load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode") +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +load("//tools/build_defs:buckconfig.bzl", "read_bool") +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") load( "//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "CXX", + "IOS", + "IS_OSS_BUILD", + "MACOSX", "YOGA_CXX_TARGET", "fb_xplat_cxx_test", "get_apple_compiler_flags", "get_apple_inspector_flags", + "get_preprocessor_flags_for_build_mode", "react_native_dep", + "react_native_root_target", "react_native_target", + "react_native_xplat_shared_library_target", "react_native_xplat_target", + "react_native_xplat_target_apple", "rn_android_library", + "rn_apple_library", "rn_xplat_cxx_library", ) +# Call this in the react-native-codegen/BUCK file +def rn_codegen_cli(): + if not IS_OSS_BUILD: + # FB Internal Setup + fb_native.sh_binary( + name = "write_to_json", + main = "src/cli/combine/combine_js_to_schema.sh", + resources = [ + "src/cli/combine/combine-js-to-schema.js", + "src/cli/combine/combine_js_to_schema.sh", + ":yarn-workspace", + "//xplat/js:setup_env", + ], + visibility = ["PUBLIC"], + ) + + fb_native.sh_binary( + name = "generate_all_from_schema", + main = "src/cli/generators/generate-all.sh", + resources = native.glob( + [ + "buck_tests/**/*.js", + "src/**/*.js", + ], + ) + [ + "package.json", + "//xplat/js:setup_env", + ], + visibility = ["PUBLIC"], + ) + else: + # OSS setup, assumes yarn and node (v12.0.0+) are installed. + fb_native.genrule( + name = "setup_cli", + srcs = native.glob([ + "scripts/**/*", + "src/**/*", + ], exclude = [ + "__tests__/**/*", + ]) + [ + ".babelrc", + ".prettierrc", + "package.json", + ], + out = "build", + bash = r""" + set -euo pipefail + mkdir -p "$OUT" + rsync -rLptgoD "$SRCDIR/" "$OUT" + cd "$OUT" + yarn install 2> >(grep -v '^warning' 1>&2) + yarn run build + """, + ) + + fb_native.sh_binary( + name = "write_to_json", + main = "scripts/buck-oss/combine_js_to_schema.sh", + resources = [ + ":setup_cli", + ], + visibility = ["PUBLIC"], + ) + + fb_native.sh_binary( + name = "generate_all_from_schema", + main = "scripts/buck-oss/generate-all.sh", + resources = [ + ":setup_cli", + ], + visibility = ["PUBLIC"], + ) + def rn_codegen_modules( - native_module_spec_name, - name = "", + name, + android_package_name, + library_labels = [], schema_target = ""): - generate_fixtures_rule_name = "generate_fixtures_modules-{}".format(name) - generate_module_hobjcpp_name = "generate_module_hobjcpp-{}".format(name) - generate_module_mm_name = "generate_module_mm-{}".format(name) + generate_fixtures_rule_name = "{}-codegen-modules".format(name) + generate_module_hobjcpp_name = "{}-codegen-modules-hobjcpp".format(name) + generate_module_mm_name = "{}-codegen-modules-mm".format(name) + generate_module_java_name = "{}-codegen-modules-java".format(name) + generate_module_java_zip_name = "{}-codegen-modules-java_zip".format(name) + generate_module_jni_h_name = "{}-codegen-modules-jni_h".format(name) + generate_module_jni_cpp_name = "{}-codegen-modules-jni_cpp".format(name) fb_native.genrule( name = generate_fixtures_rule_name, srcs = native.glob(["src/generators/**/*.js"]), - cmd = "$(exe //xplat/js/react-native-github/packages/react-native-codegen:rn_codegen) $(location {}) {} $OUT {}".format(schema_target, name, native_module_spec_name), + cmd = "$(exe {generator_script}) $(location {schema_target}) {library_name} $OUT {android_package_name}".format( + generator_script = react_native_root_target("packages/react-native-codegen:generate_all_from_schema"), + schema_target = schema_target, + library_name = name, + android_package_name = android_package_name, + ), out = "codegenfiles-{}".format(name), labels = ["codegen_rule"], ) + ################## + # Android handling + ################## + fb_native.genrule( + name = generate_module_java_name, + cmd = "mkdir -p $OUT/{spec_path} && cp -r $(location {generator_target})/java/{spec_path}/* $OUT/{spec_path}/".format( + spec_path = android_package_name.replace(".", "/"), + generator_target = ":" + generate_fixtures_rule_name, + ), + out = "src", + labels = ["codegen_rule"], + ) + + fb_native.zip_file( + name = generate_module_java_zip_name, + srcs = [":{}".format(generate_module_java_name)], + out = "{}.src.zip".format(generate_module_java_zip_name), + labels = ["codegen_rule"], + ) + fb_native.genrule( - name = generate_module_hobjcpp_name, - cmd = "cp $(location :{})/{}.h $OUT".format(generate_fixtures_rule_name, native_module_spec_name), - out = "{}.h".format(native_module_spec_name), + name = generate_module_jni_h_name, + cmd = "cp $(location :{})/jni/{}.h $OUT".format(generate_fixtures_rule_name, name), + out = "{}.h".format(name), labels = ["codegen_rule"], ) fb_native.genrule( - name = generate_module_mm_name, - cmd = "cp $(location :{})/{}-generated.mm $OUT".format(generate_fixtures_rule_name, native_module_spec_name), - out = "{}-generated.mm".format(native_module_spec_name), + name = generate_module_jni_cpp_name, + cmd = "cp $(location :{})/jni/{}-generated.cpp $OUT".format(generate_fixtures_rule_name, name), + out = "{}-generated.cpp".format(name), labels = ["codegen_rule"], ) + rn_android_library( + name = "{}".format(name), + srcs = [ + ":{}".format(generate_module_java_zip_name), + ], + autoglob = False, + labels = library_labels + ["codegen_rule"], + visibility = ["PUBLIC"], + deps = [ + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_dep("third-party/java/jsr-330:jsr-330"), + react_native_target("java/com/facebook/react/bridge:bridge"), + react_native_target("java/com/facebook/react/common:common"), + ], + exported_deps = [ + react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), + ], + ) + rn_xplat_cxx_library( - name = "generated_objcpp_modules-{}".format(name), - header_namespace = native_module_spec_name, - apple_sdks = (IOS), + name = "{}-jni".format(name), + srcs = [ + ":{}".format(generate_module_jni_cpp_name), + ], + header_namespace = "", + headers = [ + ":{}".format(generate_module_jni_h_name), + ], + exported_headers = { + "{}/{}.h".format(name, name): ":{}".format(generate_module_jni_h_name), + }, compiler_flags = [ "-fexceptions", "-frtti", "-std=c++14", "-Wall", ], - fbobjc_compiler_flags = get_apple_compiler_flags(), - fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), - ios_exported_headers = { - "{}.h".format(native_module_spec_name): ":{}".format(generate_module_hobjcpp_name), - "{}-generated.mm".format(native_module_spec_name): ":{}".format(generate_module_mm_name), - }, - ios_headers = [ - ":{}".format(generate_module_hobjcpp_name), - ], - ios_srcs = [ - ":{}".format(generate_module_mm_name), - ], - labels = ["codegen_rule"], - platforms = (APPLE), + force_static = True, preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", ], - visibility = ["PUBLIC"], - deps = [ - "//xplat/js:React", + visibility = [ + "PUBLIC", + ], + deps = [], + exported_deps = [ + react_native_xplat_shared_library_target("jsi:jsi"), + react_native_xplat_target("react/nativemodule/core:core"), ], + platforms = (ANDROID,), + labels = library_labels + ["codegen_rule"], ) + ############## + # iOS handling + ############## + if not IS_OSS_BUILD: + # iOS Buck build isn't fully working in OSS, so let's skip it for OSS for now. + fb_native.genrule( + name = generate_module_hobjcpp_name, + cmd = "cp $(location :{})/{}.h $OUT".format(generate_fixtures_rule_name, name), + out = "{}.h".format(name), + labels = ["codegen_rule"], + ) + + fb_native.genrule( + name = generate_module_mm_name, + cmd = "cp $(location :{})/{}-generated.mm $OUT".format(generate_fixtures_rule_name, name), + out = "{}-generated.mm".format(name), + labels = ["codegen_rule"], + ) + + rn_apple_library( + name = "{}Apple".format(name), + extension_api_only = True, + header_namespace = "", + sdks = (IOS), + compiler_flags = [ + "-Wno-unused-private-field", + ], + exported_headers = { + "{}/{}.h".format(name, name): ":{}".format(generate_module_hobjcpp_name), + }, + headers = [ + ":{}".format(generate_module_hobjcpp_name), + ], + srcs = [ + ":{}".format(generate_module_mm_name), + ], + labels = library_labels + ["codegen_rule"], + visibility = ["PUBLIC"], + exported_deps = [ + "//xplat/js/react-native-github:RCTTypeSafety", + "//xplat/js/react-native-github/Libraries/RCTRequired:RCTRequired", + react_native_xplat_target_apple("react/nativemodule/core:core"), + ], + ) + def rn_codegen_components( name = "", - schema_target = ""): + schema_target = "", + library_labels = []): generate_fixtures_rule_name = "generate_fixtures_components-{}".format(name) generate_component_descriptor_h_name = "generate_component_descriptor_h-{}".format(name) generate_component_hobjcpp_name = "generate_component_hobjcpp-{}".format(name) @@ -103,7 +283,7 @@ def rn_codegen_components( fb_native.genrule( name = generate_fixtures_rule_name, srcs = native.glob(["src/generators/**/*.js"]), - cmd = "$(exe //xplat/js/react-native-github/packages/react-native-codegen:rn_codegen) $(location {}) {} $OUT {}".format(schema_target, name, name), + cmd = "$(exe {}) $(location {}) {} $OUT".format(react_native_root_target("packages/react-native-codegen:generate_all_from_schema"), schema_target, name), out = "codegenfiles-{}".format(name), labels = ["codegen_rule"], ) @@ -159,7 +339,9 @@ def rn_codegen_components( fb_native.genrule( name = copy_generated_java_files, - cmd = "mkdir $OUT && find $(location :{}) -name '*.java' -exec cp {{}} $OUT \\;".format(generate_fixtures_rule_name), + # TODO: support different package name internally. + # Right now, it's hardcoded to `com.facebook.react.viewmanagers`. + cmd = "mkdir -p $OUT/com/facebook/react/viewmanagers && cp -R $(location :{})/java/com/facebook/react/viewmanagers/* $OUT/com/facebook/react/viewmanagers".format(generate_fixtures_rule_name), out = "java", labels = ["codegen_rule"], ) @@ -202,85 +384,113 @@ def rn_codegen_components( labels = ["codegen_rule"], ) - # libs - if is_running_buck_project(): - rn_xplat_cxx_library(name = "generated_components-{}".format(name), visibility = ["PUBLIC"]) - else: - rn_xplat_cxx_library( - name = "generated_components-{}".format(name), + ############## + # iOS handling + ############## + if not IS_OSS_BUILD: + # iOS Buck build isn't fully working in OSS, so let's skip it for OSS for now. + if is_running_buck_project(): + rn_xplat_cxx_library(name = "generated_components-{}".format(name), visibility = ["PUBLIC"]) + else: + rn_xplat_cxx_library( + name = "generated_components-{}".format(name), + srcs = [ + ":{}".format(generate_event_emitter_cpp_name), + ":{}".format(generate_props_cpp_name), + ":{}".format(generate_shadow_node_cpp_name), + ], + headers = [ + ":{}".format(generate_component_descriptor_h_name), + ":{}".format(generate_event_emitter_h_name), + ":{}".format(generate_props_h_name), + ":{}".format(generate_shadow_node_h_name), + ], + header_namespace = "react/renderer/components/{}".format(name), + exported_headers = { + "ComponentDescriptors.h": ":{}".format(generate_component_descriptor_h_name), + "EventEmitters.h": ":{}".format(generate_event_emitter_h_name), + "Props.h": ":{}".format(generate_props_h_name), + "RCTComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name), + "ShadowNodes.h": ":{}".format(generate_shadow_node_h_name), + }, + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++14", + "-Wall", + ], + fbobjc_compiler_flags = get_apple_compiler_flags(), + fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), + ios_exported_headers = { + "ComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name), + }, + ios_headers = [ + ":{}".format(generate_component_hobjcpp_name), + ], + labels = library_labels + ["codegen_rule"], + platforms = (ANDROID, APPLE, CXX), + preprocessor_flags = [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], + tests = [":generated_tests-{}".format(name)], + visibility = ["PUBLIC"], + deps = [ + "//third-party/glog:glog", + "//xplat/fbsystrace:fbsystrace", + "//xplat/folly:headers_only", + "//xplat/folly:memory", + "//xplat/folly:molly", + YOGA_CXX_TARGET, + react_native_xplat_target("react/renderer/debug:debug"), + react_native_xplat_target("react/renderer/core:core"), + react_native_xplat_target("react/renderer/graphics:graphics"), + react_native_xplat_target("react/renderer/components/image:image"), + react_native_xplat_target("react/renderer/imagemanager:imagemanager"), + react_native_xplat_target("react/renderer/components/view:view"), + ], + ) + + # Tests + fb_xplat_cxx_test( + name = "generated_tests-{}".format(name), srcs = [ - ":{}".format(generate_event_emitter_cpp_name), - ":{}".format(generate_props_cpp_name), - ":{}".format(generate_shadow_node_cpp_name), + ":{}".format(generate_tests_cpp_name), ], - headers = [ - ":{}".format(generate_component_descriptor_h_name), - ":{}".format(generate_event_emitter_h_name), - ":{}".format(generate_props_h_name), - ":{}".format(generate_shadow_node_h_name), - ], - header_namespace = "react/renderer/components/{}".format(name), - exported_headers = { - "ComponentDescriptors.h": ":{}".format(generate_component_descriptor_h_name), - "EventEmitters.h": ":{}".format(generate_event_emitter_h_name), - "Props.h": ":{}".format(generate_props_h_name), - "RCTComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name), - "ShadowNodes.h": ":{}".format(generate_shadow_node_h_name), - }, + apple_sdks = (IOS, MACOSX), compiler_flags = [ "-fexceptions", "-frtti", "-std=c++14", "-Wall", ], - fbobjc_compiler_flags = get_apple_compiler_flags(), - fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), - ios_exported_headers = { - "ComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name), - }, - ios_headers = [ - ":{}".format(generate_component_hobjcpp_name), - ], - labels = ["codegen_rule"], + contacts = ["oncall+react_native@xmail.facebook.com"], + labels = library_labels + ["codegen_rule"], platforms = (ANDROID, APPLE, CXX), - preprocessor_flags = [ - "-DLOG_TAG=\"ReactNative\"", - "-DWITH_FBSYSTRACE=1", - ], - tests = [":generated_tests-{}".format(name)], - visibility = ["PUBLIC"], deps = [ - "//third-party/glog:glog", - "//xplat/fbsystrace:fbsystrace", - "//xplat/folly:headers_only", - "//xplat/folly:memory", - "//xplat/folly:molly", - YOGA_CXX_TARGET, - react_native_xplat_target("react/renderer/debug:debug"), - react_native_xplat_target("react/renderer/core:core"), - react_native_xplat_target("react/renderer/graphics:graphics"), - react_native_xplat_target("react/renderer/components/image:image"), - react_native_xplat_target("react/renderer/imagemanager:imagemanager"), - react_native_xplat_target("react/renderer/components/view:view"), + "//xplat/third-party/gmock:gtest", + ":generated_components-{}".format(name), ], ) + ################## + # Android handling + ################## if is_running_buck_project(): - rn_android_library(name = "generated_components_java-{}".format(name)) + rn_android_library(name = "generated_components_java-{}".format(name), autoglob = False) else: rn_android_library( name = "generated_components_java-{}".format(name), srcs = [ ":{}".format(zip_generated_java_files), ], - labels = ["codegen_rule"], + autoglob = False, + labels = library_labels + ["codegen_rule"], visibility = ["PUBLIC"], deps = [ react_native_dep("third-party/android/androidx:annotation"), react_native_target("java/com/facebook/react/bridge:bridge"), - react_native_target("java/com/facebook/react/common:common"), - react_native_target("java/com/facebook/react/turbomodule/core:core"), - react_native_target("java/com/facebook/react/uimanager:uimanager"), + react_native_target("java/com/facebook/react/uimanager/interfaces:interfaces"), ], ) @@ -289,7 +499,8 @@ def rn_codegen_components( srcs = [ ":{}".format(zip_generated_cxx_files), ], - labels = ["codegen_rule"], + autoglob = False, + labels = library_labels + ["codegen_rule"], visibility = ["PUBLIC"], deps = [ react_native_dep("third-party/android/androidx:annotation"), @@ -300,28 +511,6 @@ def rn_codegen_components( ], ) - # Tests - fb_xplat_cxx_test( - name = "generated_tests-{}".format(name), - srcs = [ - ":{}".format(generate_tests_cpp_name), - ], - apple_sdks = (IOS, MACOSX), - compiler_flags = [ - "-fexceptions", - "-frtti", - "-std=c++14", - "-Wall", - ], - contacts = ["oncall+react_native@xmail.facebook.com"], - labels = ["codegen_rule"], - platforms = (ANDROID, APPLE, CXX), - deps = [ - "//xplat/third-party/gmock:gtest", - ":generated_components-{}".format(name), - ], - ) - def rn_codegen_cxx_modules( name = "", schema_target = ""): @@ -332,7 +521,7 @@ def rn_codegen_cxx_modules( fb_native.genrule( name = generate_fixtures_rule_name, srcs = native.glob(["src/generators/**/*.js"]), - cmd = "$(exe //xplat/js/react-native-github/packages/react-native-codegen:rn_codegen) $(location {}) {} $OUT {}".format(schema_target, name, name), + cmd = "$(exe {}) $(location {}) {} $OUT {}".format(react_native_root_target("packages/react-native-codegen:generate_all_from_schema"), schema_target, name, name), out = "codegenfiles-{}".format(name), labels = ["codegen_rule"], ) @@ -383,7 +572,7 @@ def rn_codegen_cxx_modules( ], visibility = ["PUBLIC"], exported_deps = [ - react_native_xplat_target("turbomodule/core:core"), + react_native_xplat_target("react/nativemodule/core:core"), ], ) diff --git a/packages/react-native-codegen/android/build.gradle b/packages/react-native-codegen/android/build.gradle index 69934710e3bdca..e84754762c4112 100644 --- a/packages/react-native-codegen/android/build.gradle +++ b/packages/react-native-codegen/android/build.gradle @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +import org.apache.tools.ant.taskdefs.condition.Os + buildscript { repositories { mavenLocal() @@ -12,7 +14,7 @@ buildscript { jcenter() } dependencies { - classpath("com.android.tools.build:gradle:3.6.4") + classpath("com.android.tools.build:gradle:4.1.0") } } @@ -23,3 +25,42 @@ allprojects { jcenter() } } + +// This task is required when using react-native-codegen from source, instead of npm. +task('buildCodegenCLI', type: Exec) { + def codegenRoot = "$projectDir/.." + + inputs.files( + file("$codegenRoot/scripts"), + file("$codegenRoot/src"), + file("$codegenRoot/package.json"), + file("$codegenRoot/.babelrc"), + file("$codegenRoot/.prettierrc"), + ) + + def libDir = file("$codegenRoot/lib") + libDir.mkdirs() + def nodeModulesDir = file("$codegenRoot/node_modules") + nodeModulesDir.mkdirs(); + outputs.dirs(libDir, nodeModulesDir) + + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + // Convert path to Linux format: use canonical path to strip it off relative elements in the middle of the string. + // Then replace baskslashes with slashes, remove leading colon, add leading slash. + // Eg. D:\path1\sub2/.. -> /D/path1/path2 + String canonicalPath = new File(codegenRoot).getCanonicalPath() + String linuxPath = canonicalPath.replace('\\', '/'); + linuxPath = linuxPath.replace(':', '') + linuxPath = '/' + linuxPath + + // Get the location of bash in the system; assume environment variable created to store it. + String bashHome = "$System.env.REACT_WINDOWS_BASH" + if (bashHome == null) { + throw new GradleException("REACT_WINDOWS_BASH is not defined.") + } + commandLine(bashHome, "-c", "$linuxPath/scripts/oss/build.sh") + } + else { + commandLine("$codegenRoot/scripts/oss/build.sh") + } +} diff --git a/packages/react-native-codegen/android/generator/build.gradle b/packages/react-native-codegen/android/generator/build.gradle deleted file mode 100644 index 1ba58144a415db..00000000000000 --- a/packages/react-native-codegen/android/generator/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -plugins { - id 'java' - id 'application' -} - -dependencies { - implementation 'com.squareup:javapoet:1.13.0' -} - -application { - mainClassName = 'com.facebook.react.codegen.JavaGeneratorMain' -} diff --git a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties index bca17f36566b30..14e30f7416a55e 100644 --- a/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/react-native-codegen/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle index 616590c65c97b6..2eb21ffdc01217 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle @@ -19,7 +19,7 @@ gradlePlugin { } dependencies { - implementation 'com.android.tools.build:gradle:3.6.4' + implementation 'com.android.tools.build:gradle:4.1.0' // Use the same Gson version that `com.android.tools.build:gradle` depends on. implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.google.guava:guava:29.0-jre' diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java index ee2a968bd23011..c0abf23bbb7f24 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java @@ -84,7 +84,7 @@ private final void writeTypeSpecToFile(final TypeSpec typeSpec) // Instead of using JavaFile.writeTo() API, manage the output files ourselves because // JavaFile.addFileComment() does not support "block comment" style. // See https://github.com/square/javapoet/issues/682#issuecomment-512238075. - Path outputDirPath = mOutputDir.toPath(); + Path outputDirPath = new File(mOutputDir, "java").toPath(); if (Files.exists(outputDirPath) && !Files.isDirectory(outputDirPath)) { throw new CodegenException( diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java index 0b44b62826df84..422317a787341c 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java @@ -67,25 +67,29 @@ private TypeData buildTypeData(final File schemaFile) entry -> { final String jsModuleName = entry.getKey(); final JsonObject jsModule = entry.getValue().getAsJsonObject(); - final JsonObject nativeModules = jsModule.getAsJsonObject("nativeModules"); - if (nativeModules == null) { - // TODO: Handle components-related sections. + final String jsModuleType = jsModule.get("type").getAsString(); + + if (!"NativeModule".equals(jsModuleType)) { return; } - nativeModules - .entrySet() - .forEach( - e -> { - final Type parsedType = - parseNativeModule( - // TODO (T71955395): NativeModule spec type name does not - // exist in the schema. For now assume it's "Spec". - // The final type name will be the output class name. - TypeId.of(jsModuleName, "Native" + e.getKey() + "Spec"), - e.getValue().getAsJsonObject()); - mTypeData.addType(parsedType); - }); + if (jsModule.has("excludedPlatforms")) { + final JsonArray excludedPlatforms = jsModule.getAsJsonArray("excludedPlatforms"); + for (JsonElement p : excludedPlatforms) { + if (p.getAsString().equals("android")) { + // This module is not for Android. + return; + } + } + } + + final Type parsedType = + parseNativeModule( + // TODO (T71955395): NativeModule spec type name does not + // exist in the schema. For now assume it's "Spec". + // The final type name will be the output class name. + TypeId.of(jsModuleName, jsModuleName + "Spec"), jsModule); + mTypeData.addType(parsedType); }); } @@ -93,14 +97,18 @@ private TypeData buildTypeData(final File schemaFile) } // Parse type information from a JSON "typeAnnotation" node. - private Type parseTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) { - final String type = typeAnnotation.get("type").getAsString(); - // TODO (T71824250): Support NullableTypeAnnotation in the schema instead of a field here. - final boolean nullable = - typeAnnotation.has("nullable") ? typeAnnotation.get("nullable").getAsBoolean() : false; - + private Type parseTypeAnnotation(final TypeId typeId, final JsonObject originalTypeAnnotation) { + JsonObject typeAnnotation = originalTypeAnnotation; + String type = typeAnnotation.get("type").getAsString(); + boolean nullable = false; Type parsedType = null; + if (type.equals(NullableType.TYPE_NAME)) { + nullable = true; + typeAnnotation = typeAnnotation.get("typeAnnotation").getAsJsonObject(); + type = typeAnnotation.get("type").getAsString(); + } + switch (type) { case AliasType.TYPE_NAME: parsedType = parseAliasTypeAnnotation(typeId, typeAnnotation); @@ -158,7 +166,7 @@ private Type parseTypeAnnotation(final TypeId typeId, final JsonObject typeAnnot private NativeModuleType parseNativeModule(final TypeId typeId, final JsonObject json) { final JsonObject aliases = json.getAsJsonObject("aliases"); - final JsonArray properties = json.getAsJsonArray("properties"); + final JsonArray properties = json.getAsJsonObject("spec").getAsJsonArray("properties"); final ImmutableList collectedAliases = ImmutableList.copyOf( @@ -178,10 +186,9 @@ private NativeModuleType parseNativeModule(final TypeId typeId, final JsonObject properties.forEach( p -> { final JsonObject node = p.getAsJsonObject(); - final String name = node.has("name") ? node.get("name").getAsString() : null; + final String name = node.get("name").getAsString(); final JsonObject typeAnnotation = node.getAsJsonObject("typeAnnotation"); - // TODO (T71845349): "optional" field shouldn't be part of the Function's typeAnnotation. - final boolean optional = typeAnnotation.get("optional").getAsBoolean(); + final boolean optional = node.get("optional").getAsBoolean(); final TypeId propertyTypeId = TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name)); collectedPropertiesBuilder.add( @@ -214,28 +221,21 @@ private Type parseFunctionTypeAnnotation(final TypeId typeId, final JsonObject t ImmutableList.Builder paramsList = new ImmutableList.Builder<>(); - // TODO (T71846321): Some functions are missing params specification. - if (params != null) { - for (int i = 0; i < params.size(); i++) { - final JsonElement p = params.get(i); - final JsonObject node = p.getAsJsonObject(); - final String name = node.has("name") ? node.get("name").getAsString() : ("Arg" + i); - paramsList.add( - FunctionType.createArgument( - name, - parseTypeAnnotation( - TypeId.expandOf( - typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name)), - node.getAsJsonObject("typeAnnotation")))); - } + for (int i = 0; i < params.size(); i++) { + final JsonElement p = params.get(i); + final JsonObject node = p.getAsJsonObject(); + final String name = node.get("name").getAsString(); + paramsList.add( + FunctionType.createArgument( + name, + parseTypeAnnotation( + TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name)), + node.getAsJsonObject("typeAnnotation")))); } - // TODO (T71846321): Some functions are missing a return type. final JsonObject returnTypeAnnotation = typeAnnotation.getAsJsonObject("returnTypeAnnotation"); final Type returnType = - returnTypeAnnotation != null - ? parseTypeAnnotation(TypeId.expandOf(typeId, "ReturnType"), returnTypeAnnotation) - : VoidType.VOID; + parseTypeAnnotation(TypeId.expandOf(typeId, "ReturnType"), returnTypeAnnotation); return new FunctionType(typeId, paramsList.build(), returnType); } @@ -247,18 +247,12 @@ private Type parseObjectTypeAnnotation(final TypeId typeId, final JsonObject typ properties.forEach( p -> { final JsonObject node = p.getAsJsonObject(); - final String name = node.has("name") ? node.get("name").getAsString() : null; + final String name = node.get("name").getAsString(); final boolean optional = node.get("optional").getAsBoolean(); final JsonObject propertyTypeAnnotation = node.getAsJsonObject("typeAnnotation"); final TypeId propertyTypeId = TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name)); - - // TODO (T67898313): Some object properties are missing typeAnnotation. - final Type propertyType = - propertyTypeAnnotation != null - ? parseTypeAnnotation(propertyTypeId, propertyTypeAnnotation) - : new AnyType(propertyTypeId); - + final Type propertyType = parseTypeAnnotation(propertyTypeId, propertyTypeAnnotation); propertiesList.add(new ObjectType.Property(name, propertyType, optional)); }); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java index b4051ac81d7f61..c243cae7d73a1e 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java @@ -8,7 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class PromiseType extends Type { - public static final String TYPE_NAME = "GenericPromiseTypeAnnotation"; + public static final String TYPE_NAME = "PromiseTypeAnnotation"; public PromiseType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java index 067f0b3c7a24c4..7896494eebb2f4 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java @@ -103,10 +103,13 @@ public MethodSpec getGeneratedMethodWithReactAnnotation(String methodName) { // React methods need special `@ReactMethod` annotation for now. methodBuilder.addAnnotation(annotationBuilder.build()); + // TODO(T82242829) Add @DoNotStrip annotation + return methodBuilder.build(); } private static @Nullable String getFalsyReturnStatement(TypeName returnType) { + // TODO: Handle nullable falsy return. if (returnType == TypeName.BOOLEAN) { return "return false"; } else if (returnType == TypeName.DOUBLE) { diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java index 4a4e0c823de2db..0665ddf548a0ea 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java @@ -26,7 +26,7 @@ public static VoidResolvedType create( @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - return TypeUtils.makeNullable(TypeName.VOID, mNullable); + return TypeName.VOID; } @Override diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java index 4ea0a13e09f6f3..dc760c3f17088c 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java @@ -33,15 +33,16 @@ public void apply(final Project project) { final File generatedSchemaFile = new File(generatedSrcDir, "schema.json"); // 2. Task: produce schema from JS files. + String os = System.getProperty("os.name").toLowerCase(); + project .getTasks() .register( "generateCodegenSchemaFromJavaScript", Exec.class, task -> { - if (!extension.enableCodegen) { - return; - } + // This is needed when using codegen from source, not from npm. + task.dependsOn(":packages:react-native-codegen:android:buildCodegenCLI"); task.doFirst( s -> { @@ -63,7 +64,7 @@ public void apply(final Project project) { ImmutableList execCommands = new ImmutableList.Builder() - .add("yarn") + .add(os.contains("windows") ? "yarn.cmd" : "yarn") .addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs)) .add(extension.codegenGenerateSchemaCLI().getAbsolutePath()) .add(generatedSchemaFile.getAbsolutePath()) @@ -79,56 +80,40 @@ public void apply(final Project project) { "generateCodegenArtifactsFromSchema", Exec.class, task -> { - if (!extension.enableCodegen) { - return; - } - task.dependsOn("generateCodegenSchemaFromJavaScript"); - // TODO: The codegen tool should produce this outputDir structure based on - // the provided Java package name. - File outputDir = - new File( - generatedSrcDir, - "java/" + extension.codegenJavaPackageName.replace(".", "/")); - task.getInputs() .files(project.fileTree(ImmutableMap.of("dir", extension.codegenDir()))); + task.getInputs().files(extension.codegenGenerateNativeModuleSpecsCLI()); task.getInputs().files(generatedSchemaFile); - task.getOutputs().dir(outputDir); + task.getOutputs().dir(generatedSrcDir); if (extension.useJavaGenerator) { task.doLast( s -> { generateJavaFromSchemaWithJavaGenerator( - generatedSchemaFile, - extension.codegenJavaPackageName, - new File(generatedSrcDir, "java")); + generatedSchemaFile, extension.codegenJavaPackageName, generatedSrcDir); }); - // TODO: generate JNI C++ files. - task.commandLine("echo"); - } else { - ImmutableList execCommands = - new ImmutableList.Builder() - .add("yarn") - .addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs)) - .add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath()) - .add("android") - .add(generatedSchemaFile.getAbsolutePath()) - .add(outputDir.getAbsolutePath()) - .build(); - task.commandLine(execCommands); } + + ImmutableList execCommands = + new ImmutableList.Builder() + .add(os.contains("windows") ? "yarn.cmd" : "yarn") + .addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs)) + .add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath()) + .add("android") + .add(generatedSchemaFile.getAbsolutePath()) + .add(generatedSrcDir.getAbsolutePath()) + .add(extension.libraryName) + .add(extension.codegenJavaPackageName) + .build(); + task.commandLine(execCommands); }); // 4. Add dependencies & generated sources to the project. // Note: This last step needs to happen after the project has been evaluated. project.afterEvaluate( s -> { - if (!extension.enableCodegen) { - return; - } - // `preBuild` is one of the base tasks automatically registered by Gradle. // This will invoke the codegen before compiling the entire project. Task preBuild = project.getTasks().findByName("preBuild"); @@ -151,7 +136,6 @@ public void apply(final Project project) { .getByName("main") .getJava() .srcDir(new File(generatedSrcDir, "java")); - // TODO: Add JNI sources. }); } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPluginExtension.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPluginExtension.java index 658230bd459337..4d734a1da7decc 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPluginExtension.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPluginExtension.java @@ -7,20 +7,22 @@ package com.facebook.react.codegen.plugin; +import com.google.common.base.CaseFormat; import java.io.File; +import java.util.StringTokenizer; import org.gradle.api.Project; public class CodegenPluginExtension { - // TODO: Remove beta. - public String codegenJavaPackageName = "com.facebook.fbreact.specs.beta"; - public boolean enableCodegen = false; + public String codegenJavaPackageName = "com.facebook.fbreact.specs"; public File jsRootDir; + public String libraryName; public String[] nodeExecutableAndArgs = {"node"}; public File reactNativeRootDir; public boolean useJavaGenerator = false; public CodegenPluginExtension(final Project project) { this.reactNativeRootDir = new File(project.getRootDir(), "node_modules/react-native"); + this.libraryName = projectPathToLibraryName(project.getPath()); } public File codegenDir() { @@ -32,6 +34,18 @@ public File codegenGenerateSchemaCLI() { } public File codegenGenerateNativeModuleSpecsCLI() { - return new File(this.reactNativeRootDir, "scripts/generate-native-modules-specs-cli.js"); + return new File(this.reactNativeRootDir, "scripts/generate-specs-cli.js"); + } + + private String projectPathToLibraryName(final String projectPath) { + final StringTokenizer tokenizer = new StringTokenizer(projectPath, ":-_."); + final StringBuilder nameBuilder = new StringBuilder(); + + while (tokenizer.hasMoreTokens()) { + nameBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, tokenizer.nextToken())); + } + nameBuilder.append("Spec"); + + return nameBuilder.toString(); } } diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js index b697ab954dd573..02784457c3bdfb 100644 --- a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js @@ -17,7 +17,6 @@ export interface Spec extends TurboModule { +getConstants: () => {| D?: ?boolean, A?: Array, - G?: any, E?: ?{| D?: ?boolean, E?: ?{| diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js index ee6c0983afb75f..c950ed9e288972 100644 --- a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js @@ -10,9 +10,16 @@ 'use strict'; -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; +type Animal = {| + name: string, +|}; + export interface Spec extends TurboModule { // Exported methods. +getConstants: () => {| @@ -26,7 +33,14 @@ export interface Spec extends TurboModule { +getString: (arg: string) => string; +getArray: (arg: Array) => Array; +getObject: (arg: Object) => Object; - +getValue: (x: number, y: string, z: Object) => Object; + +getObjectShape: (arg: {|prop: number|}) => {|prop: number|}; + +getAlias: (arg: Animal) => Animal; + +getRootTag: (arg: RootTag) => RootTag; + +getValue: ( + x: number, + getValuegetValuegetValuegetValuegetValuey: string, + z: Object, + ) => Object; +getValueWithCallback: (callback: (value: string) => void) => void; +getValueWithPromise: (error: boolean) => Promise; } diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js new file mode 100644 index 00000000000000..fce6f7c0f0fb6a --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = {| + name: string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants: () => {| + const1: Array, + const2: Array, + const3: Array, + id?: Array, + |}; + +voidFunc: () => void; + +getBool: (id: Array) => Array; + +getNumber: (arg: Array) => Array; + +getString: (arg: Array) => Array; + +getArray: (arg: Array>) => Array>; + +getObject: (arg: Array) => Array; + +getObjectShape: (arg: Array<{|prop: number|}>) => Array<{|prop: number|}>; + +getAlias: (arg: Array) => Array; + +getRootTag: (arg: Array) => Array; + +getValue: ( + x: Array, + y: Array, + z: Array, + ) => Array; + +getValueWithCallback: (callback: (value: Array) => void) => void; + +getValueWithPromise: (error: Array) => Promise>; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleArrays', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js new file mode 100644 index 00000000000000..ac7b57e386a2d0 --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = ?{| + name: ?string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants: () => {| + const1: ?boolean, + const2: ?number, + const3: ?string, + |}; + +voidFunc: () => void; + +getBool: (arg: ?boolean) => ?boolean; + +getNumber: (arg: ?number) => ?number; + +getString: (arg: ?string) => ?string; + +getArray: (arg: ?Array) => ?Array; + +getObject: (arg: ?Object) => ?Object; + +getObjectShape: (arg: ?{|prop: ?number|}) => ?{|prop: ?number|}; + +getAlias: (arg: ?Animal) => ?Animal; + +getRootTag: (arg: ?RootTag) => ?RootTag; + +getValue: (x: ?number, y: ?string, z: ?Object) => ?Object; + +getValueWithCallback: (callback: (value: ?string) => void) => void; + +getValueWithPromise: (error: ?boolean) => ?Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleNullable', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js new file mode 100644 index 00000000000000..29e54d8a5c3693 --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = ?{| + name?: ?string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants?: () => {| + const1?: ?boolean, + const2?: ?number, + const3?: ?string, + |}; + +voidFunc?: () => void; + +getBool?: (arg?: ?boolean) => ?boolean; + +getNumber?: (arg?: ?number) => ?number; + +getString?: (arg?: ?string) => ?string; + +getArray?: (arg?: ?Array) => ?Array; + +getObject?: (arg?: ?Object) => ?Object; + +getObjectShape?: (arg?: {|prop?: ?number|}) => {|prop?: ?number|}; + +getAlias?: (arg?: ?Animal) => ?Animal; + +getRootTag?: (arg?: ?RootTag) => ?RootTag; + +getValue?: (x?: ?number, y?: ?string, z?: ?Object) => ?Object; + +getValueWithCallback?: (callback?: ?(value?: ?string) => void) => void; + +getValueWithPromise?: (error?: ?boolean) => ?Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleNullableAndOptional', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js new file mode 100644 index 00000000000000..9f12225a2d883b --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = {| + name?: string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants?: () => {| + const1?: boolean, + const2?: number, + const3?: string, + |}; + +voidFunc?: () => void; + +getBool?: (arg?: boolean) => boolean; + +getNumber?: (arg?: number) => number; + +getString?: (arg?: string) => string; + +getArray?: (arg?: Array) => Array; + +getObject?: (arg?: Object) => Object; + +getObjectShape?: (arg?: {|prop?: number|}) => {|prop?: number|}; + +getAlias?: (arg?: Animal) => Animal; + +getRootTag?: (arg?: RootTag) => RootTag; + +getValue?: (x?: number, y?: string, z?: Object) => Object; + +getValueWithCallback?: (callback?: (value?: string) => void) => void; + +getValueWithPromise?: (error?: boolean) => Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleOptional', +): Spec); diff --git a/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js b/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js new file mode 100644 index 00000000000000..039c05323bdd08 --- /dev/null +++ b/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails oncall+react_native + * @flow strict-local + * @format + */ + +'use strict'; + +const parser = require('../../../src/parsers/flow'); +const generator = require('../../../src/generators/modules/GenerateModuleObjCpp'); +const fs = require('fs'); + +import type {SchemaType} from '../../../src/CodegenSchema'; + +const FIXTURE_DIR = `${__dirname}/../../__test_fixtures__/modules`; + +function getModules(): SchemaType { + const filenames: Array = fs.readdirSync(FIXTURE_DIR); + return filenames.reduce( + (accumulator, file) => { + const schema = parser.parseFile(`${FIXTURE_DIR}/${file}`); + return { + modules: { + ...accumulator.modules, + ...schema.modules, + }, + }; + }, + {modules: {}}, + ); +} + +describe('GenerateModuleObjCpp', () => { + it('can generate a header file NativeModule specs', () => { + const libName = 'RNCodegenModuleFixtures'; + const output = generator.generate(libName, getModules()); + expect(output.get(libName + '.h')).toMatchSnapshot(); + }); + + it('can generate an implementation file NativeModule specs', () => { + const libName = 'RNCodegenModuleFixtures'; + const output = generator.generate(libName, getModules()); + expect(output.get(libName + '-generated.mm')).toMatchSnapshot(); + }); +}); diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap new file mode 100644 index 00000000000000..435e5d6471ec2a --- /dev/null +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap @@ -0,0 +1,2021 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GenerateModuleObjCpp can generate a header file NativeModule specs 1`] = ` +"/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +@protocol NativeArrayTurboModuleSpec + +- (NSArray *)getArray:(NSArray *)a; +- (NSArray *)getReadOnlyArray:(NSArray *)a; +- (NSArray *)getArrayWithAlias:(NSArray *)a + b:(NSArray *)b; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeArrayTurboModule' + */ + class JSI_EXPORT NativeArrayTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeArrayTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativeBooleanTurboModuleSpec + +- (NSNumber *)getBoolean:(BOOL)arg; +- (NSNumber *)getBooleanWithAlias:(BOOL)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeBooleanTurboModule' + */ + class JSI_EXPORT NativeBooleanTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeBooleanTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativeCallbackTurboModuleSpec + +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithCallbackWithAlias:(RCTResponseSenderBlock)c; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeCallbackTurboModule' + */ + class JSI_EXPORT NativeCallbackTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeCallbackTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativeNullableTurboModuleSpec + +- (NSNumber * _Nullable)getBool:(NSNumber *)a; +- (NSNumber * _Nullable)getNumber:(NSNumber *)a; +- (NSString * _Nullable)getString:(NSNumber *)a; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)a; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)a; +- (void)getValueWithPromise:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeNullableTurboModule' + */ + class JSI_EXPORT NativeNullableTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeNullableTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativeNumberTurboModuleSpec + +- (NSNumber *)getNumber:(double)arg; +- (NSNumber *)getNumberWithAlias:(double)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeNumberTurboModule' + */ + class JSI_EXPORT NativeNumberTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeNumberTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeObjectTurboModule { + struct SpecDifficultObjectAE { + bool D() const; + double E() const; + NSString *F() const; + + SpecDifficultObjectAE(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectAE:(id)json; +@end +namespace JS { + namespace NativeObjectTurboModule { + struct SpecDifficultObjectA { + bool D() const; + JS::NativeObjectTurboModule::SpecDifficultObjectAE E() const; + NSString *F() const; + + SpecDifficultObjectA(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectA) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectA:(id)json; +@end +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsEEE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEEE */ + Builder(ConstantsEEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsEE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEE */ + Builder(ConstantsEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsE */ + Builder(ConstantsE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeObjectTurboModule { + struct Constants { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeObjectTurboModuleSpec + +- (NSDictionary *)getGenericObject:(NSDictionary *)arg; +- (NSDictionary *)getGenericObjectReadOnly:(NSDictionary *)arg; +- (NSDictionary *)getGenericObjectWithAlias:(NSDictionary *)arg; +- (NSDictionary *)difficultObject:(JS::NativeObjectTurboModule::SpecDifficultObjectA &)A; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeObjectTurboModule' + */ + class JSI_EXPORT NativeObjectTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsEEE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEEE */ + Builder(ConstantsEEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsEE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEE */ + Builder(ConstantsEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsE */ + Builder(ConstantsE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct Constants { + + struct Builder { + struct Input { + folly::Optional D; + id _Nullable A; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeOptionalObjectTurboModuleSpec + +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeOptionalObjectTurboModule' + */ + class JSI_EXPORT NativeOptionalObjectTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeOptionalObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativePromiseTurboModuleSpec + +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)getValueWithPromiseWithAlias:(NSString *)arg + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativePromiseTurboModule' + */ + class JSI_EXPORT NativePromiseTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativePromiseTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeSampleTurboModule { + struct SpecGetObjectShapeArg { + double prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetObjectShapeArg:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModule { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_Animal:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModule { + struct Constants { + + struct Builder { + struct Input { + RCTRequired const1; + RCTRequired const2; + RCTRequired const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(BOOL)arg; +- (NSNumber *)getNumber:(double)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray> *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModule::SpecGetObjectShapeArg &)arg; +- (NSDictionary *)getAlias:(JS::NativeSampleTurboModule::Animal &)arg; +- (NSNumber *)getRootTag:(double)arg; +- (NSDictionary *)getValue:(double)x +getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuegetValuegetValuey + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeSampleTurboModuleArrays { + struct ConstantsIdElement { + + struct Builder { + struct Input { + RCTRequired prop; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsIdElement */ + Builder(ConstantsIdElement i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsIdElement fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsIdElement(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +namespace JS { + namespace NativeSampleTurboModuleArrays { + struct Constants { + + struct Builder { + struct Input { + RCTRequired> const1; + RCTRequired> const2; + RCTRequired> const3; + folly::Optional>> id_; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleArraysSpec + +- (void)voidFunc; +- (NSArray *)getBool:(NSArray *)id; +- (NSArray *)getNumber:(NSArray *)arg; +- (NSArray *)getString:(NSArray *)arg; +- (NSArray> *> *)getArray:(NSArray *)arg; +- (NSArray *)getObject:(NSArray *)arg; +- (NSArray *)getObjectShape:(NSArray *)arg; +- (NSArray *)getAlias:(NSArray *)arg; +- (NSArray *)getRootTag:(NSArray *)arg; +- (NSArray *)getValue:(NSArray *)x + y:(NSArray *)y + z:(NSArray *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSArray *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModuleArrays' + */ + class JSI_EXPORT NativeSampleTurboModuleArraysSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleArraysSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullable_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_Animal:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct Constants { + + struct Builder { + struct Input { + RCTRequired> const1; + RCTRequired> const2; + RCTRequired const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleNullableSpec + +- (void)voidFunc; +- (NSNumber * _Nullable)getBool:(NSNumber *)arg; +- (NSNumber * _Nullable)getNumber:(NSNumber *)arg; +- (NSString * _Nullable)getString:(NSString * _Nullable)arg; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)arg; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)arg; +- (NSDictionary * _Nullable)getObjectShape:(JS::NativeSampleTurboModuleNullable::SpecGetObjectShapeArg &)arg; +- (NSDictionary * _Nullable)getAlias:(JS::NativeSampleTurboModuleNullable::Animal &)arg; +- (NSNumber * _Nullable)getRootTag:(NSNumber *)arg; +- (NSDictionary * _Nullable)getValue:(NSNumber *)x + y:(NSString * _Nullable)y + z:(NSDictionary * _Nullable)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModuleNullable' + */ + class JSI_EXPORT NativeSampleTurboModuleNullableSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleNullableSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_Animal:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct Constants { + + struct Builder { + struct Input { + folly::Optional const1; + folly::Optional const2; + NSString *const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleNullableAndOptionalSpec + +- (void)voidFunc; +- (NSNumber * _Nullable)getBool:(NSNumber *)arg; +- (NSNumber * _Nullable)getNumber:(NSNumber *)arg; +- (NSString * _Nullable)getString:(NSString * _Nullable)arg; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)arg; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModuleNullableAndOptional::SpecGetObjectShapeArg &)arg; +- (NSDictionary * _Nullable)getAlias:(JS::NativeSampleTurboModuleNullableAndOptional::Animal &)arg; +- (NSNumber * _Nullable)getRootTag:(NSNumber *)arg; +- (NSDictionary * _Nullable)getValue:(NSNumber *)x + y:(NSString * _Nullable)y + z:(NSDictionary * _Nullable)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModuleNullableAndOptional' + */ + class JSI_EXPORT NativeSampleTurboModuleNullableAndOptionalSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleNullableAndOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_Animal:(id)json; +@end +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct Constants { + + struct Builder { + struct Input { + folly::Optional const1; + folly::Optional const2; + NSString *const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleOptionalSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(NSNumber *)arg; +- (NSNumber *)getNumber:(NSNumber *)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray> *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModuleOptional::SpecGetObjectShapeArg &)arg; +- (NSDictionary *)getAlias:(JS::NativeSampleTurboModuleOptional::Animal &)arg; +- (NSNumber *)getRootTag:(NSNumber *)arg; +- (NSDictionary *)getValue:(NSNumber *)x + y:(NSString *)y + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModuleOptional' + */ + class JSI_EXPORT NativeSampleTurboModuleOptionalSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + +@protocol NativeStringTurboModuleSpec + +- (NSString *)getString:(NSString *)arg; +- (NSString *)getStringWithAlias:(NSString *)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeStringTurboModule' + */ + class JSI_EXPORT NativeStringTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeStringTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + + + +inline bool JS::NativeObjectTurboModule::SpecDifficultObjectAE::D() const +{ + id const p = _v[@\\"D\\"]; + return RCTBridgingToBool(p); +} +inline double JS::NativeObjectTurboModule::SpecDifficultObjectAE::E() const +{ + id const p = _v[@\\"E\\"]; + return RCTBridgingToDouble(p); +} +inline NSString *JS::NativeObjectTurboModule::SpecDifficultObjectAE::F() const +{ + id const p = _v[@\\"F\\"]; + return RCTBridgingToString(p); +} +inline bool JS::NativeObjectTurboModule::SpecDifficultObjectA::D() const +{ + id const p = _v[@\\"D\\"]; + return RCTBridgingToBool(p); +} +inline JS::NativeObjectTurboModule::SpecDifficultObjectAE JS::NativeObjectTurboModule::SpecDifficultObjectA::E() const +{ + id const p = _v[@\\"E\\"]; + return JS::NativeObjectTurboModule::SpecDifficultObjectAE(p); +} +inline NSString *JS::NativeObjectTurboModule::SpecDifficultObjectA::F() const +{ + id const p = _v[@\\"F\\"]; + return RCTBridgingToString(p); +} +inline JS::NativeObjectTurboModule::ConstantsEEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = @(E); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsEEE::Builder::Builder(ConstantsEEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeObjectTurboModule::ConstantsEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsEE::Builder::Builder(ConstantsEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeObjectTurboModule::ConstantsE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsE::Builder::Builder(ConstantsE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeObjectTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? @((double)E.value()) : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEEE::Builder::Builder(ConstantsEEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEE::Builder::Builder(ConstantsEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsE::Builder::Builder(ConstantsE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeOptionalObjectTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto A = i.A; + d[@\\"A\\"] = A; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline double JS::NativeSampleTurboModule::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToDouble(p); +} +inline NSString *JS::NativeSampleTurboModule::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToString(p); +} +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = @(const1); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = @(const2); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeSampleTurboModuleArrays::ConstantsIdElement::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto prop = i.prop.get(); + d[@\\"prop\\"] = @(prop); + return d; +}) {} +inline JS::NativeSampleTurboModuleArrays::ConstantsIdElement::Builder::Builder(ConstantsIdElement i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline JS::NativeSampleTurboModuleArrays::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = RCTConvertVecToArray(const1, ^id(bool el_) { return @(el_); }); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = RCTConvertVecToArray(const2, ^id(double el_) { return @(el_); }); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = RCTConvertVecToArray(const3, ^id(NSString * el_) { return el_; }); + auto id_ = i.id_; + d[@\\"id\\"] = RCTConvertOptionalVecToArray(id_, ^id(folly::Optional el_) { return el_.hasValue() ? el_.value().buildUnsafeRawValue() : nil; }); + return d; +}) {} +inline JS::NativeSampleTurboModuleArrays::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline folly::Optional JS::NativeSampleTurboModuleNullable::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} +inline NSString *JS::NativeSampleTurboModuleNullable::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} +inline JS::NativeSampleTurboModuleNullable::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2.get(); + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleNullable::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline folly::Optional JS::NativeSampleTurboModuleNullableAndOptional::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} +inline NSString *JS::NativeSampleTurboModuleNullableAndOptional::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} +inline JS::NativeSampleTurboModuleNullableAndOptional::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1; + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2; + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3; + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleNullableAndOptional::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} +inline folly::Optional JS::NativeSampleTurboModuleOptional::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} +inline NSString *JS::NativeSampleTurboModuleOptional::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} +inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1; + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2; + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3; + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +" +`; + +exports[`GenerateModuleObjCpp can generate an implementation file NativeModule specs 1`] = ` +"/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#import \\"RNCodegenModuleFixtures.h\\" + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getReadOnlyArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getReadOnlyArray\\", @selector(getReadOnlyArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getArrayWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArrayWithAlias\\", @selector(getArrayWithAlias:b:), args, count); + } + + NativeArrayTurboModuleSpecJSI::NativeArrayTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeArrayTurboModuleSpecJSI_getArray}; + + + methodMap_[\\"getReadOnlyArray\\"] = MethodMetadata {1, __hostFunction_NativeArrayTurboModuleSpecJSI_getReadOnlyArray}; + + + methodMap_[\\"getArrayWithAlias\\"] = MethodMetadata {2, __hostFunction_NativeArrayTurboModuleSpecJSI_getArrayWithAlias}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeBooleanTurboModuleSpecJSI_getBoolean(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBoolean\\", @selector(getBoolean:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeBooleanTurboModuleSpecJSI_getBooleanWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBooleanWithAlias\\", @selector(getBooleanWithAlias:), args, count); + } + + NativeBooleanTurboModuleSpecJSI::NativeBooleanTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getBoolean\\"] = MethodMetadata {1, __hostFunction_NativeBooleanTurboModuleSpecJSI_getBoolean}; + + + methodMap_[\\"getBooleanWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeBooleanTurboModuleSpecJSI_getBooleanWithAlias}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallbackWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallbackWithAlias\\", @selector(getValueWithCallbackWithAlias:), args, count); + } + + NativeCallbackTurboModuleSpecJSI::NativeCallbackTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithCallbackWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallbackWithAlias}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:reject:), args, count); + } + + NativeNullableTurboModuleSpecJSI::NativeNullableTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getObject}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {0, __hostFunction_NativeNullableTurboModuleSpecJSI_getValueWithPromise}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeNumberTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeNumberTurboModuleSpecJSI_getNumberWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumberWithAlias\\", @selector(getNumberWithAlias:), args, count); + } + + NativeNumberTurboModuleSpecJSI::NativeNumberTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeNumberTurboModuleSpecJSI_getNumber}; + + + methodMap_[\\"getNumberWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeNumberTurboModuleSpecJSI_getNumberWithAlias}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectAE:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectA) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectA:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObject\\", @selector(getGenericObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectReadOnly(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObjectReadOnly\\", @selector(getGenericObjectReadOnly:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObjectWithAlias\\", @selector(getGenericObjectWithAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_difficultObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"difficultObject\\", @selector(difficultObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeObjectTurboModuleSpecJSI::NativeObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getGenericObject\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObject}; + + + methodMap_[\\"getGenericObjectReadOnly\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectReadOnly}; + + + methodMap_[\\"getGenericObjectWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectWithAlias}; + + + methodMap_[\\"difficultObject\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_difficultObject}; + setMethodArgConversionSelector(@\\"difficultObject\\", 0, @\\"JS_NativeObjectTurboModule_SpecDifficultObjectA:\\"); + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeObjectTurboModuleSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeOptionalObjectTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeOptionalObjectTurboModuleSpecJSI::NativeOptionalObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeOptionalObjectTurboModuleSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromiseWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromiseWithAlias\\", @selector(getValueWithPromiseWithAlias:resolve:reject:), args, count); + } + + NativePromiseTurboModuleSpecJSI::NativePromiseTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getValueWithPromiseWithAlias\\"] = MethodMetadata {1, __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromiseWithAlias}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeSampleTurboModule_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:getValuegetValuegetValuegetValuegetValuey:z:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetObjectShapeArg:\\"); + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModule_Animal:\\"); + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleArraysSpecJSI::NativeSampleTurboModuleArraysSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObject}; + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObjectShape}; + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getAlias}; + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeSampleTurboModuleNullable_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleNullableSpecJSI::NativeSampleTurboModuleNullableSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObject}; + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:\\"); + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleNullable_Animal:\\"); + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleNullableAndOptionalSpecJSI::NativeSampleTurboModuleNullableAndOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObject}; + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:\\"); + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleNullableAndOptional_Animal:\\"); + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeSampleTurboModuleOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleOptionalSpecJSI::NativeSampleTurboModuleOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObject}; + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:\\"); + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleOptional_Animal:\\"); + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getConstants}; + + } + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeStringTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeStringTurboModuleSpecJSI_getStringWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getStringWithAlias\\", @selector(getStringWithAlias:), args, count); + } + + NativeStringTurboModuleSpecJSI::NativeStringTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeStringTurboModuleSpecJSI_getString}; + + + methodMap_[\\"getStringWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeStringTurboModuleSpecJSI_getStringWithAlias}; + + } + } // namespace react +} // namespace facebook +" +`; diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index a68d170a740d1c..2ab4e05ad21a78 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,11 +1,12 @@ { "name": "react-native-codegen", - "version": "0.0.3", + "version": "0.0.6", "description": "⚛️ Code generation tools for React Native", "homepage": "https://github.com/facebook/react-native/tree/master/packages/react-native-codegen", "repository": { "type": "git", - "url": "git@github.com:facebook/react-native.git" + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/react-native-codegen" }, "scripts": { "build": "yarn clean && node scripts/build.js --verbose", @@ -18,11 +19,12 @@ ], "dependencies": { "flow-parser": "^0.121.0", - "jscodeshift": "^0.9.0", + "jscodeshift": "^0.11.0", "nullthrows": "^1.1.1" }, "devDependencies": { "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.0.0", @@ -32,6 +34,7 @@ "@babel/plugin-transform-flow-strip-types": "^7.0.0", "chalk": "^4.0.0", "glob": "^7.1.1", + "invariant": "^2.2.4", "micromatch": "^4.0.2", "mkdirp": "^0.5.1", "prettier": "1.19.1" diff --git a/packages/react-native-codegen/scripts/buck-oss/combine_js_to_schema.sh b/packages/react-native-codegen/scripts/buck-oss/combine_js_to_schema.sh new file mode 100755 index 00000000000000..85bfb85a981528 --- /dev/null +++ b/packages/react-native-codegen/scripts/buck-oss/combine_js_to_schema.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Note: To be invoked by Buck sh_binary() in OSS environment. +# DO NOT USE outside of Buck! + +set -e +set -u + +pushd "$BUCK_DEFAULT_RUNTIME_RESOURCES" >/dev/null +node "build/lib/cli/combine/combine-js-to-schema-cli.js" "$@" +popd >/dev/null diff --git a/packages/react-native-codegen/scripts/buck-oss/generate-all.sh b/packages/react-native-codegen/scripts/buck-oss/generate-all.sh new file mode 100755 index 00000000000000..a60d6f40fe86c2 --- /dev/null +++ b/packages/react-native-codegen/scripts/buck-oss/generate-all.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Note: To be invoked by Buck sh_binary() in OSS environment. +# DO NOT USE outside of Buck! + +set -e +set -u + +pushd "$BUCK_DEFAULT_RUNTIME_RESOURCES" >/dev/null +node "build/lib/cli/generators/generate-all.js" "$@" +popd >/dev/null diff --git a/packages/react-native-codegen/scripts/oss/build.sh b/packages/react-native-codegen/scripts/oss/build.sh new file mode 100755 index 00000000000000..b5913f9f1d6a1e --- /dev/null +++ b/packages/react-native-codegen/scripts/oss/build.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This script assumes yarn is already installed. + +THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd) + +set -e +set -u + +CODEGEN_DIR="$THIS_DIR/../.." + +rm -rf "${CODEGEN_DIR:?}/lib" "${CODEGEN_DIR:?}/node_modules" + +# Fallback to npm if yarn is not available +if [ -x "$(command -v yarn)" ]; then + YARN_OR_NPM=$(command -v yarn) +else + YARN_OR_NPM=$(command -v npm) +fi +YARN_BINARY="${YARN_BINARY:-$YARN_OR_NPM}" + +if [[ ${FBSOURCE_ENV:-0} -eq 1 ]]; then + # Custom FB-specific setup + pushd "$CODEGEN_DIR" >/dev/null + + "$YARN_BINARY" install 2> >(grep -v '^warning' 1>&2) + # Note: Within FBSOURCE_ENV, this has to explicitly run build. + "$YARN_BINARY" run build + + popd >/dev/null + +else + # Run yarn install in a separate tmp dir to avoid conflict with the rest of the repo. + # Note: OSS-only. + TMP_DIR=$(mktemp -d) + + # On Windows this script gets run by a seprate Git Bash instance, which cannot perform the copy + # due to file locks created by the host process. Need to exclude .lock files while copying. + # Using in-memory tar operation because piping `find` and `grep` doesn't preserve folder structure + # during recursive copying, and `rsync` is not installed by default in Git Bash. + # As an added benefit, blob copy is faster. + if [ "$OSTYPE" = "msys" ] || [ "$OSTYPE" = "cygwin" ]; then + tar cf - --exclude='*.lock' "$CODEGEN_DIR" | (cd "$TMP_DIR" && tar xvf - ); + else + cp -R "$CODEGEN_DIR/." "$TMP_DIR"; + fi + + pushd "$TMP_DIR" >/dev/null + + # Note: this automatically runs build as well. + "$YARN_BINARY" install 2> >(grep -v '^warning' 1>&2) + + popd >/dev/null + + mv "$TMP_DIR/lib" "$TMP_DIR/node_modules" "$CODEGEN_DIR" + rm -rf "$TMP_DIR" +fi diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index ffd3a1a4666173..241017d53c0309 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -12,358 +12,316 @@ export type PlatformType = 'iOS' | 'android'; -export type CommandsFunctionTypeAnnotation = $ReadOnly<{| - type: 'FunctionTypeAnnotation', - params: $ReadOnlyArray, -|}>; - -export type CommandsFunctionTypeParamAnnotation = $ReadOnly<{| - name: string, - typeAnnotation: CommandsTypeAnnotation, -|}>; - -export type CommandsTypeAnnotation = - | ReservedFunctionValueTypeAnnotation - | BooleanTypeAnnotation - | Int32TypeAnnotation - | DoubleTypeAnnotation - | FloatTypeAnnotation - | StringTypeAnnotation; - -type ReservedFunctionValueTypeAnnotation = $ReadOnly<{| - type: 'ReservedFunctionValueTypeAnnotation', - name: ReservedFunctionValueTypeName, -|}>; +export type SchemaType = $ReadOnly<{ + modules: $ReadOnly<{ + [hasteModuleName: string]: ComponentSchema | NativeModuleSchema, + }>, +}>; -export type DoubleTypeAnnotation = $ReadOnly<{| +/** + * Component Type Annotations + */ +export type DoubleTypeAnnotation = $ReadOnly<{ type: 'DoubleTypeAnnotation', -|}>; +}>; -export type FloatTypeAnnotation = $ReadOnly<{| +export type FloatTypeAnnotation = $ReadOnly<{ type: 'FloatTypeAnnotation', -|}>; +}>; -export type BooleanTypeAnnotation = $ReadOnly<{| +export type BooleanTypeAnnotation = $ReadOnly<{ type: 'BooleanTypeAnnotation', -|}>; +}>; -export type Int32TypeAnnotation = $ReadOnly<{| +export type Int32TypeAnnotation = $ReadOnly<{ type: 'Int32TypeAnnotation', -|}>; +}>; -export type StringTypeAnnotation = $ReadOnly<{| +export type StringTypeAnnotation = $ReadOnly<{ type: 'StringTypeAnnotation', -|}>; +}>; -export type EventObjectPropertyType = - | $ReadOnly<{| - type: 'BooleanTypeAnnotation', - name: string, - optional: boolean, - |}> - | $ReadOnly<{| - type: 'StringTypeAnnotation', - name: string, - optional: boolean, - |}> - | $ReadOnly<{| - type: 'DoubleTypeAnnotation', - name: string, - optional: boolean, - |}> - | $ReadOnly<{| - type: 'FloatTypeAnnotation', - name: string, - optional: boolean, - |}> - | $ReadOnly<{| - type: 'Int32TypeAnnotation', - name: string, - optional: boolean, - |}> - | $ReadOnly<{| - type: 'StringEnumTypeAnnotation', - name: string, - optional: boolean, - options: $ReadOnlyArray<{| - name: string, - |}>, - |}> - | $ReadOnly<{| - type: 'ObjectTypeAnnotation', - name: string, - optional: boolean, - properties: $ReadOnlyArray, - |}>; - -type PropTypeTypeAnnotation = - | $ReadOnly<{| +export type StringEnumTypeAnnotation = $ReadOnly<{ + type: 'StringEnumTypeAnnotation', + options: $ReadOnlyArray, +}>; + +export type VoidTypeAnnotation = $ReadOnly<{ + type: 'VoidTypeAnnotation', +}>; + +export type ObjectTypeAnnotation<+T> = $ReadOnly<{ + type: 'ObjectTypeAnnotation', + properties: $ReadOnlyArray>, +}>; + +type FunctionTypeAnnotation<+P, +R> = $ReadOnly<{ + type: 'FunctionTypeAnnotation', + params: $ReadOnlyArray>, + returnTypeAnnotation: R, +}>; + +export type NamedShape<+T> = $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: T, +}>; + +export type ComponentSchema = $ReadOnly<{ + type: 'Component', + components: $ReadOnly<{ + [componentName: string]: ComponentShape, + }>, +}>; + +export type ComponentShape = $ReadOnly<{ + ...OptionsShape, + extendsProps: $ReadOnlyArray, + events: $ReadOnlyArray, + props: $ReadOnlyArray>, + commands: $ReadOnlyArray>, +}>; + +export type OptionsShape = $ReadOnly<{ + interfaceOnly?: boolean, + + // Use for components with no current paper rename in progress + // Does not check for new name + paperComponentName?: string, + + // Use for components that are not used on other platforms. + excludedPlatforms?: $ReadOnlyArray, + + // Use for components currently being renamed in paper + // Will use new name if it is available and fallback to this name + paperComponentNameDeprecated?: string, +}>; + +export type ExtendsPropsShape = $ReadOnly<{ + type: 'ReactNativeBuiltInType', + knownTypeName: 'ReactNativeCoreViewProps', +}>; + +export type EventTypeShape = $ReadOnly<{ + name: string, + bubblingType: 'direct' | 'bubble', + optional: boolean, + paperTopLevelNameDeprecated?: string, + typeAnnotation: $ReadOnly<{ + type: 'EventTypeAnnotation', + argument?: ObjectTypeAnnotation, + }>, +}>; + +export type EventTypeAnnotation = + | BooleanTypeAnnotation + | StringTypeAnnotation + | DoubleTypeAnnotation + | FloatTypeAnnotation + | Int32TypeAnnotation + | StringEnumTypeAnnotation + | ObjectTypeAnnotation; + +export type PropTypeAnnotation = + | $ReadOnly<{ type: 'BooleanTypeAnnotation', default: boolean | null, - |}> - | $ReadOnly<{| + }> + | $ReadOnly<{ type: 'StringTypeAnnotation', default: string | null, - |}> - | $ReadOnly<{| + }> + | $ReadOnly<{ type: 'DoubleTypeAnnotation', default: number, - |}> - | $ReadOnly<{| + }> + | $ReadOnly<{ type: 'FloatTypeAnnotation', default: number | null, - |}> - | $ReadOnly<{| + }> + | $ReadOnly<{ type: 'Int32TypeAnnotation', default: number, - |}> - | $ReadOnly<{| + }> + | $ReadOnly<{ type: 'StringEnumTypeAnnotation', default: string, - options: $ReadOnlyArray<{| - name: string, - |}>, - |}> - | $ReadOnly<{| + options: $ReadOnlyArray, + }> + | $ReadOnly<{ type: 'Int32EnumTypeAnnotation', default: number, - options: $ReadOnlyArray<{| - value: number, - |}>, - |}> - | $ReadOnly<{| - type: 'ReservedPropTypeAnnotation', - name: - | 'ColorPrimitive' - | 'ImageSourcePrimitive' - | 'PointPrimitive' - | 'EdgeInsetsPrimitive', - |}> - | $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}> - | $ReadOnly<{| + options: $ReadOnlyArray, + }> + | ReservedPropTypeAnnotation + | ObjectTypeAnnotation + | $ReadOnly<{ type: 'ArrayTypeAnnotation', elementType: - | $ReadOnly<{| - type: 'BooleanTypeAnnotation', - |}> - | $ReadOnly<{| - type: 'StringTypeAnnotation', - |}> - | $ReadOnly<{| - type: 'DoubleTypeAnnotation', - |}> - | $ReadOnly<{| - type: 'FloatTypeAnnotation', - |}> - | $ReadOnly<{| - type: 'Int32TypeAnnotation', - |}> - | $ReadOnly<{| + | BooleanTypeAnnotation + | StringTypeAnnotation + | DoubleTypeAnnotation + | FloatTypeAnnotation + | Int32TypeAnnotation + | $ReadOnly<{ type: 'StringEnumTypeAnnotation', default: string, - options: $ReadOnlyArray<{| - name: string, - |}>, - |}> - | $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}> - | $ReadOnly<{| - type: 'ReservedPropTypeAnnotation', - name: - | 'ColorPrimitive' - | 'ImageSourcePrimitive' - | 'PointPrimitive' - | 'EdgeInsetsPrimitive', - |}> - | $ReadOnly<{| + options: $ReadOnlyArray, + }> + | ObjectTypeAnnotation + | ReservedPropTypeAnnotation + | $ReadOnly<{ type: 'ArrayTypeAnnotation', - elementType: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - |}>; - -export type PropTypeShape = $ReadOnly<{| - name: string, - optional: boolean, - typeAnnotation: PropTypeTypeAnnotation, -|}>; - -export type EventTypeShape = $ReadOnly<{| - name: string, - bubblingType: 'direct' | 'bubble', - optional: boolean, - paperTopLevelNameDeprecated?: string, - typeAnnotation: $ReadOnly<{| - type: 'EventTypeAnnotation', - argument?: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, -|}>; - -export type CommandTypeShape = $ReadOnly<{| - name: string, - optional: boolean, - typeAnnotation: CommandsFunctionTypeAnnotation, -|}>; - -export type OptionsShape = $ReadOnly<{| - interfaceOnly?: boolean, + elementType: ObjectTypeAnnotation, + }>, + }>; + +export type ReservedPropTypeAnnotation = $ReadOnly<{ + type: 'ReservedPropTypeAnnotation', + name: + | 'ColorPrimitive' + | 'ImageSourcePrimitive' + | 'PointPrimitive' + | 'EdgeInsetsPrimitive', +}>; + +export type CommandTypeAnnotation = FunctionTypeAnnotation< + CommandParamTypeAnnotation, + VoidTypeAnnotation, +>; + +export type CommandParamTypeAnnotation = + | ReservedTypeAnnotation + | BooleanTypeAnnotation + | Int32TypeAnnotation + | DoubleTypeAnnotation + | FloatTypeAnnotation + | StringTypeAnnotation; - // Use for components with no current paper rename in progress - // Does not check for new name - paperComponentName?: string, +export type ReservedTypeAnnotation = $ReadOnly<{ + type: 'ReservedTypeAnnotation', + name: 'RootTag', // Union with more custom types. +}>; - // Use for components that are not used on other platforms. +/** + * NativeModule Types + */ +export type Nullable<+T: NativeModuleTypeAnnotation> = + | NullableTypeAnnotation + | T; + +export type NullableTypeAnnotation<+T: NativeModuleTypeAnnotation> = $ReadOnly<{ + type: 'NullableTypeAnnotation', + typeAnnotation: T, +}>; + +export type NativeModuleSchema = $ReadOnly<{ + type: 'NativeModule', + aliases: NativeModuleAliasMap, + spec: NativeModuleSpec, + moduleNames: $ReadOnlyArray, + // Use for modules that are not used on other platforms. + // TODO: It's clearer to define `restrictedToPlatforms` instead, but + // `excludedPlatforms` is used here to be consistent with ComponentSchema. excludedPlatforms?: $ReadOnlyArray, +}>; + +type NativeModuleSpec = $ReadOnly<{ + properties: $ReadOnlyArray, +}>; + +export type NativeModulePropertyShape = NamedShape< + Nullable, +>; + +export type NativeModuleAliasMap = $ReadOnly<{ + [aliasName: string]: NativeModuleObjectTypeAnnotation, +}>; + +export type NativeModuleFunctionTypeAnnotation = FunctionTypeAnnotation< + Nullable, + Nullable, +>; + +export type NativeModuleObjectTypeAnnotation = ObjectTypeAnnotation< + Nullable, +>; + +export type NativeModuleArrayTypeAnnotation< + +T: Nullable, +> = $ReadOnly<{ + type: 'ArrayTypeAnnotation', + /** + * TODO(T72031674): Migrate all our NativeModule specs to not use + * invalid Array ElementTypes. Then, make the elementType required. + */ + elementType?: T, +}>; + +export type NativeModuleStringTypeAnnotation = $ReadOnly<{ + type: 'StringTypeAnnotation', +}>; - // Use for components currently being renamed in paper - // Will use new name if it is available and fallback to this name - paperComponentNameDeprecated?: string, -|}>; - -export type ExtendsPropsShape = $ReadOnly<{| - type: 'ReactNativeBuiltInType', - knownTypeName: 'ReactNativeCoreViewProps', -|}>; +export type NativeModuleNumberTypeAnnotation = $ReadOnly<{ + type: 'NumberTypeAnnotation', +}>; -export type ComponentShape = $ReadOnly<{| - ...OptionsShape, - extendsProps: $ReadOnlyArray, - events: $ReadOnlyArray, - props: $ReadOnlyArray, - commands: $ReadOnlyArray, -|}>; +export type NativeModuleInt32TypeAnnotation = $ReadOnly<{ + type: 'Int32TypeAnnotation', +}>; -export type SchemaType = $ReadOnly<{| - modules: $ReadOnly<{ - [module: string]: $ReadOnly<{| - components?: $ReadOnly<{[component: string]: ComponentShape, ...}>, - nativeModules?: $ReadOnly<{ - [nativeModule: string]: NativeModuleShape, - ..., - }>, - |}>, - ..., - }>, -|}>; +export type NativeModuleDoubleTypeAnnotation = $ReadOnly<{ + type: 'DoubleTypeAnnotation', +}>; -/** - * NativeModule Types - */ -export type NativeModuleShape = $ReadOnly<{| - // We only support aliases to Objects - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, - properties: $ReadOnlyArray, -|}>; +export type NativeModuleFloatTypeAnnotation = $ReadOnly<{ + type: 'FloatTypeAnnotation', +}>; -export type ObjectTypeAliasTypeShape = $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, -|}>; +export type NativeModuleBooleanTypeAnnotation = $ReadOnly<{ + type: 'BooleanTypeAnnotation', +}>; -export type NativeModuleMethodTypeShape = $ReadOnly<{| - name: string, - typeAnnotation: FunctionTypeAnnotation, -|}>; +export type NativeModuleGenericObjectTypeAnnotation = $ReadOnly<{ + type: 'GenericObjectTypeAnnotation', +}>; -export type FunctionTypeAnnotation = $ReadOnly<{| - type: 'FunctionTypeAnnotation', - params: $ReadOnlyArray, - returnTypeAnnotation: FunctionTypeAnnotationReturn, - optional: boolean, -|}>; - -export type FunctionTypeAnnotationReturn = - | $ReadOnly<{| - nullable: boolean, - type: - | 'GenericPromiseTypeAnnotation' - | 'VoidTypeAnnotation' - | PrimitiveTypeAnnotationType, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ReservedFunctionValueTypeAnnotation', - name: ReservedFunctionValueTypeName, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ArrayTypeAnnotation', - elementType: ?FunctionTypeAnnotationReturnArrayElementType, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ObjectTypeAnnotation', - properties: ?$ReadOnlyArray, - |}>; - -export type FunctionTypeAnnotationReturnArrayElementType = - | FunctionTypeAnnotationParamTypeAnnotation // TODO: What does FunctionTypeAnnotationParamTypeAnnotation have to do with function returns? - | TypeAliasTypeAnnotation; - -export type TypeAliasTypeAnnotation = $ReadOnly<{| +export type NativeModuleTypeAliasTypeAnnotation = $ReadOnly<{ type: 'TypeAliasTypeAnnotation', name: string, -|}>; - -export type FunctionTypeAnnotationParam = $ReadOnly<{| - nullable: boolean, - name: string, - typeAnnotation: - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation, -|}>; - -export type FunctionTypeAnnotationParamTypeAnnotation = - | $ReadOnly<{| - type: - | 'AnyTypeAnnotation' - | 'FunctionTypeAnnotation' - | PrimitiveTypeAnnotationType, - |}> - | $ReadOnly<{| - type: 'ReservedFunctionValueTypeAnnotation', - name: ReservedFunctionValueTypeName, - |}> - | $ReadOnly<{| - type: 'ArrayTypeAnnotation', - elementType: - | ?FunctionTypeAnnotationParamTypeAnnotation - | ?TypeAliasTypeAnnotation, - |}> - | $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: ?$ReadOnlyArray, - |}>; - -export type PrimitiveTypeAnnotationType = - | 'StringTypeAnnotation' - | 'NumberTypeAnnotation' - | 'Int32TypeAnnotation' - | 'DoubleTypeAnnotation' - | 'FloatTypeAnnotation' - | 'BooleanTypeAnnotation' - | 'GenericObjectTypeAnnotation'; - -export type PrimitiveTypeAnnotation = $ReadOnly<{| - type: PrimitiveTypeAnnotationType, -|}>; - -export type ReservedFunctionValueTypeName = 'RootTag'; // Union with more custom types. - -export type ObjectParamTypeAnnotation = $ReadOnly<{| - optional: boolean, - name: string, - typeAnnotation?: - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation, // TODO (T67898313): Workaround for NativeLinking's use of union type, typeAnnotations should not be optional -|}>; +}>; + +export type NativeModulePromiseTypeAnnotation = $ReadOnly<{ + type: 'PromiseTypeAnnotation', +}>; + +export type NativeModuleBaseTypeAnnotation = + | NativeModuleStringTypeAnnotation + | NativeModuleNumberTypeAnnotation + | NativeModuleInt32TypeAnnotation + | NativeModuleDoubleTypeAnnotation + | NativeModuleFloatTypeAnnotation + | NativeModuleBooleanTypeAnnotation + | NativeModuleGenericObjectTypeAnnotation + | ReservedTypeAnnotation + | NativeModuleTypeAliasTypeAnnotation + | NativeModuleArrayTypeAnnotation> + | NativeModuleObjectTypeAnnotation; + +export type NativeModuleParamTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleParamOnlyTypeAnnotation; + +export type NativeModuleReturnTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleReturnOnlyTypeAnnotation; + +export type NativeModuleTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleParamOnlyTypeAnnotation + | NativeModuleReturnOnlyTypeAnnotation; + +type NativeModuleParamOnlyTypeAnnotation = NativeModuleFunctionTypeAnnotation; +type NativeModuleReturnOnlyTypeAnnotation = + | NativeModulePromiseTypeAnnotation + | VoidTypeAnnotation; diff --git a/packages/react-native-codegen/src/__tests__/SchemaValidator-test.js b/packages/react-native-codegen/src/__tests__/SchemaValidator-test.js index d2c65b18a937aa..76781b67e9ab8d 100644 --- a/packages/react-native-codegen/src/__tests__/SchemaValidator-test.js +++ b/packages/react-native-codegen/src/__tests__/SchemaValidator-test.js @@ -30,6 +30,7 @@ describe('SchemaValidator', () => { const fixture: SchemaType = { modules: { Module1: { + type: 'Component', components: { Component1: { extendsProps: [ @@ -45,6 +46,7 @@ describe('SchemaValidator', () => { }, }, Module2: { + type: 'Component', components: { Component1: { extendsProps: [ diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js index f9a0a07d8c90af..64449287296335 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js @@ -19,6 +19,19 @@ const path = require('path'); const [outfile, ...fileList] = process.argv.slice(2); +function filterJSFile(file) { + return ( + /^(Native.+|.+NativeComponent)/.test(path.basename(file)) && + // NativeUIManager will be deprecated by Fabric UIManager. + // For now, ignore this spec completely because the types are not fully supported. + !file.endsWith('NativeUIManager.js') && + // NativeSampleTurboModule is for demo purpose. It should be added manually to the + // app for now. + !file.endsWith('NativeSampleTurboModule.js') && + !file.includes('__tests') + ); +} + const allFiles = []; fileList.forEach(file => { if (fs.lstatSync(file).isDirectory()) { @@ -26,16 +39,9 @@ fileList.forEach(file => { .sync(`${file}/**/*.js`, { nodir: true, }) - .filter( - f => - /^(Native.+|.+NativeComponent)/.test(path.basename(f)) && - // NativeUIManager will be deprecated by Fabric UIManager. - // For now, ignore this spec completely because the types are not fully supported. - !f.endsWith('NativeUIManager.js') && - !f.includes('__tests'), - ); + .filter(filterJSFile); allFiles.push(...dirFiles); - } else { + } else if (filterJSFile(file)) { allFiles.push(file); } }); diff --git a/packages/react-native-codegen/buck_tests/generate-tests.js b/packages/react-native-codegen/src/cli/generators/generate-all.js similarity index 76% rename from packages/react-native-codegen/buck_tests/generate-tests.js rename to packages/react-native-codegen/src/cli/generators/generate-all.js index 2681bddc64a92f..3aaca12c7a28ad 100644 --- a/packages/react-native-codegen/buck_tests/generate-tests.js +++ b/packages/react-native-codegen/src/cli/generators/generate-all.js @@ -8,14 +8,18 @@ * @format */ +/** + * This generates all possible outputs by executing all available generators. + */ + 'use strict'; -const RNCodegen = require('../src/generators/RNCodegen.js'); +const RNCodegen = require('../../generators/RNCodegen.js'); const fs = require('fs'); const mkdirp = require('mkdirp'); const args = process.argv.slice(2); -if (args.length !== 4) { +if (args.length < 3) { throw new Error( `Expected to receive path to schema, library name, output directory and module spec name. Received ${args.join( ', ', @@ -26,7 +30,7 @@ if (args.length !== 4) { const schemaPath = args[0]; const libraryName = args[1]; const outputDirectory = args[2]; -const moduleSpecName = args[3]; +const packageName = args[3]; const schemaText = fs.readFileSync(schemaPath, 'utf-8'); @@ -44,7 +48,7 @@ try { } RNCodegen.generate( - {libraryName, schema, outputDirectory, moduleSpecName}, + {libraryName, schema, outputDirectory, packageName}, { generators: [ 'descriptors', @@ -52,7 +56,9 @@ RNCodegen.generate( 'props', 'tests', 'shadow-nodes', - 'modules', + 'modulesAndroid', + 'modulesCxx', + 'modulesIOS', ], }, ); diff --git a/packages/react-native-codegen/buck_tests/generate-tests.sh b/packages/react-native-codegen/src/cli/generators/generate-all.sh similarity index 77% rename from packages/react-native-codegen/buck_tests/generate-tests.sh rename to packages/react-native-codegen/src/cli/generators/generate-all.sh index 5a45850d25ef3a..c17f3a36bbfe0a 100755 --- a/packages/react-native-codegen/buck_tests/generate-tests.sh +++ b/packages/react-native-codegen/src/cli/generators/generate-all.sh @@ -10,10 +10,10 @@ set -u THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd) # shellcheck source=xplat/js/env-utils/setup_env_vars.sh -source "$THIS_DIR/../../../../env-utils/setup_env_vars.sh" +source "$THIS_DIR/../../../../../../env-utils/setup_env_vars.sh" pushd "$JS_DIR" >/dev/null "$INSTALL_NODE_MODULES" popd >/dev/null -exec "$FLOW_NODE_BINARY" "$THIS_DIR/generate-tests.js" "$@" +exec "$FLOW_NODE_BINARY" "$THIS_DIR/generate-all.js" "$@" diff --git a/packages/react-native-codegen/src/cli/verify_all_modules_with_old_codegen.sh b/packages/react-native-codegen/src/cli/verify_all_modules_with_old_codegen.sh deleted file mode 100755 index a46079351aaf8c..00000000000000 --- a/packages/react-native-codegen/src/cli/verify_all_modules_with_old_codegen.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -set -e -set -u - -exec buck query "filter('generated_objcpp_modules_tests_', '//xplat/js/...')" | xargs buck build diff --git a/packages/react-native-codegen/src/cli/verify_with_old_codegen.js b/packages/react-native-codegen/src/cli/verify_with_old_codegen.js deleted file mode 100755 index 60192bfab7d852..00000000000000 --- a/packages/react-native-codegen/src/cli/verify_with_old_codegen.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -const fs = require('fs'); -const [first, second] = process.argv.slice(2); - -const contents1 = fs.readFileSync(first, 'utf8'); -const contents2 = fs.readFileSync(second, 'utf8'); - -function traverse(t) { - return t - .replace(/\).invoke/g, ')\n.invoke') // in old codegen it was in one line - .split('\n') - .map(l => l.trim()) // no whitespaces - .filter(Boolean) // no empty lines - .filter( - l => - !l.startsWith('namespace') && // no namespaces - !l.startsWith('}') && // after removing openign namespaces we need to remove all closings - !l.startsWith('/**') && // all comments - !l.startsWith('#') && // imports - !l.startsWith('//') && // comments - !l.startsWith('importing it, you must change') && // comment in old codegen - !l.startsWith('*'), //comments - ) - .map(l => l.replace(/ /g, '')) // remove rest whitespaces - .sort(); // sort alphabetically lines -} - -const t1 = traverse(contents1); -const t2 = traverse(contents2); - -if (t1.length !== t2.length) { - throw new Error('Old and new codegen produces output of different size'); -} else { - for (let i = 0; i < t1.length; i++) { - if (t1[i] !== t2[i]) { - throw new Error( - `Old and new codegen does not produce similar output! ${i} ${t1[i]} | ${t2[i]}`, - ); - } - } -} diff --git a/packages/react-native-codegen/src/cli/verify_with_old_codegen.sh b/packages/react-native-codegen/src/cli/verify_with_old_codegen.sh deleted file mode 100755 index 7399c20dcb6294..00000000000000 --- a/packages/react-native-codegen/src/cli/verify_with_old_codegen.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -set -e -set -u - -THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd) - -# shellcheck source=xplat/js/env-utils/setup_env_vars.sh -source "$THIS_DIR/../../../../../env-utils/setup_env_vars.sh" - -pushd "$JS_DIR" >/dev/null - "$INSTALL_NODE_MODULES" -popd >/dev/null - -exec "$FLOW_NODE_BINARY" "$THIS_DIR/verify_with_old_codegen.js" "$@" diff --git a/packages/react-native-codegen/src/generators/RNCodegen.js b/packages/react-native-codegen/src/generators/RNCodegen.js index 576d984abd8d71..34b2a390300bc5 100644 --- a/packages/react-native-codegen/src/generators/RNCodegen.js +++ b/packages/react-native-codegen/src/generators/RNCodegen.js @@ -25,11 +25,10 @@ const generatePropsCpp = require('./components/GeneratePropsCpp.js'); const generatePropsH = require('./components/GeneratePropsH.js'); const generateModuleH = require('./modules/GenerateModuleH.js'); const generateModuleCpp = require('./modules/GenerateModuleCpp.js'); -const generateModuleHObjCpp = require('./modules/GenerateModuleHObjCpp.js'); +const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp'); const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js'); const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js'); const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js'); -const generateModuleMm = require('./modules/GenerateModuleMm.js'); const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js'); const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js'); const generateTests = require('./components/GenerateTests.js'); @@ -41,25 +40,29 @@ const schemaValidator = require('../SchemaValidator.js'); import type {SchemaType} from '../CodegenSchema'; -type Options = $ReadOnly<{| +type Options = $ReadOnly<{ libraryName: string, schema: SchemaType, outputDirectory: string, - moduleSpecName: string, -|}>; + packageName?: string, // Some platforms have a notion of package, which should be configurable. +}>; type Generators = + | 'componentsAndroid' + | 'componentsIOS' | 'descriptors' | 'events' | 'props' | 'tests' | 'shadow-nodes' - | 'modules'; + | 'modulesAndroid' + | 'modulesCxx' + | 'modulesIOS'; -type Config = $ReadOnly<{| +type Config = $ReadOnly<{ generators: Array, test?: boolean, -|}>; +}>; const GENERATORS = { descriptors: [generateComponentDescriptorH.generate], @@ -71,18 +74,37 @@ const GENERATORS = { generatePropsJavaInterface.generate, generatePropsJavaDelegate.generate, ], - modules: [ - generateModuleCpp.generate, - generateModuleH.generate, - generateModuleHObjCpp.generate, - generateModuleMm.generate, + // TODO: Refactor this to consolidate various C++ output variation instead of forking per platform. + componentsAndroid: [ + // JNI/C++ files + generateComponentDescriptorH.generate, + generateEventEmitterCpp.generate, + generateEventEmitterH.generate, + generatePropsCpp.generate, + generatePropsH.generate, + generateShadowNodeCpp.generate, + generateShadowNodeH.generate, + // Java files + generatePropsJavaInterface.generate, + generatePropsJavaDelegate.generate, + ], + componentsIOS: [ + generateComponentDescriptorH.generate, + generateEventEmitterCpp.generate, + generateEventEmitterH.generate, + generateComponentHObjCpp.generate, + generatePropsCpp.generate, + generatePropsH.generate, + generateShadowNodeCpp.generate, + generateShadowNodeH.generate, ], - // TODO: Refactor this to consolidate various C++ output variation instead of forking Android. modulesAndroid: [ GenerateModuleJniCpp.generate, GenerateModuleJniH.generate, generateModuleJavaSpec.generate, ], + modulesCxx: [generateModuleCpp.generate, generateModuleH.generate], + modulesIOS: [generateModuleObjCpp.generate], tests: [generateTests.generate], 'shadow-nodes': [ generateShadowNodeCpp.generate, @@ -95,6 +117,10 @@ function writeMapToFiles(map: Map, outputDir: string) { map.forEach((contents: string, fileName: string) => { try { const location = path.join(outputDir, fileName); + const dirName = path.dirname(location); + if (!fs.existsSync(dirName)) { + fs.mkdirSync(dirName, {recursive: true}); + } fs.writeFileSync(location, contents); } catch (error) { success = false; @@ -126,7 +152,7 @@ function checkFilesForChanges( module.exports = { generate( - {libraryName, schema, outputDirectory, moduleSpecName}: Options, + {libraryName, schema, outputDirectory, packageName}: Options, {generators, test}: Config, ): boolean { schemaValidator.validate(schema); @@ -134,7 +160,7 @@ module.exports = { const generatedFiles = []; for (const name of generators) { for (const generator of GENERATORS[name]) { - generatedFiles.push(...generator(libraryName, schema, moduleSpecName)); + generatedFiles.push(...generator(libraryName, schema, packageName)); } } diff --git a/packages/react-native-codegen/src/generators/Utils.js b/packages/react-native-codegen/src/generators/Utils.js new file mode 100644 index 00000000000000..68c128360e15e7 --- /dev/null +++ b/packages/react-native-codegen/src/generators/Utils.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +function capitalize(string: string): string { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +module.exports = { + capitalize, +}; diff --git a/packages/react-native-codegen/src/generators/components/CppHelpers.js b/packages/react-native-codegen/src/generators/components/CppHelpers.js index f6e7077a416942..1f816df8fd793b 100644 --- a/packages/react-native-codegen/src/generators/components/CppHelpers.js +++ b/packages/react-native-codegen/src/generators/components/CppHelpers.js @@ -9,7 +9,7 @@ */ 'use strict'; -import type {PropTypeShape} from '../../CodegenSchema'; +import type {NamedShape, PropTypeAnnotation} from '../../CodegenSchema'; function upperCaseFirst(inString: string): string { if (inString.length === 0) { @@ -55,7 +55,9 @@ function getCppTypeForAnnotation( } } -function getImports(properties: $ReadOnlyArray): Set { +function getImports( + properties: $ReadOnlyArray>, +): Set { const imports: Set = new Set(); function addImportsForNativeName(name) { @@ -122,7 +124,7 @@ function getEnumMaskName(enumName: string): string { function convertDefaultTypeToString( componentName: string, - prop: PropTypeShape, + prop: NamedShape, ): string { const typeAnnotation = prop.typeAnnotation; switch (typeAnnotation.type) { diff --git a/packages/react-native-codegen/src/generators/components/GenerateComponentDescriptorH.js b/packages/react-native-codegen/src/generators/components/GenerateComponentDescriptorH.js index 93a94ca5a85bc0..2adf7ad393631d 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateComponentDescriptorH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateComponentDescriptorH.js @@ -47,13 +47,18 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'ComponentDescriptors.h'; const componentDescriptors = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js index 9d5a5011a17843..a2f42c8b3476f0 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateComponentHObjCpp.js @@ -11,10 +11,11 @@ 'use strict'; import type { - CommandTypeShape, + NamedShape, + CommandTypeAnnotation, ComponentShape, SchemaType, - CommandsFunctionTypeParamAnnotation, + CommandParamTypeAnnotation, } from '../../CodegenSchema'; type FilesOutput = Map; @@ -103,11 +104,13 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END `.trim(); -function getObjCParamType(param: CommandsFunctionTypeParamAnnotation): string { +type Param = NamedShape; + +function getObjCParamType(param: Param): string { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return 'double'; @@ -131,13 +134,11 @@ function getObjCParamType(param: CommandsFunctionTypeParamAnnotation): string { } } -function getObjCExpectedKindParamType( - param: CommandsFunctionTypeParamAnnotation, -): string { +function getObjCExpectedKindParamType(param: Param): string { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return '[NSNumber class]'; @@ -161,13 +162,11 @@ function getObjCExpectedKindParamType( } } -function getReadableExpectedKindParamType( - param: CommandsFunctionTypeParamAnnotation, -): string { +function getReadableExpectedKindParamType(param: Param): string { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return 'double'; @@ -192,13 +191,13 @@ function getReadableExpectedKindParamType( } function getObjCRightHandAssignmentParamType( - param: CommandsFunctionTypeParamAnnotation, + param: Param, index: number, ): string { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return `[(NSNumber *)arg${index} doubleValue]`; @@ -252,7 +251,7 @@ function generateProtocol( } function generateConvertAndValidateParam( - param: CommandsFunctionTypeParamAnnotation, + param: Param, index: number, componentName: string, ): string { @@ -273,7 +272,7 @@ function generateConvertAndValidateParam( } function generateCommandIfCase( - command: CommandTypeShape, + command: NamedShape, componentName: string, ) { const params = command.typeAnnotation.params; @@ -324,13 +323,18 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'RCTComponentViewHelpers.h'; const componentContent = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js index 6ae392d20af9ab..b4f32f428079c7 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterCpp.js @@ -14,7 +14,8 @@ const {generateEventStructName} = require('./CppHelpers.js'); import type { ComponentShape, - EventObjectPropertyType, + NamedShape, + EventTypeAnnotation, SchemaType, } from '../../CodegenSchema'; @@ -81,16 +82,37 @@ function generateEnumSetter(variableName, propertyName, propertyParts) { function generateSetters( parentPropertyName: string, - properties: $ReadOnlyArray, + properties: $ReadOnlyArray>, propertyParts: $ReadOnlyArray, ): string { const propSetters = properties .map(eventProperty => { - switch (eventProperty.type) { + const {typeAnnotation} = eventProperty; + switch (typeAnnotation.type) { case 'BooleanTypeAnnotation': + return generateSetter( + parentPropertyName, + eventProperty.name, + propertyParts, + ); case 'StringTypeAnnotation': + return generateSetter( + parentPropertyName, + eventProperty.name, + propertyParts, + ); case 'Int32TypeAnnotation': + return generateSetter( + parentPropertyName, + eventProperty.name, + propertyParts, + ); case 'DoubleTypeAnnotation': + return generateSetter( + parentPropertyName, + eventProperty.name, + propertyParts, + ); case 'FloatTypeAnnotation': return generateSetter( parentPropertyName, @@ -110,7 +132,7 @@ function generateSetters( auto ${propertyName} = jsi::Object(runtime); ${generateSetters( propertyName, - eventProperty.properties, + typeAnnotation.properties, propertyParts.concat([propertyName]), )} @@ -118,7 +140,7 @@ function generateSetters( } `.trim(); default: - (eventProperty: empty); + (typeAnnotation.type: empty); throw new Error('Received invalid event property type'); } }) @@ -167,11 +189,16 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const moduleComponents: ComponentCollection = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js index 7081a912e88ba0..812783b947d3b3 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js @@ -21,7 +21,8 @@ const { import type { ComponentShape, EventTypeShape, - EventObjectPropertyType, + NamedShape, + EventTypeAnnotation, SchemaType, } from '../../CodegenSchema'; @@ -99,10 +100,10 @@ function indent(nice: string, spaces: number) { function getNativeTypeFromAnnotation( componentName: string, - eventProperty: EventObjectPropertyType, + eventProperty: NamedShape, nameParts: $ReadOnlyArray, ): string { - const type = eventProperty.type; + const {type} = eventProperty.typeAnnotation; switch (type) { case 'BooleanTypeAnnotation': @@ -123,15 +124,13 @@ function getNativeTypeFromAnnotation( function generateEnum(structs, options, nameParts) { const structName = generateEventStructName(nameParts); const fields = options - .map((option, index) => `${toSafeCppString(option.name)}`) + .map((option, index) => `${toSafeCppString(option)}`) .join(',\n '); const toCases = options .map( option => - `case ${structName}::${toSafeCppString(option.name)}: return "${ - option.name - }";`, + `case ${structName}::${toSafeCppString(option)}: return "${option}";`, ) .join('\n' + ' '); @@ -148,7 +147,7 @@ function generateStruct( structs: StructsMap, componentName: string, nameParts: $ReadOnlyArray, - properties: $ReadOnlyArray, + properties: $ReadOnlyArray>, ): void { const structNameParts = nameParts; const structName = generateEventStructName(structNameParts); @@ -163,13 +162,17 @@ function generateStruct( }) .join('\n' + ' '); - properties.forEach((property: EventObjectPropertyType) => { - const name = property.name; - switch (property.type) { + properties.forEach(property => { + const {name, typeAnnotation} = property; + switch (typeAnnotation.type) { case 'BooleanTypeAnnotation': + return; case 'StringTypeAnnotation': + return; case 'Int32TypeAnnotation': + return; case 'DoubleTypeAnnotation': + return; case 'FloatTypeAnnotation': return; case 'ObjectTypeAnnotation': @@ -177,16 +180,16 @@ function generateStruct( structs, componentName, nameParts.concat([name]), - nullthrows(property.properties), + nullthrows(typeAnnotation.properties), ); return; case 'StringEnumTypeAnnotation': - generateEnum(structs, property.options, nameParts.concat([name])); + generateEnum(structs, typeAnnotation.options, nameParts.concat([name])); return; default: - (property: empty); + (typeAnnotation.type: empty); throw new Error( - `Received invalid event property type ${property.type}`, + `Received invalid event property type ${typeAnnotation.type}`, ); } }); @@ -235,11 +238,16 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const moduleComponents: ComponentCollection = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js b/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js index 0afb7d11613b9b..39fc1ffc60fbb7 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsCpp.js @@ -85,7 +85,7 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'Props.cpp'; const allImports: Set = new Set([ @@ -94,7 +94,12 @@ module.exports = { const componentProps = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js index 85020bac0cee57..d218d809bc5bac 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js @@ -23,7 +23,8 @@ const { import type { ExtendsPropsShape, - PropTypeShape, + NamedShape, + PropTypeAnnotation, SchemaType, } from '../../CodegenSchema'; @@ -289,9 +290,8 @@ function convertValueToEnumOption(value: string): string { function generateArrayEnumString( componentName: string, name: string, - enumOptions, + options: $ReadOnlyArray, ): string { - const options = enumOptions.map(option => option.name); const enumName = getEnumName(componentName, name); const values = options @@ -328,9 +328,7 @@ function generateArrayEnumString( function generateStringEnum(componentName, prop) { const typeAnnotation = prop.typeAnnotation; if (typeAnnotation.type === 'StringEnumTypeAnnotation') { - const values: $ReadOnlyArray = typeAnnotation.options.map( - option => option.name, - ); + const values: $ReadOnlyArray = typeAnnotation.options; const enumName = getEnumName(componentName, prop.name); const fromCases = values @@ -364,9 +362,7 @@ function generateStringEnum(componentName, prop) { function generateIntEnum(componentName, prop) { const typeAnnotation = prop.typeAnnotation; if (typeAnnotation.type === 'Int32EnumTypeAnnotation') { - const values: $ReadOnlyArray = typeAnnotation.options.map( - option => option.value, - ); + const values: $ReadOnlyArray = typeAnnotation.options; const enumName = getEnumName(componentName, prop.name); const fromCases = values @@ -447,7 +443,7 @@ function generateEnumString(componentName: string, component): string { function generatePropsString( componentName: string, - props: $ReadOnlyArray, + props: $ReadOnlyArray>, ) { return props .map(prop => { @@ -487,7 +483,7 @@ function getExtendsImports( } function getLocalImports( - properties: $ReadOnlyArray, + properties: $ReadOnlyArray>, ): Set { const imports: Set = new Set(); @@ -677,7 +673,7 @@ function generateStruct( structs: StructsMap, componentName: string, nameParts: $ReadOnlyArray, - properties: $ReadOnlyArray, + properties: $ReadOnlyArray>, ): void { const structNameParts = nameParts; const structName = generateStructName(componentName, structNameParts); @@ -692,7 +688,7 @@ function generateStruct( }) .join('\n' + ' '); - properties.forEach((property: PropTypeShape) => { + properties.forEach((property: NamedShape) => { const name = property.name; switch (property.typeAnnotation.type) { case 'BooleanTypeAnnotation': @@ -755,7 +751,7 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'Props.h'; @@ -763,7 +759,12 @@ module.exports = { const componentClasses = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js index dd0258a488ab7d..0e71cdbaa8673b 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaDelegate.js @@ -11,9 +11,10 @@ 'use strict'; import type { - CommandTypeShape, + NamedShape, + CommandTypeAnnotation, ComponentShape, - PropTypeShape, + PropTypeAnnotation, SchemaType, } from '../../CodegenSchema'; const { @@ -35,7 +36,7 @@ const template = `/** * ${'@'}generated by codegen project: GeneratePropsJavaDelegate.js */ -package com.facebook.react.viewmanagers; +package ::_PACKAGE_NAME_::; ::_IMPORTS_:: @@ -64,7 +65,7 @@ const commandsTemplate = ` `; function getJavaValueForProp( - prop: PropTypeShape, + prop: NamedShape, componentName: string, ): string { const typeAnnotation = prop.typeAnnotation; @@ -157,7 +158,7 @@ function getCommandArgJavaType(param, index) { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return `args.getDouble(${index})`; @@ -181,7 +182,9 @@ function getCommandArgJavaType(param, index) { } } -function getCommandArguments(command: CommandTypeShape): string { +function getCommandArguments( + command: NamedShape, +): string { return [ 'view', ...command.typeAnnotation.params.map(getCommandArgJavaType), @@ -242,7 +245,6 @@ function getDelegateImports(component) { imports.add('import androidx.annotation.Nullable;'); imports.add('import com.facebook.react.uimanager.BaseViewManagerDelegate;'); imports.add('import com.facebook.react.uimanager.BaseViewManagerInterface;'); - imports.add('import com.facebook.react.uimanager.LayoutShadowNode;'); return imports; } @@ -262,11 +264,20 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { + // TODO: This doesn't support custom package name yet. + const normalizedPackageName = 'com.facebook.react.viewmanagers'; + const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`; + const files = new Map(); Object.keys(schema.modules).forEach(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return; @@ -284,7 +295,6 @@ module.exports = { const component = components[componentName]; const className = getDelegateJavaClassName(componentName); const interfaceClassName = getInterfaceJavaClassName(componentName); - const fileName = `${className}.java`; const imports = getDelegateImports(component); const propsString = generatePropCasesString(component, componentName); @@ -301,6 +311,7 @@ module.exports = { .sort() .join('\n'), ) + .replace(/::_PACKAGE_NAME_::/g, normalizedPackageName) .replace(/::_CLASSNAME_::/g, className) .replace('::_EXTEND_CLASSES_::', extendString) .replace('::_PROP_CASES_::', propsString) @@ -310,7 +321,7 @@ module.exports = { ) .replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName); - files.set(fileName, replacedTemplate); + files.set(`${outputDir}/${className}.java`, replacedTemplate); }); }); diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js index af41763c82c0e5..77781ec192b22a 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaInterface.js @@ -11,9 +11,10 @@ 'use strict'; import type { - CommandTypeShape, + NamedShape, + CommandTypeAnnotation, ComponentShape, - PropTypeShape, + PropTypeAnnotation, SchemaType, } from '../../CodegenSchema'; const { @@ -34,7 +35,7 @@ const template = `/** * ${'@'}generated by codegen project: GeneratePropsJavaInterface.js */ -package com.facebook.react.viewmanagers; +package ::_PACKAGE_NAME_::; ::_IMPORTS_:: @@ -47,7 +48,10 @@ function addNullable(imports) { imports.add('import androidx.annotation.Nullable;'); } -function getJavaValueForProp(prop: PropTypeShape, imports): string { +function getJavaValueForProp( + prop: NamedShape, + imports, +): string { const typeAnnotation = prop.typeAnnotation; switch (typeAnnotation.type) { @@ -128,7 +132,7 @@ function getCommandArgJavaType(param) { const {typeAnnotation} = param; switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (typeAnnotation.name) { case 'RootTag': return 'double'; @@ -153,7 +157,7 @@ function getCommandArgJavaType(param) { } function getCommandArguments( - command: CommandTypeShape, + command: NamedShape, componentName: string, ): string { return [ @@ -208,11 +212,21 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { + // TODO: This doesn't support custom package name yet. + const normalizedPackageName = 'com.facebook.react.viewmanagers'; + const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`; + const files = new Map(); Object.keys(schema.modules).forEach(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; + // No components in this module if (components == null) { return; @@ -229,7 +243,6 @@ module.exports = { .forEach(componentName => { const component = components[componentName]; const className = getInterfaceJavaClassName(componentName); - const fileName = `${className}.java`; const imports = getImports(component, 'interface'); const propsString = generatePropsString(component, imports); @@ -246,6 +259,7 @@ module.exports = { .sort() .join('\n'), ) + .replace(/::_PACKAGE_NAME_::/g, normalizedPackageName) .replace(/::_CLASSNAME_::/g, className) .replace('::_EXTEND_CLASSES_::', extendString) .replace( @@ -254,7 +268,7 @@ module.exports = { ) .replace('::_COMMAND_HANDLERS_::', commandsString); - files.set(fileName, replacedTemplate); + files.set(`${outputDir}/${className}.java`, replacedTemplate); }); }); diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/PojoCollector.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/PojoCollector.js new file mode 100644 index 00000000000000..767b96157f3e85 --- /dev/null +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/PojoCollector.js @@ -0,0 +1,204 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type { + ReservedPropTypeAnnotation, + NamedShape, + ObjectTypeAnnotation, + BooleanTypeAnnotation, + StringTypeAnnotation, + DoubleTypeAnnotation, + FloatTypeAnnotation, + Int32TypeAnnotation, + PropTypeAnnotation, +} from '../../../CodegenSchema'; + +const {capitalize} = require('../../Utils'); + +export type Pojo = { + name: string, + namespace: string, + properties: $ReadOnlyArray, + isRoot: boolean, +}; + +export type PojoProperty = NamedShape; + +export type PojoTypeAliasAnnotation = { + type: 'PojoTypeAliasTypeAnnotation', + name: string, +}; + +export type PojoTypeAnnotation = + | $ReadOnly<{ + type: 'BooleanTypeAnnotation', + default: boolean | null, + }> + | $ReadOnly<{ + type: 'StringTypeAnnotation', + default: string | null, + }> + | $ReadOnly<{ + type: 'DoubleTypeAnnotation', + default: number, + }> + | $ReadOnly<{ + type: 'FloatTypeAnnotation', + default: number | null, + }> + | $ReadOnly<{ + type: 'Int32TypeAnnotation', + default: number, + }> + | $ReadOnly<{ + type: 'StringEnumTypeAnnotation', + default: string, + options: $ReadOnlyArray, + }> + | $ReadOnly<{ + type: 'Int32EnumTypeAnnotation', + default: number, + options: $ReadOnlyArray, + }> + | ReservedPropTypeAnnotation + | PojoTypeAliasAnnotation + | $ReadOnly<{ + type: 'ArrayTypeAnnotation', + elementType: + | BooleanTypeAnnotation + | StringTypeAnnotation + | DoubleTypeAnnotation + | FloatTypeAnnotation + | Int32TypeAnnotation + | $ReadOnly<{ + type: 'StringEnumTypeAnnotation', + default: string, + options: $ReadOnlyArray, + }> + | PojoTypeAliasAnnotation + | ReservedPropTypeAnnotation + | $ReadOnly<{ + type: 'ArrayTypeAnnotation', + elementType: PojoTypeAliasAnnotation, + }>, + }>; + +class PojoCollector { + _pojos: Map = new Map(); + _process( + namespace: string, + pojoName: string, + typeAnnotation: PropTypeAnnotation, + ): PojoTypeAnnotation { + switch (typeAnnotation.type) { + case 'ObjectTypeAnnotation': { + this._insertPojo(namespace, pojoName, typeAnnotation, false); + return { + type: 'PojoTypeAliasTypeAnnotation', + name: pojoName, + }; + } + case 'ArrayTypeAnnotation': { + const arrayTypeAnnotation = typeAnnotation; + // TODO: Flow assumes elementType can be any. Fix this. + const elementType: $PropertyType< + typeof arrayTypeAnnotation, + 'elementType', + > = arrayTypeAnnotation.elementType; + + const pojoElementType = (() => { + switch (elementType.type) { + case 'ObjectTypeAnnotation': { + this._insertPojo( + namespace, + `${pojoName}Element`, + elementType, + false, + ); + return { + type: 'PojoTypeAliasTypeAnnotation', + name: `${pojoName}Element`, + }; + } + case 'ArrayTypeAnnotation': { + const {elementType: objectTypeAnnotation} = elementType; + this._insertPojo( + namespace, + `${pojoName}ElementElement`, + objectTypeAnnotation, + false, + ); + return { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'PojoTypeAliasTypeAnnotation', + name: `${pojoName}ElementElement`, + }, + }; + } + default: { + return elementType; + } + } + })(); + + return { + type: 'ArrayTypeAnnotation', + elementType: pojoElementType, + }; + } + default: + return typeAnnotation; + } + } + + _insertPojo( + namespace: string, + pojoName: string, + objectTypeAnnotation: ObjectTypeAnnotation, + isRoot: boolean, + ) { + const properties = objectTypeAnnotation.properties.map(property => { + const propertyPojoName = pojoName + capitalize(property.name); + + return { + ...property, + typeAnnotation: this._process( + namespace, + propertyPojoName, + property.typeAnnotation, + ), + }; + }); + + this._pojos.set(pojoName, { + name: pojoName, + isRoot, + namespace, + properties, + }); + } + + processPojo( + namespace: string, + pojoName: string, + objectTypeAnnotation: ObjectTypeAnnotation, + ) { + this._insertPojo(namespace, pojoName, objectTypeAnnotation, true); + } + + getAllPojos(): $ReadOnlyArray { + return [...this._pojos.values()]; + } +} + +module.exports = PojoCollector; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/index.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/index.js new file mode 100644 index 00000000000000..f24a6bb827eb76 --- /dev/null +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/index.js @@ -0,0 +1,80 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {SchemaType} from '../../../CodegenSchema'; + +const PojoCollector = require('./PojoCollector'); +const {capitalize} = require('../../Utils'); +const {serializePojo} = require('./serializePojo'); + +type FilesOutput = Map; + +module.exports = { + generate( + libraryName: string, + schema: SchemaType, + packageName?: string, + ): FilesOutput { + const pojoCollector = new PojoCollector(); + const basePackageName = 'com.facebook.react.viewmanagers'; + + Object.keys(schema.modules).forEach(hasteModuleName => { + const module = schema.modules[hasteModuleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; + // No components in this module + if (components == null) { + return null; + } + + Object.keys(components) + .filter(componentName => { + const component = components[componentName]; + return !( + component.excludedPlatforms && + component.excludedPlatforms.includes('android') + ); + }) + .forEach(componentName => { + const component = components[componentName]; + if (component == null) { + return; + } + + const {props} = component; + + pojoCollector.processPojo( + capitalize(hasteModuleName), + `${capitalize(componentName)}Props`, + { + type: 'ObjectTypeAnnotation', + properties: props, + }, + ); + }); + }); + + const pojoDir = basePackageName.split('.').join('/'); + + return new Map( + pojoCollector.getAllPojos().map(pojo => { + return [ + `java/${pojoDir}/${pojo.namespace}/${pojo.name}.java`, + serializePojo(pojo, basePackageName), + ]; + }), + ); + }, +}; diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/serializePojo.js b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/serializePojo.js new file mode 100644 index 00000000000000..76fd0850d1593a --- /dev/null +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/serializePojo.js @@ -0,0 +1,283 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {Pojo, PojoProperty, PojoTypeAnnotation} from './PojoCollector'; +const {capitalize} = require('../../Utils'); + +type ImportCollector = ($import: string) => void; + +function toJavaType( + typeAnnotation: PojoTypeAnnotation, + addImport: ImportCollector, +): string { + const importNullable = () => addImport('androidx.annotation.Nullable'); + const importReadableMap = () => + addImport('com.facebook.react.bridge.ReadableMap'); + const importArrayList = () => addImport('java.util.ArrayList'); + switch (typeAnnotation.type) { + /** + * Primitives + */ + case 'BooleanTypeAnnotation': { + if (typeAnnotation.default === null) { + importNullable(); + return '@Nullable Boolean'; + } else { + return 'boolean'; + } + } + case 'StringTypeAnnotation': { + importNullable(); + return '@Nullable String'; + } + case 'DoubleTypeAnnotation': { + return 'double'; + } + case 'FloatTypeAnnotation': { + if (typeAnnotation.default === null) { + importNullable(); + return '@Nullable Float'; + } else { + return 'float'; + } + } + case 'Int32TypeAnnotation': { + return 'int'; + } + + /** + * Enums + */ + // TODO: Make StringEnumTypeAnnotation type-safe? + case 'StringEnumTypeAnnotation': + importNullable(); + return '@Nullable String'; + // TODO: Make Int32EnumTypeAnnotation type-safe? + case 'Int32EnumTypeAnnotation': + importNullable(); + return '@Nullable Integer'; + + /** + * Reserved types + */ + case 'ReservedPropTypeAnnotation': { + switch (typeAnnotation.name) { + case 'ColorPrimitive': + importNullable(); + return '@Nullable Integer'; + + // TODO: Make ImageSourcePrimitive type-safe + case 'ImageSourcePrimitive': + importNullable(); + importReadableMap(); + return '@Nullable ReadableMap'; + + // TODO: Make PointPrimitive type-safe + case 'PointPrimitive': + importNullable(); + importReadableMap(); + return '@Nullable ReadableMap'; + + // TODO: Make EdgeInsetsPrimitive type-safe + case 'EdgeInsetsPrimitive': + importNullable(); + importReadableMap(); + return '@Nullable ReadableMap'; + default: + (typeAnnotation.name: empty); + throw new Error( + `Received unknown ReservedPropTypeAnnotation ${typeAnnotation.name}`, + ); + } + } + + /** + * Other Pojo objects + */ + case 'PojoTypeAliasTypeAnnotation': { + return typeAnnotation.name; + } + + /** + * Arrays + */ + case 'ArrayTypeAnnotation': { + const {elementType} = typeAnnotation; + + const elementTypeString = (() => { + switch (elementType.type) { + /** + * Primitives + */ + case 'BooleanTypeAnnotation': { + return 'Boolean'; + } + case 'StringTypeAnnotation': { + return 'String'; + } + case 'DoubleTypeAnnotation': { + return 'Double'; + } + case 'FloatTypeAnnotation': { + return 'Float'; + } + case 'Int32TypeAnnotation': { + return 'Integer'; + } + + /** + * Enums + */ + // TODO: Make StringEnums type-safe in Pojos + case 'StringEnumTypeAnnotation': { + return 'String'; + } + + /** + * Other Pojo objects + */ + case 'PojoTypeAliasTypeAnnotation': { + return elementType.name; + } + + /** + * Reserved types + */ + case 'ReservedPropTypeAnnotation': { + switch (elementType.name) { + case 'ColorPrimitive': + return 'Integer'; + + // TODO: Make ImageSourcePrimitive type-safe + case 'ImageSourcePrimitive': + importReadableMap(); + return 'ReadableMap'; + + // TODO: Make PointPrimitive type-safe + case 'PointPrimitive': + importReadableMap(); + return 'ReadableMap'; + + // TODO: Make EdgeInsetsPrimitive type-safe + case 'EdgeInsetsPrimitive': + importReadableMap(); + return 'ReadableMap'; + default: + (elementType.name: empty); + throw new Error( + `Received unknown ReservedPropTypeAnnotation ${elementType.name}`, + ); + } + } + + // Arrays + case 'ArrayTypeAnnotation': { + const {elementType: pojoTypeAliasTypeAnnotation} = elementType; + + importArrayList(); + return `ArrayList<${pojoTypeAliasTypeAnnotation.name}>`; + } + default: { + (elementType.type: empty); + throw new Error( + `Unrecognized PojoTypeAnnotation Array element type annotation '${typeAnnotation.type}'`, + ); + } + } + })(); + + importArrayList(); + return `ArrayList<${elementTypeString}>`; + } + + default: { + (typeAnnotation.type: empty); + throw new Error( + `Unrecognized PojoTypeAnnotation '${typeAnnotation.type}'`, + ); + } + } +} + +function toJavaMemberName(property: PojoProperty): string { + return `m${capitalize(property.name)}`; +} + +function toJavaMemberDeclaration( + property: PojoProperty, + addImport: ImportCollector, +): string { + const type = toJavaType(property.typeAnnotation, addImport); + const memberName = toJavaMemberName(property); + return `private ${type} ${memberName};`; +} + +function toJavaGetter(property: PojoProperty, addImport: ImportCollector) { + const type = toJavaType(property.typeAnnotation, addImport); + const getterName = `get${capitalize(property.name)}`; + const memberName = toJavaMemberName(property); + return `public ${type} ${getterName}() { + return ${memberName}; +}`; +} + +function serializePojo(pojo: Pojo, basePackageName: string): string { + const importSet: Set = new Set(); + const addImport = ($import: string) => { + importSet.add($import); + }; + + if (pojo.isRoot) { + addImport('com.facebook.proguard.annotations.DoNotStrip'); + } + + const indent = ' '.repeat(2); + + const members = pojo.properties + .map(property => toJavaMemberDeclaration(property, addImport)) + .map(member => `${indent}${member}`) + .join('\n'); + + const getters = pojo.properties + .map(property => toJavaGetter(property, addImport)) + .map(getter => + getter + .split('\n') + .map(line => `${indent}${line}`) + .join('\n'), + ) + .join('\n'); + + const imports = [...importSet] + .map($import => `import ${$import};`) + .sort() + .join('\n'); + + return `/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* ${'@'}generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package ${basePackageName}.${pojo.namespace}; +${imports === '' ? '' : `\n${imports}\n`} +${pojo.isRoot ? '@DoNotStrip\n' : ''}public class ${pojo.name} { +${members} +${getters} +} +`; +} + +module.exports = {serializePojo}; diff --git a/packages/react-native-codegen/src/generators/components/GenerateShadowNodeCpp.js b/packages/react-native-codegen/src/generators/components/GenerateShadowNodeCpp.js index e499bdcea45e5e..f52444da89d64e 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateShadowNodeCpp.js +++ b/packages/react-native-codegen/src/generators/components/GenerateShadowNodeCpp.js @@ -44,13 +44,18 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'ShadowNodes.cpp'; const componentNames = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GenerateShadowNodeH.js b/packages/react-native-codegen/src/generators/components/GenerateShadowNodeH.js index f5c5a8cf7b5de5..b42da9bd557615 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateShadowNodeH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateShadowNodeH.js @@ -54,7 +54,7 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'ShadowNodes.h'; @@ -62,7 +62,12 @@ module.exports = { const moduleResults = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; // No components in this module if (components == null) { return null; diff --git a/packages/react-native-codegen/src/generators/components/GenerateTests.js b/packages/react-native-codegen/src/generators/components/GenerateTests.js index 5d7a5af846a56a..ef5c3a47dfc2af 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateTests.js +++ b/packages/react-native-codegen/src/generators/components/GenerateTests.js @@ -16,12 +16,12 @@ const {getImports, toSafeCppString} = require('./CppHelpers'); type FilesOutput = Map; type PropValueType = string | number | boolean; -type TestCase = $ReadOnly<{| +type TestCase = $ReadOnly<{ propName: string, propValue: ?PropValueType, testName?: string, raw?: boolean, -|}>; +}>; const fileTemplate = ` /** @@ -58,8 +58,8 @@ function getTestCasesForProp(propName, typeAnnotation) { typeAnnotation.options.forEach(option => cases.push({ propName, - testName: `${propName}_${toSafeCppString(option.name)}`, - propValue: option.name, + testName: `${propName}_${toSafeCppString(option)}`, + propValue: option, }), ); } else if (typeAnnotation.type === 'StringTypeAnnotation') { @@ -139,7 +139,7 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const fileName = 'Tests.cpp'; const allImports = new Set([ @@ -150,7 +150,12 @@ module.exports = { const componentTests = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; + } + + const {components} = module; if (components == null) { return null; } diff --git a/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js b/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js index e7c0946d253536..a95cce35fe0c90 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js +++ b/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js @@ -94,24 +94,18 @@ function getReactDiffProcessValue(typeAnnotation) { } const componentTemplate = ` -const ::_COMPONENT_NAME_::ViewConfig = VIEW_CONFIG; - let nativeComponentName = '::_COMPONENT_NAME_WITH_COMPAT_SUPPORT_::'; ::_DEPRECATION_CHECK_:: -registerGeneratedViewConfig(nativeComponentName, ::_COMPONENT_NAME_::ViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ::_COMPONENT_NAME_::ViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => VIEW_CONFIG); `.trim(); const deprecatedComponentTemplate = ` if (UIManager.getViewManagerConfig('::_COMPONENT_NAME_::')) { nativeComponentName = '::_COMPONENT_NAME_::'; -} else if (UIManager.getViewManagerConfig('::_COMPONENT_NAME_DEPRECATED_::')){ +} else if (UIManager.getViewManagerConfig('::_COMPONENT_NAME_DEPRECATED_::')) { nativeComponentName = '::_COMPONENT_NAME_DEPRECATED_::'; } else { - throw new Error('Failed to find native component for either "::_COMPONENT_NAME_::" or "::_COMPONENT_NAME_DEPRECATED_::"') + throw new Error('Failed to find native component for either "::_COMPONENT_NAME_::" or "::_COMPONENT_NAME_DEPRECATED_::"'); } `.trim(); @@ -183,7 +177,7 @@ function buildViewConfig( switch (extendProps.knownTypeName) { case 'ReactNativeCoreViewProps': imports.add( - "const registerGeneratedViewConfig = require('registerGeneratedViewConfig');", + "const NativeComponentRegistry = require('NativeComponentRegistry');", ); return; @@ -337,14 +331,15 @@ module.exports = { const moduleResults = Object.keys(schema.modules) .map(moduleName => { - const components = schema.modules[moduleName].components; - // No components in this module - if (components == null) { - return null; + const module = schema.modules[moduleName]; + if (module.type !== 'Component') { + return; } + const {components} = module; + return Object.keys(components) - .map(componentName => { + .map((componentName: string) => { const component = components[componentName]; const paperComponentName = component.paperComponentName diff --git a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js index 31689b483dcaed..69529644cc4298 100644 --- a/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/components/__test_fixtures__/fixtures.js @@ -15,6 +15,7 @@ import type {SchemaType} from '../../../CodegenSchema.js'; const NO_PROPS_NO_EVENTS: SchemaType = { modules: { NoPropsNoEvents: { + type: 'Component', components: { NoPropsNoEventsComponent: { extendsProps: [ @@ -35,6 +36,7 @@ const NO_PROPS_NO_EVENTS: SchemaType = { const INTERFACE_ONLY: SchemaType = { modules: { Switch: { + type: 'Component', components: { InterfaceOnlyComponent: { interfaceOnly: true, @@ -56,9 +58,11 @@ const INTERFACE_ONLY: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'BooleanTypeAnnotation', name: 'value', optional: false, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }, ], }, @@ -85,6 +89,7 @@ const INTERFACE_ONLY: SchemaType = { const EVENTS_WITH_PAPER_NAME: SchemaType = { modules: { Switch: { + type: 'Component', components: { InterfaceOnlyComponent: { interfaceOnly: true, @@ -107,9 +112,11 @@ const EVENTS_WITH_PAPER_NAME: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'BooleanTypeAnnotation', name: 'value', optional: false, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }, ], }, @@ -126,9 +133,11 @@ const EVENTS_WITH_PAPER_NAME: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'BooleanTypeAnnotation', name: 'value', optional: false, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }, ], }, @@ -146,6 +155,7 @@ const EVENTS_WITH_PAPER_NAME: SchemaType = { const BOOLEAN_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { BooleanPropNativeComponent: { extendsProps: [ @@ -175,6 +185,7 @@ const BOOLEAN_PROP: SchemaType = { const STRING_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { StringPropComponent: { extendsProps: [ @@ -212,6 +223,7 @@ const STRING_PROP: SchemaType = { const INTEGER_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { IntegerPropNativeComponent: { extendsProps: [ @@ -257,6 +269,7 @@ const INTEGER_PROPS: SchemaType = { const FLOAT_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { FloatPropNativeComponent: { extendsProps: [ @@ -326,6 +339,7 @@ const FLOAT_PROPS: SchemaType = { const DOUBLE_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { DoublePropNativeComponent: { extendsProps: [ @@ -395,6 +409,7 @@ const DOUBLE_PROPS: SchemaType = { const COLOR_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { ColorPropNativeComponent: { extendsProps: [ @@ -424,6 +439,7 @@ const COLOR_PROP: SchemaType = { const IMAGE_PROP: SchemaType = { modules: { Slider: { + type: 'Component', components: { ImagePropNativeComponent: { extendsProps: [ @@ -453,6 +469,7 @@ const IMAGE_PROP: SchemaType = { const POINT_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { PointPropNativeComponent: { extendsProps: [ @@ -482,6 +499,7 @@ const POINT_PROP: SchemaType = { const INSETS_PROP: SchemaType = { modules: { ScrollView: { + type: 'Component', components: { InsetsPropNativeComponent: { extendsProps: [ @@ -511,6 +529,7 @@ const INSETS_PROP: SchemaType = { const ARRAY_PROPS: SchemaType = { modules: { Slider: { + type: 'Component', components: { ArrayPropsNativeComponent: { extendsProps: [ @@ -602,14 +621,7 @@ const ARRAY_PROPS: SchemaType = { elementType: { type: 'StringEnumTypeAnnotation', default: 'small', - options: [ - { - name: 'small', - }, - { - name: 'large', - }, - ], + options: ['small', 'large'], }, }, }, @@ -702,6 +714,7 @@ const ARRAY_PROPS: SchemaType = { const ARRAY_PROPS_WITH_NESTED_OBJECT: SchemaType = { modules: { Slider: { + type: 'Component', components: { ArrayPropsNativeComponent: { extendsProps: [ @@ -768,6 +781,7 @@ const ARRAY_PROPS_WITH_NESTED_OBJECT: SchemaType = { const OBJECT_PROPS: SchemaType = { modules: { ObjectPropsNativeComponent: { + type: 'Component', components: { ObjectProps: { extendsProps: [ @@ -822,11 +836,7 @@ const OBJECT_PROPS: SchemaType = { typeAnnotation: { type: 'StringEnumTypeAnnotation', default: 'option1', - options: [ - { - name: 'option1', - }, - ], + options: ['option1'], }, }, { @@ -835,11 +845,7 @@ const OBJECT_PROPS: SchemaType = { typeAnnotation: { type: 'Int32EnumTypeAnnotation', default: 0, - options: [ - { - value: 0, - }, - ], + options: [0], }, }, { @@ -963,6 +969,7 @@ const OBJECT_PROPS: SchemaType = { const MULTI_NATIVE_PROP: SchemaType = { modules: { Slider: { + type: 'Component', components: { ImageColorPropNativeComponent: { extendsProps: [ @@ -1016,6 +1023,7 @@ const MULTI_NATIVE_PROP: SchemaType = { const STRING_ENUM_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { StringEnumPropsNativeComponent: { extendsProps: [ @@ -1032,17 +1040,7 @@ const STRING_ENUM_PROP: SchemaType = { typeAnnotation: { type: 'StringEnumTypeAnnotation', default: 'center', - options: [ - { - name: 'top', - }, - { - name: 'center', - }, - { - name: 'bottom-right', - }, - ], + options: ['top', 'center', 'bottom-right'], }, }, ], @@ -1056,6 +1054,7 @@ const STRING_ENUM_PROP: SchemaType = { const INT32_ENUM_PROP: SchemaType = { modules: { Switch: { + type: 'Component', components: { Int32EnumPropsNativeComponent: { extendsProps: [ @@ -1072,17 +1071,7 @@ const INT32_ENUM_PROP: SchemaType = { typeAnnotation: { type: 'Int32EnumTypeAnnotation', default: 0, - options: [ - { - value: 0, - }, - { - value: 1, - }, - { - value: 2, - }, - ], + options: [0, 1, 2], }, }, ], @@ -1096,6 +1085,7 @@ const INT32_ENUM_PROP: SchemaType = { const EVENT_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { EventsNativeComponent: { extendsProps: [ @@ -1115,24 +1105,32 @@ const EVENT_PROPS: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'BooleanTypeAnnotation', name: 'value', optional: false, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }, { - type: 'StringTypeAnnotation', name: 'source', optional: true, + typeAnnotation: { + type: 'StringTypeAnnotation', + }, }, { - type: 'Int32TypeAnnotation', name: 'progress', optional: true, + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, }, { - type: 'FloatTypeAnnotation', name: 'scale', optional: true, + typeAnnotation: { + type: 'FloatTypeAnnotation', + }, }, ], }, @@ -1148,9 +1146,11 @@ const EVENT_PROPS: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'BooleanTypeAnnotation', name: 'value', optional: false, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }, ], }, @@ -1166,17 +1166,12 @@ const EVENT_PROPS: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'StringEnumTypeAnnotation', name: 'orientation', optional: false, - options: [ - { - name: 'landscape', - }, - { - name: 'portrait', - }, - ], + typeAnnotation: { + type: 'StringEnumTypeAnnotation', + options: ['landscape', 'portrait'], + }, }, ], }, @@ -1211,6 +1206,7 @@ const EVENT_PROPS: SchemaType = { const EVENT_NESTED_OBJECT_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { EventsNestedObjectNativeComponent: { extendsProps: [ @@ -1230,33 +1226,43 @@ const EVENT_NESTED_OBJECT_PROPS: SchemaType = { type: 'ObjectTypeAnnotation', properties: [ { - type: 'ObjectTypeAnnotation', name: 'location', optional: false, - properties: [ - { - type: 'ObjectTypeAnnotation', - name: 'source', - optional: false, - properties: [ - { - type: 'StringTypeAnnotation', - name: 'url', - optional: false, + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + name: 'source', + optional: false, + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + name: 'url', + optional: false, + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + ], }, - ], - }, - { - type: 'Int32TypeAnnotation', - name: 'x', - optional: false, - }, - { - type: 'Int32TypeAnnotation', - name: 'y', - optional: false, - }, - ], + }, + { + name: 'x', + optional: false, + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, + }, + { + name: 'y', + optional: false, + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, + }, + ], + }, }, ], }, @@ -1283,6 +1289,7 @@ const EVENT_NESTED_OBJECT_PROPS: SchemaType = { const TWO_COMPONENTS_SAME_FILE: SchemaType = { modules: { MyComponents: { + type: 'Component', components: { MultiComponent1NativeComponent: { extendsProps: [ @@ -1333,6 +1340,7 @@ const TWO_COMPONENTS_SAME_FILE: SchemaType = { const TWO_COMPONENTS_DIFFERENT_FILES: SchemaType = { modules: { ComponentFile1: { + type: 'Component', components: { MultiFile1NativeComponent: { extendsProps: [ @@ -1358,6 +1366,7 @@ const TWO_COMPONENTS_DIFFERENT_FILES: SchemaType = { }, ComponentFile2: { + type: 'Component', components: { MultiFile2NativeComponent: { extendsProps: [ @@ -1387,6 +1396,7 @@ const TWO_COMPONENTS_DIFFERENT_FILES: SchemaType = { const COMMANDS: SchemaType = { modules: { Switch: { + type: 'Component', components: { CommandNativeComponent: { extendsProps: [ @@ -1404,6 +1414,9 @@ const COMMANDS: SchemaType = { typeAnnotation: { type: 'FunctionTypeAnnotation', params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, { @@ -1414,35 +1427,43 @@ const COMMANDS: SchemaType = { params: [ { name: 'x', + optional: false, typeAnnotation: { type: 'Int32TypeAnnotation', }, }, { name: 'y', + optional: false, typeAnnotation: { type: 'FloatTypeAnnotation', }, }, { name: 'z', + optional: false, typeAnnotation: { type: 'DoubleTypeAnnotation', }, }, { name: 'message', + optional: false, typeAnnotation: { type: 'StringTypeAnnotation', }, }, { name: 'animated', + optional: false, typeAnnotation: { type: 'BooleanTypeAnnotation', }, }, ], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, ], @@ -1455,6 +1476,7 @@ const COMMANDS: SchemaType = { const COMMANDS_AND_PROPS: SchemaType = { modules: { Switch: { + type: 'Component', components: { CommandNativeComponent: { extendsProps: [ @@ -1483,12 +1505,16 @@ const COMMANDS_AND_PROPS: SchemaType = { params: [ { name: 'rootTag', + optional: false, typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', + type: 'ReservedTypeAnnotation', name: 'RootTag', }, }, ], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, { @@ -1499,17 +1525,22 @@ const COMMANDS_AND_PROPS: SchemaType = { params: [ { name: 'x', + optional: false, typeAnnotation: { type: 'Int32TypeAnnotation', }, }, { name: 'y', + optional: false, typeAnnotation: { type: 'Int32TypeAnnotation', }, }, ], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, ], @@ -1522,6 +1553,7 @@ const COMMANDS_AND_PROPS: SchemaType = { const EXCLUDE_ANDROID: SchemaType = { modules: { ExcludedAndroid: { + type: 'Component', components: { ExcludedAndroidComponent: { excludedPlatforms: ['android'], @@ -1543,6 +1575,7 @@ const EXCLUDE_ANDROID: SchemaType = { const EXCLUDE_ANDROID_IOS: SchemaType = { modules: { ExcludedAndroidIos: { + type: 'Component', components: { ExcludedAndroidIosComponent: { excludedPlatforms: ['android', 'iOS'], diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentDescriptorH-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentDescriptorH-test.js index c73dd315c8bf95..02133c76f90539 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentDescriptorH-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentDescriptorH-test.js @@ -21,9 +21,7 @@ describe('GenerateComponentDescriptorH', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentHObjCpp-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentHObjCpp-test.js index 44528dbbb02a37..52b638973aae82 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentHObjCpp-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateComponentHObjCpp-test.js @@ -21,9 +21,7 @@ describe('GenerateComponentHObjCpp', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterCpp-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterCpp-test.js index 5a17690e597b8f..14ac106e959b4d 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterCpp-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterCpp-test.js @@ -21,9 +21,7 @@ describe('GenerateEventEmitterCpp', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterH-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterH-test.js index 3b1974f66539f1..2b6a26422aa306 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterH-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateEventEmitterH-test.js @@ -21,9 +21,7 @@ describe('GenerateEventEmitterH', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsCpp-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsCpp-test.js index 284c5457acadcb..f9b9332a1259ca 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsCpp-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsCpp-test.js @@ -21,9 +21,7 @@ describe('GeneratePropsCpp', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsH-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsH-test.js index 23f8769ebeb814..77305fc2c4a077 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsH-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsH-test.js @@ -21,9 +21,7 @@ describe('GeneratePropsH', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaDelegate-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaDelegate-test.js index b9c5724c914e6a..36f1f9e8a5ca1a 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaDelegate-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaDelegate-test.js @@ -21,9 +21,7 @@ describe('GeneratePropsJavaDelegate', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaInterface-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaInterface-test.js index a14ac875cc7b9a..cc1eadab41ab78 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaInterface-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaInterface-test.js @@ -21,9 +21,7 @@ describe('GeneratePropsJavaInterface', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaPojo-test.js similarity index 55% rename from packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js rename to packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaPojo-test.js index a66b5ff7e4c28c..80b2df4dd042b9 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaPojo-test.js @@ -11,21 +11,17 @@ 'use strict'; -const fixtures = require('../__test_fixtures__/structFixtures.js'); -const generator = require('../ObjCppUtils/GenerateStructs.js'); +const fixtures = require('../__test_fixtures__/fixtures.js'); +const generator = require('../GeneratePropsJavaPojo'); -describe('GenerateStructs', () => { +describe('GeneratePropsJavaPojo', () => { Object.keys(fixtures) .sort() .forEach(fixtureName => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator - .translateObjectsForStructs(fixture, fixtureName, {}) - .replace(/::_MODULE_NAME_::/g, 'SampleTurboModule'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateShadowNodeH-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateShadowNodeH-test.js index 3edd5e3695fdab..ea704d4773d614 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateShadowNodeH-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateShadowNodeH-test.js @@ -21,9 +21,7 @@ describe('GenerateShadowNodeH', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateTests-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateTests-test.js index 8b9f066b0c18b4..6961d0b1754ee1 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateTests-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateTests-test.js @@ -21,9 +21,7 @@ describe('GenerateTests', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { - expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), - ).toMatchSnapshot(); + expect(generator.generate(fixtureName, fixture)).toMatchSnapshot(); }); }); }); diff --git a/packages/react-native-codegen/src/generators/components/__tests__/GenerateViewConfigJs-test.js b/packages/react-native-codegen/src/generators/components/__tests__/GenerateViewConfigJs-test.js index 039398cb51dd61..dbb69c01457055 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/GenerateViewConfigJs-test.js +++ b/packages/react-native-codegen/src/generators/components/__tests__/GenerateViewConfigJs-test.js @@ -30,6 +30,7 @@ describe('GenerateViewConfigJs', () => { generator.generate('DEPRECATED_VIEW_CONFIG_NAME', { modules: { Component: { + type: 'Component', components: { NativeComponentName: { paperComponentNameDeprecated: 'DeprecatedNativeComponentName', diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap index fda2e0e535ed63..2b062c4f906bc0 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaDelegate-test.js.snap @@ -2,7 +2,7 @@ exports[`GeneratePropsJavaDelegate can generate fixture ARRAY_PROPS 1`] = ` Map { - "ArrayPropsNativeComponentManagerDelegate.java" => "/** + "java/com/facebook/react/viewmanagers/ArrayPropsNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -18,7 +18,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ArrayPropsNativeComponentManagerDelegate & ArrayPropsNativeComponentManagerInterface> extends BaseViewManagerDelegate { public ArrayPropsNativeComponentManagerDelegate(U viewManager) { @@ -71,7 +70,7 @@ public class ArrayPropsNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/ArrayPropsNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -87,7 +86,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ArrayPropsNativeComponentManagerDelegate & ArrayPropsNativeComponentManagerInterface> extends BaseViewManagerDelegate { public ArrayPropsNativeComponentManagerDelegate(U viewManager) { @@ -110,7 +108,7 @@ public class ArrayPropsNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/BooleanPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -125,7 +123,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class BooleanPropNativeComponentManagerDelegate & BooleanPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public BooleanPropNativeComponentManagerDelegate(U viewManager) { @@ -148,7 +145,7 @@ public class BooleanPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/ColorPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -164,7 +161,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ColorPropConverter; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ColorPropNativeComponentManagerDelegate & ColorPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public ColorPropNativeComponentManagerDelegate(U viewManager) { @@ -187,7 +183,7 @@ public class ColorPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/CommandNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -203,7 +199,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class CommandNativeComponentManagerDelegate & CommandNativeComponentManagerInterface> extends BaseViewManagerDelegate { public CommandNativeComponentManagerDelegate(U viewManager) { @@ -232,7 +227,7 @@ public class CommandNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/CommandNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -248,7 +243,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class CommandNativeComponentManagerDelegate & CommandNativeComponentManagerInterface> extends BaseViewManagerDelegate { public CommandNativeComponentManagerDelegate(U viewManager) { @@ -283,7 +277,7 @@ public class CommandNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/DoublePropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -298,7 +292,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class DoublePropNativeComponentManagerDelegate & DoublePropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public DoublePropNativeComponentManagerDelegate(U viewManager) { @@ -336,7 +329,7 @@ public class DoublePropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/EventsNestedObjectNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -351,7 +344,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class EventsNestedObjectNativeComponentManagerDelegate & EventsNestedObjectNativeComponentManagerInterface> extends BaseViewManagerDelegate { public EventsNestedObjectNativeComponentManagerDelegate(U viewManager) { @@ -374,7 +366,7 @@ public class EventsNestedObjectNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/EventsNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -389,7 +381,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class EventsNativeComponentManagerDelegate & EventsNativeComponentManagerInterface> extends BaseViewManagerDelegate { public EventsNativeComponentManagerDelegate(U viewManager) { @@ -412,7 +403,7 @@ public class EventsNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/InterfaceOnlyComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -427,7 +418,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class InterfaceOnlyComponentManagerDelegate & InterfaceOnlyComponentManagerInterface> extends BaseViewManagerDelegate { public InterfaceOnlyComponentManagerDelegate(U viewManager) { @@ -448,7 +438,7 @@ exports[`GeneratePropsJavaDelegate can generate fixture EXCLUDE_ANDROID_IOS 1`] exports[`GeneratePropsJavaDelegate can generate fixture FLOAT_PROPS 1`] = ` Map { - "FloatPropNativeComponentManagerDelegate.java" => "/** + "java/com/facebook/react/viewmanagers/FloatPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -463,7 +453,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class FloatPropNativeComponentManagerDelegate & FloatPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public FloatPropNativeComponentManagerDelegate(U viewManager) { @@ -501,7 +490,7 @@ public class FloatPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/ImagePropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -517,7 +506,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ImagePropNativeComponentManagerDelegate & ImagePropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public ImagePropNativeComponentManagerDelegate(U viewManager) { @@ -540,7 +528,7 @@ public class ImagePropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/InsetsPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -556,7 +544,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class InsetsPropNativeComponentManagerDelegate & InsetsPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public InsetsPropNativeComponentManagerDelegate(U viewManager) { @@ -579,7 +566,7 @@ public class InsetsPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/Int32EnumPropsNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -594,7 +581,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class Int32EnumPropsNativeComponentManagerDelegate & Int32EnumPropsNativeComponentManagerInterface> extends BaseViewManagerDelegate { public Int32EnumPropsNativeComponentManagerDelegate(U viewManager) { @@ -617,7 +603,7 @@ public class Int32EnumPropsNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/IntegerPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -632,7 +618,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class IntegerPropNativeComponentManagerDelegate & IntegerPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public IntegerPropNativeComponentManagerDelegate(U viewManager) { @@ -661,7 +646,7 @@ public class IntegerPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/InterfaceOnlyComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -676,7 +661,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class InterfaceOnlyComponentManagerDelegate & InterfaceOnlyComponentManagerInterface> extends BaseViewManagerDelegate { public InterfaceOnlyComponentManagerDelegate(U viewManager) { @@ -699,7 +683,7 @@ public class InterfaceOnlyComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/ImageColorPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -716,7 +700,6 @@ import com.facebook.react.bridge.ColorPropConverter; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ImageColorPropNativeComponentManagerDelegate & ImageColorPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public ImageColorPropNativeComponentManagerDelegate(U viewManager) { @@ -748,7 +731,7 @@ public class ImageColorPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/NoPropsNoEventsComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -763,7 +746,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class NoPropsNoEventsComponentManagerDelegate & NoPropsNoEventsComponentManagerInterface> extends BaseViewManagerDelegate { public NoPropsNoEventsComponentManagerDelegate(U viewManager) { @@ -780,7 +762,7 @@ public class NoPropsNoEventsComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/ObjectPropsManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -796,7 +778,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class ObjectPropsManagerDelegate & ObjectPropsManagerInterface> extends BaseViewManagerDelegate { public ObjectPropsManagerDelegate(U viewManager) { @@ -819,7 +800,7 @@ public class ObjectPropsManagerDelegate "/** + "java/com/facebook/react/viewmanagers/PointPropNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -835,7 +816,6 @@ import androidx.annotation.Nullable; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class PointPropNativeComponentManagerDelegate & PointPropNativeComponentManagerInterface> extends BaseViewManagerDelegate { public PointPropNativeComponentManagerDelegate(U viewManager) { @@ -858,7 +838,7 @@ public class PointPropNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/StringEnumPropsNativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -873,7 +853,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class StringEnumPropsNativeComponentManagerDelegate & StringEnumPropsNativeComponentManagerInterface> extends BaseViewManagerDelegate { public StringEnumPropsNativeComponentManagerDelegate(U viewManager) { @@ -896,7 +875,7 @@ public class StringEnumPropsNativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/StringPropComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -911,7 +890,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class StringPropComponentManagerDelegate & StringPropComponentManagerInterface> extends BaseViewManagerDelegate { public StringPropComponentManagerDelegate(U viewManager) { @@ -937,7 +915,7 @@ public class StringPropComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/MultiFile1NativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -952,7 +930,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class MultiFile1NativeComponentManagerDelegate & MultiFile1NativeComponentManagerInterface> extends BaseViewManagerDelegate { public MultiFile1NativeComponentManagerDelegate(U viewManager) { @@ -970,7 +947,7 @@ public class MultiFile1NativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/MultiFile2NativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -985,7 +962,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class MultiFile2NativeComponentManagerDelegate & MultiFile2NativeComponentManagerInterface> extends BaseViewManagerDelegate { public MultiFile2NativeComponentManagerDelegate(U viewManager) { @@ -1008,7 +984,7 @@ public class MultiFile2NativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/MultiComponent1NativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -1023,7 +999,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class MultiComponent1NativeComponentManagerDelegate & MultiComponent1NativeComponentManagerInterface> extends BaseViewManagerDelegate { public MultiComponent1NativeComponentManagerDelegate(U viewManager) { @@ -1041,7 +1016,7 @@ public class MultiComponent1NativeComponentManagerDelegate "/** + "java/com/facebook/react/viewmanagers/MultiComponent2NativeComponentManagerDelegate.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -1056,7 +1031,6 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; -import com.facebook.react.uimanager.LayoutShadowNode; public class MultiComponent2NativeComponentManagerDelegate & MultiComponent2NativeComponentManagerInterface> extends BaseViewManagerDelegate { public MultiComponent2NativeComponentManagerDelegate(U viewManager) { diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap index b064446f35b63a..2add98876ce447 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaInterface-test.js.snap @@ -2,7 +2,7 @@ exports[`GeneratePropsJavaInterface can generate fixture ARRAY_PROPS 1`] = ` Map { - "ArrayPropsNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ArrayPropsNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -36,7 +36,7 @@ public interface ArrayPropsNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture ARRAY_PROPS_WITH_NESTED_OBJECT 1`] = ` Map { - "ArrayPropsNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ArrayPropsNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -60,7 +60,7 @@ public interface ArrayPropsNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture BOOLEAN_PROP 1`] = ` Map { - "BooleanPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/BooleanPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -82,7 +82,7 @@ public interface BooleanPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture COLOR_PROP 1`] = ` Map { - "ColorPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ColorPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -105,7 +105,7 @@ public interface ColorPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture COMMANDS 1`] = ` Map { - "CommandNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/CommandNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -129,7 +129,7 @@ public interface CommandNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture COMMANDS_AND_PROPS 1`] = ` Map { - "CommandNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/CommandNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -154,7 +154,7 @@ public interface CommandNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture DOUBLE_PROPS 1`] = ` Map { - "DoublePropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/DoublePropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -181,7 +181,7 @@ public interface DoublePropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture EVENT_NESTED_OBJECT_PROPS 1`] = ` Map { - "EventsNestedObjectNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/EventsNestedObjectNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -203,7 +203,7 @@ public interface EventsNestedObjectNativeComponentManagerInterface "/** + "java/com/facebook/react/viewmanagers/EventsNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -225,7 +225,7 @@ public interface EventsNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture EVENTS_WITH_PAPER_NAME 1`] = ` Map { - "InterfaceOnlyComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/InterfaceOnlyComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -251,7 +251,7 @@ exports[`GeneratePropsJavaInterface can generate fixture EXCLUDE_ANDROID_IOS 1`] exports[`GeneratePropsJavaInterface can generate fixture FLOAT_PROPS 1`] = ` Map { - "FloatPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/FloatPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -278,7 +278,7 @@ public interface FloatPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture IMAGE_PROP 1`] = ` Map { - "ImagePropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ImagePropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -302,7 +302,7 @@ public interface ImagePropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture INSETS_PROP 1`] = ` Map { - "InsetsPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/InsetsPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -326,7 +326,7 @@ public interface InsetsPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture INT32_ENUM_PROP 1`] = ` Map { - "Int32EnumPropsNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/Int32EnumPropsNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -349,7 +349,7 @@ public interface Int32EnumPropsNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture INTEGER_PROPS 1`] = ` Map { - "IntegerPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/IntegerPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -373,7 +373,7 @@ public interface IntegerPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture INTERFACE_ONLY 1`] = ` Map { - "InterfaceOnlyComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/InterfaceOnlyComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -396,7 +396,7 @@ public interface InterfaceOnlyComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture MULTI_NATIVE_PROP 1`] = ` Map { - "ImageColorPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ImageColorPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -423,7 +423,7 @@ public interface ImageColorPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture NO_PROPS_NO_EVENTS 1`] = ` Map { - "NoPropsNoEventsComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/NoPropsNoEventsComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -445,7 +445,7 @@ public interface NoPropsNoEventsComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture OBJECT_PROPS 1`] = ` Map { - "ObjectPropsManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/ObjectPropsManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -469,7 +469,7 @@ public interface ObjectPropsManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture POINT_PROP 1`] = ` Map { - "PointPropNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/PointPropNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -493,7 +493,7 @@ public interface PointPropNativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture STRING_ENUM_PROP 1`] = ` Map { - "StringEnumPropsNativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/StringEnumPropsNativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -516,7 +516,7 @@ public interface StringEnumPropsNativeComponentManagerInterface exports[`GeneratePropsJavaInterface can generate fixture STRING_PROP 1`] = ` Map { - "StringPropComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/StringPropComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -540,7 +540,7 @@ public interface StringPropComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture TWO_COMPONENTS_DIFFERENT_FILES 1`] = ` Map { - "MultiFile1NativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/MultiFile1NativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -557,7 +557,7 @@ public interface MultiFile1NativeComponentManagerInterface { void setDisabled(T view, boolean value); } ", - "MultiFile2NativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/MultiFile2NativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -579,7 +579,7 @@ public interface MultiFile2NativeComponentManagerInterface { exports[`GeneratePropsJavaInterface can generate fixture TWO_COMPONENTS_SAME_FILE 1`] = ` Map { - "MultiComponent1NativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/MultiComponent1NativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -596,7 +596,7 @@ public interface MultiComponent1NativeComponentManagerInterface void setDisabled(T view, boolean value); } ", - "MultiComponent2NativeComponentManagerInterface.java" => "/** + "java/com/facebook/react/viewmanagers/MultiComponent2NativeComponentManagerInterface.java" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaPojo-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaPojo-test.js.snap new file mode 100644 index 00000000000000..2de4d2b94641be --- /dev/null +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaPojo-test.js.snap @@ -0,0 +1,1078 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GeneratePropsJavaPojo can generate fixture ARRAY_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentPropsObjectElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import androidx.annotation.Nullable; + +public class ArrayPropsNativeComponentPropsObjectElement { + private @Nullable String mStringProp; + public @Nullable String getStringProp() { + return mStringProp; + } +} +", + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentPropsArrayElementObjectElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import androidx.annotation.Nullable; + +public class ArrayPropsNativeComponentPropsArrayElementObjectElement { + private @Nullable String mStringProp; + public @Nullable String getStringProp() { + return mStringProp; + } +} +", + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentPropsArrayElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import java.util.ArrayList; + +public class ArrayPropsNativeComponentPropsArrayElement { + private ArrayList mObject; + public ArrayList getObject() { + return mObject; + } +} +", + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentPropsArrayOfArrayOfObjectElementElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import androidx.annotation.Nullable; + +public class ArrayPropsNativeComponentPropsArrayOfArrayOfObjectElementElement { + private @Nullable String mStringProp; + public @Nullable String getStringProp() { + return mStringProp; + } +} +", + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReadableMap; +import java.util.ArrayList; + +@DoNotStrip +public class ArrayPropsNativeComponentProps { + private ArrayList mNames; + private ArrayList mDisableds; + private ArrayList mProgress; + private ArrayList mRadii; + private ArrayList mColors; + private ArrayList mSrcs; + private ArrayList mPoints; + private ArrayList mSizes; + private ArrayList mObject; + private ArrayList mArray; + private ArrayList> mArrayOfArrayOfObject; + public ArrayList getNames() { + return mNames; + } + public ArrayList getDisableds() { + return mDisableds; + } + public ArrayList getProgress() { + return mProgress; + } + public ArrayList getRadii() { + return mRadii; + } + public ArrayList getColors() { + return mColors; + } + public ArrayList getSrcs() { + return mSrcs; + } + public ArrayList getPoints() { + return mPoints; + } + public ArrayList getSizes() { + return mSizes; + } + public ArrayList getObject() { + return mObject; + } + public ArrayList getArray() { + return mArray; + } + public ArrayList> getArrayOfArrayOfObject() { + return mArrayOfArrayOfObject; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture ARRAY_PROPS_WITH_NESTED_OBJECT 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentPropsNativePrimitivesElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import com.facebook.react.bridge.ReadableMap; +import java.util.ArrayList; + +public class ArrayPropsNativeComponentPropsNativePrimitivesElement { + private ArrayList mColors; + private ArrayList mSrcs; + private ArrayList mPoints; + public ArrayList getColors() { + return mColors; + } + public ArrayList getSrcs() { + return mSrcs; + } + public ArrayList getPoints() { + return mPoints; + } +} +", + "java/com/facebook/react/viewmanagers/Slider/ArrayPropsNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import com.facebook.proguard.annotations.DoNotStrip; +import java.util.ArrayList; + +@DoNotStrip +public class ArrayPropsNativeComponentProps { + private ArrayList mNativePrimitives; + public ArrayList getNativePrimitives() { + return mNativePrimitives; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture BOOLEAN_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/BooleanPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class BooleanPropNativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture COLOR_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/ColorPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class ColorPropNativeComponentProps { + private @Nullable Integer mTintColor; + public @Nullable Integer getTintColor() { + return mTintColor; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture COMMANDS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/CommandNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class CommandNativeComponentProps { + + +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture COMMANDS_AND_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/CommandNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class CommandNativeComponentProps { + private @Nullable String mAccessibilityHint; + public @Nullable String getAccessibilityHint() { + return mAccessibilityHint; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture DOUBLE_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/DoublePropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class DoublePropNativeComponentProps { + private double mBlurRadius; + private double mBlurRadius2; + private double mBlurRadius3; + private double mBlurRadius4; + private double mBlurRadius5; + private double mBlurRadius6; + public double getBlurRadius() { + return mBlurRadius; + } + public double getBlurRadius2() { + return mBlurRadius2; + } + public double getBlurRadius3() { + return mBlurRadius3; + } + public double getBlurRadius4() { + return mBlurRadius4; + } + public double getBlurRadius5() { + return mBlurRadius5; + } + public double getBlurRadius6() { + return mBlurRadius6; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture EVENT_NESTED_OBJECT_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/EventsNestedObjectNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class EventsNestedObjectNativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture EVENT_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/EventsNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class EventsNativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture EVENTS_WITH_PAPER_NAME 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/InterfaceOnlyComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class InterfaceOnlyComponentProps { + + +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture EXCLUDE_ANDROID 1`] = `Map {}`; + +exports[`GeneratePropsJavaPojo can generate fixture EXCLUDE_ANDROID_IOS 1`] = `Map {}`; + +exports[`GeneratePropsJavaPojo can generate fixture FLOAT_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/FloatPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class FloatPropNativeComponentProps { + private float mBlurRadius; + private float mBlurRadius2; + private float mBlurRadius3; + private float mBlurRadius4; + private float mBlurRadius5; + private float mBlurRadius6; + public float getBlurRadius() { + return mBlurRadius; + } + public float getBlurRadius2() { + return mBlurRadius2; + } + public float getBlurRadius3() { + return mBlurRadius3; + } + public float getBlurRadius4() { + return mBlurRadius4; + } + public float getBlurRadius5() { + return mBlurRadius5; + } + public float getBlurRadius6() { + return mBlurRadius6; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture IMAGE_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Slider/ImagePropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReadableMap; + +@DoNotStrip +public class ImagePropNativeComponentProps { + private @Nullable ReadableMap mThumbImage; + public @Nullable ReadableMap getThumbImage() { + return mThumbImage; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture INSETS_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/ScrollView/InsetsPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ScrollView; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReadableMap; + +@DoNotStrip +public class InsetsPropNativeComponentProps { + private @Nullable ReadableMap mContentInset; + public @Nullable ReadableMap getContentInset() { + return mContentInset; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture INT32_ENUM_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/Int32EnumPropsNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class Int32EnumPropsNativeComponentProps { + private @Nullable Integer mMaxInterval; + public @Nullable Integer getMaxInterval() { + return mMaxInterval; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture INTEGER_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/IntegerPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class IntegerPropNativeComponentProps { + private int mProgress1; + private int mProgress2; + private int mProgress3; + public int getProgress1() { + return mProgress1; + } + public int getProgress2() { + return mProgress2; + } + public int getProgress3() { + return mProgress3; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture INTERFACE_ONLY 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/InterfaceOnlyComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class InterfaceOnlyComponentProps { + private @Nullable String mAccessibilityHint; + public @Nullable String getAccessibilityHint() { + return mAccessibilityHint; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture MULTI_NATIVE_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Slider/ImageColorPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Slider; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReadableMap; + +@DoNotStrip +public class ImageColorPropNativeComponentProps { + private @Nullable ReadableMap mThumbImage; + private @Nullable Integer mColor; + private @Nullable Integer mThumbTintColor; + private @Nullable ReadableMap mPoint; + public @Nullable ReadableMap getThumbImage() { + return mThumbImage; + } + public @Nullable Integer getColor() { + return mColor; + } + public @Nullable Integer getThumbTintColor() { + return mThumbTintColor; + } + public @Nullable ReadableMap getPoint() { + return mPoint; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture NO_PROPS_NO_EVENTS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/NoPropsNoEvents/NoPropsNoEventsComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.NoPropsNoEvents; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class NoPropsNoEventsComponentProps { + + +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture OBJECT_PROPS 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropObjectArrayProp.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import java.util.ArrayList; + +public class ObjectPropsPropsObjectPropObjectArrayProp { + private ArrayList mArray; + public ArrayList getArray() { + return mArray; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropObjectPrimitiveRequiredProp.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableMap; + +public class ObjectPropsPropsObjectPropObjectPrimitiveRequiredProp { + private @Nullable ReadableMap mImage; + private @Nullable Integer mColor; + private @Nullable ReadableMap mPoint; + public @Nullable ReadableMap getImage() { + return mImage; + } + public @Nullable Integer getColor() { + return mColor; + } + public @Nullable ReadableMap getPoint() { + return mPoint; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropNestedPropANestedPropB.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import androidx.annotation.Nullable; + +public class ObjectPropsPropsObjectPropNestedPropANestedPropB { + private @Nullable String mNestedPropC; + public @Nullable String getNestedPropC() { + return mNestedPropC; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropNestedPropA.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +public class ObjectPropsPropsObjectPropNestedPropA { + private ObjectPropsPropsObjectPropNestedPropANestedPropB mNestedPropB; + public ObjectPropsPropsObjectPropNestedPropANestedPropB getNestedPropB() { + return mNestedPropB; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropNestedArrayAsPropertyArrayPropElement.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import androidx.annotation.Nullable; + +public class ObjectPropsPropsObjectPropNestedArrayAsPropertyArrayPropElement { + private @Nullable String mStringProp; + public @Nullable String getStringProp() { + return mStringProp; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectPropNestedArrayAsProperty.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import java.util.ArrayList; + +public class ObjectPropsPropsObjectPropNestedArrayAsProperty { + private ArrayList mArrayProp; + public ArrayList getArrayProp() { + return mArrayProp; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsPropsObjectProp.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import androidx.annotation.Nullable; + +public class ObjectPropsPropsObjectProp { + private @Nullable String mStringProp; + private boolean mBooleanProp; + private float mFloatProp; + private int mIntProp; + private @Nullable String mStringEnumProp; + private @Nullable Integer mIntEnumProp; + private ObjectPropsPropsObjectPropObjectArrayProp mObjectArrayProp; + private ObjectPropsPropsObjectPropObjectPrimitiveRequiredProp mObjectPrimitiveRequiredProp; + private ObjectPropsPropsObjectPropNestedPropA mNestedPropA; + private ObjectPropsPropsObjectPropNestedArrayAsProperty mNestedArrayAsProperty; + public @Nullable String getStringProp() { + return mStringProp; + } + public boolean getBooleanProp() { + return mBooleanProp; + } + public float getFloatProp() { + return mFloatProp; + } + public int getIntProp() { + return mIntProp; + } + public @Nullable String getStringEnumProp() { + return mStringEnumProp; + } + public @Nullable Integer getIntEnumProp() { + return mIntEnumProp; + } + public ObjectPropsPropsObjectPropObjectArrayProp getObjectArrayProp() { + return mObjectArrayProp; + } + public ObjectPropsPropsObjectPropObjectPrimitiveRequiredProp getObjectPrimitiveRequiredProp() { + return mObjectPrimitiveRequiredProp; + } + public ObjectPropsPropsObjectPropNestedPropA getNestedPropA() { + return mNestedPropA; + } + public ObjectPropsPropsObjectPropNestedArrayAsProperty getNestedArrayAsProperty() { + return mNestedArrayAsProperty; + } +} +", + "java/com/facebook/react/viewmanagers/ObjectPropsNativeComponent/ObjectPropsProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ObjectPropsNativeComponent; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class ObjectPropsProps { + private ObjectPropsPropsObjectProp mObjectProp; + public ObjectPropsPropsObjectProp getObjectProp() { + return mObjectProp; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture POINT_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/PointPropNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReadableMap; + +@DoNotStrip +public class PointPropNativeComponentProps { + private @Nullable ReadableMap mStartPoint; + public @Nullable ReadableMap getStartPoint() { + return mStartPoint; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture STRING_ENUM_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/StringEnumPropsNativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class StringEnumPropsNativeComponentProps { + private @Nullable String mAlignment; + public @Nullable String getAlignment() { + return mAlignment; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture STRING_PROP 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/Switch/StringPropComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.Switch; + +import androidx.annotation.Nullable; +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class StringPropComponentProps { + private @Nullable String mAccessibilityHint; + private @Nullable String mAccessibilityRole; + public @Nullable String getAccessibilityHint() { + return mAccessibilityHint; + } + public @Nullable String getAccessibilityRole() { + return mAccessibilityRole; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture TWO_COMPONENTS_DIFFERENT_FILES 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/ComponentFile1/MultiFile1NativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ComponentFile1; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class MultiFile1NativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", + "java/com/facebook/react/viewmanagers/ComponentFile2/MultiFile2NativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.ComponentFile2; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class MultiFile2NativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", +} +`; + +exports[`GeneratePropsJavaPojo can generate fixture TWO_COMPONENTS_SAME_FILE 1`] = ` +Map { + "java/com/facebook/react/viewmanagers/MyComponents/MultiComponent1NativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.MyComponents; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class MultiComponent1NativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", + "java/com/facebook/react/viewmanagers/MyComponents/MultiComponent2NativeComponentProps.java" => "/** +* Copyright (c) Facebook, Inc. and its affiliates. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +* +* @generated by codegen project: GeneratePropsJavaPojo.js +*/ + +package com.facebook.react.viewmanagers.MyComponents; + +import com.facebook.proguard.annotations.DoNotStrip; + +@DoNotStrip +public class MultiComponent2NativeComponentProps { + private boolean mDisabled; + public boolean getDisabled() { + return mDisabled; + } +} +", +} +`; diff --git a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap index 35c49ffe489873..099c42e270fb58 100644 --- a/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -16,9 +16,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const ArrayPropsNativeComponentViewConfig = { +let nativeComponentName = 'ArrayPropsNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ArrayPropsNativeComponent', validAttributes: { @@ -26,7 +28,11 @@ const ArrayPropsNativeComponentViewConfig = { disableds: true, progress: true, radii: true, - colors: { process: require('processColorArray') }, + + colors: { + process: require('processColorArray'), + }, + srcs: true, points: true, sizes: true, @@ -34,15 +40,7 @@ const ArrayPropsNativeComponentViewConfig = { array: true, arrayOfArrayOfObject: true, }, -}; - -let nativeComponentName = 'ArrayPropsNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, ArrayPropsNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ArrayPropsNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -63,23 +61,17 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const ArrayPropsNativeComponentViewConfig = { +let nativeComponentName = 'ArrayPropsNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ArrayPropsNativeComponent', validAttributes: { nativePrimitives: true, }, -}; - -let nativeComponentName = 'ArrayPropsNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, ArrayPropsNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ArrayPropsNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -100,23 +92,17 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const BooleanPropNativeComponentViewConfig = { +let nativeComponentName = 'BooleanPropNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'BooleanPropNativeComponent', validAttributes: { disabled: true, }, -}; - -let nativeComponentName = 'BooleanPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, BooleanPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = BooleanPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -137,23 +123,19 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const ColorPropNativeComponentViewConfig = { +let nativeComponentName = 'ColorPropNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ColorPropNativeComponent', validAttributes: { - tintColor: { process: require('processColor') }, + tintColor: { + process: require('processColor'), + }, }, -}; - -let nativeComponentName = 'ColorPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, ColorPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ColorPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -174,21 +156,15 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); -const CommandNativeComponentViewConfig = { - uiViewClassName: 'CommandNativeComponent', - validAttributes: {}, -}; - let nativeComponentName = 'CommandNativeComponent'; -registerGeneratedViewConfig(nativeComponentName, CommandNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = CommandNativeComponentViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ + uiViewClassName: 'CommandNativeComponent', + validAttributes: {}, +})); export const Commands = { flashScrollIndicators(ref) { @@ -219,24 +195,18 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); const {dispatchCommand} = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); -const CommandNativeComponentViewConfig = { +let nativeComponentName = 'CommandNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'CommandNativeComponent', validAttributes: { accessibilityHint: true, }, -}; - -let nativeComponentName = 'CommandNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, CommandNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = CommandNativeComponentViewConfig; - -export default nativeComponentName; +})); export const Commands = { handleRootTag(ref, rootTag) { @@ -267,9 +237,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const DoublePropNativeComponentViewConfig = { +let nativeComponentName = 'DoublePropNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'DoublePropNativeComponent', validAttributes: { @@ -280,15 +252,7 @@ const DoublePropNativeComponentViewConfig = { blurRadius5: true, blurRadius6: true, }, -}; - -let nativeComponentName = 'DoublePropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, DoublePropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = DoublePropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -309,9 +273,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const EventsNestedObjectNativeComponentViewConfig = { +let nativeComponentName = 'EventsNestedObjectNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'EventsNestedObjectNativeComponent', bubblingEventTypes: { @@ -327,15 +293,7 @@ const EventsNestedObjectNativeComponentViewConfig = { disabled: true, onChange: true, }, -}; - -let nativeComponentName = 'EventsNestedObjectNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, EventsNestedObjectNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = EventsNestedObjectNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -356,9 +314,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const EventsNativeComponentViewConfig = { +let nativeComponentName = 'EventsNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'EventsNativeComponent', bubblingEventTypes: { @@ -394,15 +354,7 @@ const EventsNativeComponentViewConfig = { onOrientationChange: true, onEnd: true, }, -}; - -let nativeComponentName = 'EventsNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, EventsNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = EventsNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -423,9 +375,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'RCTInterfaceOnlyComponent'; -const InterfaceOnlyComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'RCTInterfaceOnlyComponent', bubblingEventTypes: { @@ -458,15 +412,7 @@ const InterfaceOnlyComponentViewConfig = { onChange: true, onDire tChange: true, }, -}; - -let nativeComponentName = 'RCTInterfaceOnlyComponent'; - -registerGeneratedViewConfig(nativeComponentName, InterfaceOnlyComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = InterfaceOnlyComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -487,20 +433,14 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); - -const ExcludedAndroidComponentViewConfig = { - uiViewClassName: 'ExcludedAndroidComponent', - validAttributes: {}, -}; +const NativeComponentRegistry = require('NativeComponentRegistry'); let nativeComponentName = 'ExcludedAndroidComponent'; -registerGeneratedViewConfig(nativeComponentName, ExcludedAndroidComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ExcludedAndroidComponentViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ + uiViewClassName: 'ExcludedAndroidComponent', + validAttributes: {}, +})); ", } `; @@ -521,20 +461,14 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); - -const ExcludedAndroidIosComponentViewConfig = { - uiViewClassName: 'ExcludedAndroidIosComponent', - validAttributes: {}, -}; +const NativeComponentRegistry = require('NativeComponentRegistry'); let nativeComponentName = 'ExcludedAndroidIosComponent'; -registerGeneratedViewConfig(nativeComponentName, ExcludedAndroidIosComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ExcludedAndroidIosComponentViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ + uiViewClassName: 'ExcludedAndroidIosComponent', + validAttributes: {}, +})); ", } `; @@ -555,9 +489,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'FloatPropNativeComponent'; -const FloatPropNativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'FloatPropNativeComponent', validAttributes: { @@ -568,15 +504,7 @@ const FloatPropNativeComponentViewConfig = { blurRadius5: true, blurRadius6: true, }, -}; - -let nativeComponentName = 'FloatPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, FloatPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = FloatPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -597,23 +525,19 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const ImagePropNativeComponentViewConfig = { +let nativeComponentName = 'ImagePropNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ImagePropNativeComponent', validAttributes: { - thumbImage: { process: require('resolveAssetSource') }, + thumbImage: { + process: require('resolveAssetSource'), + }, }, -}; - -let nativeComponentName = 'ImagePropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, ImagePropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ImagePropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -634,23 +558,19 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'InsetsPropNativeComponent'; -const InsetsPropNativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'InsetsPropNativeComponent', validAttributes: { - contentInset: { diff: require('insetsDiffer') }, + contentInset: { + diff: require('insetsDiffer'), + }, }, -}; - -let nativeComponentName = 'InsetsPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, InsetsPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = InsetsPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -671,23 +591,17 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const Int32EnumPropsNativeComponentViewConfig = { +let nativeComponentName = 'Int32EnumPropsNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'Int32EnumPropsNativeComponent', validAttributes: { maxInterval: true, }, -}; - -let nativeComponentName = 'Int32EnumPropsNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, Int32EnumPropsNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = Int32EnumPropsNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -708,9 +622,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const IntegerPropNativeComponentViewConfig = { +let nativeComponentName = 'IntegerPropNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'IntegerPropNativeComponent', validAttributes: { @@ -718,15 +634,7 @@ const IntegerPropNativeComponentViewConfig = { progress2: true, progress3: true, }, -}; - -let nativeComponentName = 'IntegerPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, IntegerPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = IntegerPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -747,9 +655,11 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const InterfaceOnlyComponentViewConfig = { +let nativeComponentName = 'RCTInterfaceOnlyComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'RCTInterfaceOnlyComponent', bubblingEventTypes: { @@ -765,15 +675,7 @@ const InterfaceOnlyComponentViewConfig = { accessibilityHint: true, onChange: true, }, -}; - -let nativeComponentName = 'RCTInterfaceOnlyComponent'; - -registerGeneratedViewConfig(nativeComponentName, InterfaceOnlyComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = InterfaceOnlyComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -794,26 +696,31 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'ImageColorPropNativeComponent'; -const ImageColorPropNativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ImageColorPropNativeComponent', validAttributes: { - thumbImage: { process: require('resolveAssetSource') }, - color: { process: require('processColor') }, - thumbTintColor: { process: require('processColor') }, - point: { diff: require('pointsDiffer') }, - }, -}; - -let nativeComponentName = 'ImageColorPropNativeComponent'; + thumbImage: { + process: require('resolveAssetSource'), + }, -registerGeneratedViewConfig(nativeComponentName, ImageColorPropNativeComponentViewConfig); + color: { + process: require('processColor'), + }, -export const __INTERNAL_VIEW_CONFIG = ImageColorPropNativeComponentViewConfig; + thumbTintColor: { + process: require('processColor'), + }, -export default nativeComponentName; + point: { + diff: require('pointsDiffer'), + }, + }, +})); ", } `; @@ -834,20 +741,14 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); - -const NoPropsNoEventsComponentViewConfig = { - uiViewClassName: 'NoPropsNoEventsComponent', - validAttributes: {}, -}; +const NativeComponentRegistry = require('NativeComponentRegistry'); let nativeComponentName = 'NoPropsNoEventsComponent'; -registerGeneratedViewConfig(nativeComponentName, NoPropsNoEventsComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = NoPropsNoEventsComponentViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ + uiViewClassName: 'NoPropsNoEventsComponent', + validAttributes: {}, +})); ", } `; @@ -868,23 +769,17 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'ObjectProps'; -const ObjectPropsViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'ObjectProps', validAttributes: { objectProp: true, }, -}; - -let nativeComponentName = 'ObjectProps'; - -registerGeneratedViewConfig(nativeComponentName, ObjectPropsViewConfig); - -export const __INTERNAL_VIEW_CONFIG = ObjectPropsViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -905,23 +800,19 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); + +let nativeComponentName = 'PointPropNativeComponent'; -const PointPropNativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'PointPropNativeComponent', validAttributes: { - startPoint: { diff: require('pointsDiffer') }, + startPoint: { + diff: require('pointsDiffer'), + }, }, -}; - -let nativeComponentName = 'PointPropNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, PointPropNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = PointPropNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -942,23 +833,17 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const StringEnumPropsNativeComponentViewConfig = { +let nativeComponentName = 'StringEnumPropsNativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'StringEnumPropsNativeComponent', validAttributes: { alignment: true, }, -}; - -let nativeComponentName = 'StringEnumPropsNativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, StringEnumPropsNativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = StringEnumPropsNativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -979,24 +864,18 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const StringPropComponentViewConfig = { +let nativeComponentName = 'StringPropComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'StringPropComponent', validAttributes: { accessibilityHint: true, accessibilityRole: true, }, -}; - -let nativeComponentName = 'StringPropComponent'; - -registerGeneratedViewConfig(nativeComponentName, StringPropComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = StringPropComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -1017,39 +896,27 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const MultiFile1NativeComponentViewConfig = { +let nativeComponentName = 'MultiFile1NativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'MultiFile1NativeComponent', validAttributes: { disabled: true, }, -}; - -let nativeComponentName = 'MultiFile1NativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, MultiFile1NativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = MultiFile1NativeComponentViewConfig; +})); -export default nativeComponentName; +let nativeComponentName = 'MultiFile2NativeComponent'; -const MultiFile2NativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'MultiFile2NativeComponent', validAttributes: { disabled: true, }, -}; - -let nativeComponentName = 'MultiFile2NativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, MultiFile2NativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = MultiFile2NativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -1070,39 +937,27 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); -const MultiComponent1NativeComponentViewConfig = { +let nativeComponentName = 'MultiComponent1NativeComponent'; + +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'MultiComponent1NativeComponent', validAttributes: { disabled: true, }, -}; - -let nativeComponentName = 'MultiComponent1NativeComponent'; +})); -registerGeneratedViewConfig(nativeComponentName, MultiComponent1NativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = MultiComponent1NativeComponentViewConfig; - -export default nativeComponentName; +let nativeComponentName = 'MultiComponent2NativeComponent'; -const MultiComponent2NativeComponentViewConfig = { +export default NativeComponentRegistry.get(nativeComponentName, () => ({ uiViewClassName: 'MultiComponent2NativeComponent', validAttributes: { disabled: true, }, -}; - -let nativeComponentName = 'MultiComponent2NativeComponent'; - -registerGeneratedViewConfig(nativeComponentName, MultiComponent2NativeComponentViewConfig); - -export const __INTERNAL_VIEW_CONFIG = MultiComponent2NativeComponentViewConfig; - -export default nativeComponentName; +})); ", } `; @@ -1123,27 +978,21 @@ Map { 'use strict'; -const registerGeneratedViewConfig = require('registerGeneratedViewConfig'); +const NativeComponentRegistry = require('NativeComponentRegistry'); const {UIManager} = require(\\"react-native\\") -const NativeComponentNameViewConfig = { - uiViewClassName: 'NativeComponentName', - validAttributes: {}, -}; - let nativeComponentName = 'NativeComponentName'; if (UIManager.getViewManagerConfig('NativeComponentName')) { nativeComponentName = 'NativeComponentName'; -} else if (UIManager.getViewManagerConfig('DeprecatedNativeComponentName')){ +} else if (UIManager.getViewManagerConfig('DeprecatedNativeComponentName')) { nativeComponentName = 'DeprecatedNativeComponentName'; } else { - throw new Error('Failed to find native component for either \\"NativeComponentName\\" or \\"DeprecatedNativeComponentName\\"') + throw new Error('Failed to find native component for either \\"NativeComponentName\\" or \\"DeprecatedNativeComponentName\\"'); } -registerGeneratedViewConfig(nativeComponentName, NativeComponentNameViewConfig); - -export const __INTERNAL_VIEW_CONFIG = NativeComponentNameViewConfig; - -export default nativeComponentName; +export default NativeComponentRegistry.get(nativeComponentName, () => ({ + uiViewClassName: 'NativeComponentName', + validAttributes: {}, +})); ", } `; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index cf02b4095b1c92..215b57846dc8a8 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -10,41 +10,74 @@ 'use strict'; -import type {SchemaType} from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); -type FilesOutput = Map; - -const propertyHeaderTemplate = - 'static jsi::Value __hostFunction_Native::_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {'; - -const propertyCastTemplate = - 'static_cast(&turboModule)->::_PROPERTY_NAME_::(rt::_ARGS_::);'; +import type { + SchemaType, + Nullable, + NamedShape, + NativeModulePropertyShape, + NativeModuleFunctionTypeAnnotation, + NativeModuleParamTypeAnnotation, +} from '../../CodegenSchema'; + +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); +const {unwrapNullable} = require('../../parsers/flow/modules/utils'); -const nonvoidPropertyTemplate = ` -${propertyHeaderTemplate} - return ${propertyCastTemplate} -}`.trim(); +type FilesOutput = Map; -const voidPropertyTemplate = ` -${propertyHeaderTemplate} - ${propertyCastTemplate} - return jsi::Value::undefined(); +const HostFunctionTemplate = ({ + hasteModuleName, + methodName, + isVoid, + args, +}: $ReadOnly<{ + hasteModuleName: string, + methodName: string, + isVoid: boolean, + args: Array, +}>) => { + const methodCallArgs = ['rt', ...args].join(', '); + const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`; + + return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${ + isVoid ? `\n ${methodCall}` : '' + } + return ${isVoid ? 'jsi::Value::undefined();' : methodCall} }`; +}; -const proprertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::};'; - -const moduleTemplate = ` -::_MODULE_PROPERTIES_:: - -Native::_MODULE_NAME_::CxxSpecJSI::Native::_MODULE_NAME_::CxxSpecJSI(std::shared_ptr jsInvoker) - : TurboModule("::_MODULE_NAME_::", jsInvoker) { -::_PROPERTIES_MAP_:: -}`.trim(); +const ModuleTemplate = ({ + hasteModuleName, + hostFunctions, + moduleName, + methods, +}: $ReadOnly<{ + hasteModuleName: string, + hostFunctions: $ReadOnlyArray, + moduleName: string, + methods: $ReadOnlyArray<$ReadOnly<{methodName: string, paramCount: number}>>, +}>) => { + return `${hostFunctions.join('\n')} + +${hasteModuleName}CxxSpecJSI::${hasteModuleName}CxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("${moduleName}", jsInvoker) { +${methods + .map(({methodName, paramCount}) => { + return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`; + }) + .join('\n')} +}`; +}; -const template = ` -/** - * Copyright (c) Facebook, Inc. and its affiliates. +const FileTemplate = ({ + libraryName, + modules, +}: $ReadOnly<{ + libraryName: string, + modules: string, +}>) => { + return `/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -52,30 +85,41 @@ const template = ` * ${'@'}generated by codegen project: GenerateModuleH.js */ -#include +#include namespace facebook { namespace react { -::_MODULES_:: +${modules} } // namespace react } // namespace facebook `; +}; -function traverseArg(arg, index, aliases): string { +type Param = NamedShape>; + +function serializeArg( + arg: Param, + index: number, + resolveAlias: AliasResolver, +): string { function wrap(suffix) { return `args[${index}]${suffix}`; } - const {typeAnnotation} = arg; + const {typeAnnotation: nullableTypeAnnotation} = arg; + const [typeAnnotation] = unwrapNullable( + nullableTypeAnnotation, + ); + + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return wrap('.getNumber()'); @@ -90,7 +134,11 @@ function traverseArg(arg, index, aliases): string { case 'BooleanTypeAnnotation': return wrap('.getBool()'); case 'NumberTypeAnnotation': + return wrap('.getNumber()'); case 'FloatTypeAnnotation': + return wrap('.getNumber()'); + case 'DoubleTypeAnnotation': + return wrap('.getNumber()'); case 'Int32TypeAnnotation': return wrap('.getNumber()'); case 'ArrayTypeAnnotation': @@ -98,76 +146,88 @@ function traverseArg(arg, index, aliases): string { case 'FunctionTypeAnnotation': return `std::move(${wrap('.getObject(rt).getFunction(rt)')})`; case 'GenericObjectTypeAnnotation': + return wrap('.getObject(rt)'); case 'ObjectTypeAnnotation': return wrap('.getObject(rt)'); - case 'AnyTypeAnnotation': - throw new Error(`Any type is not allowed in params for "${arg.name}"`); default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); + (realTypeAnnotation.type: empty); throw new Error( `Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`, ); } } -function traverseProperty(property, aliases): string { - const propertyTemplate = - property.typeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation' - ? voidPropertyTemplate - : nonvoidPropertyTemplate; - const traversedArgs = property.typeAnnotation.params - .map((p, i) => traverseArg(p, i, aliases)) - .join(', '); - return propertyTemplate - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace(/::_ARGS_::/g, traversedArgs === '' ? '' : ', ' + traversedArgs); +function serializePropertyIntoHostFunction( + hasteModuleName: string, + property: NativeModulePropertyShape, + resolveAlias: AliasResolver, +): string { + const [ + propertyTypeAnnotation, + ] = unwrapNullable( + property.typeAnnotation, + ); + const isVoid = + propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation'; + + return HostFunctionTemplate({ + hasteModuleName, + methodName: property.name, + isVoid, + args: propertyTypeAnnotation.params.map((p, i) => + serializeArg(p, i, resolveAlias), + ), + }); } module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) - .map(name => { - const {aliases, properties} = nativeModules[name]; - const traversedProperties = properties - .map(property => traverseProperty(property, aliases)) - .join('\n'); - return moduleTemplate - .replace(/::_MODULE_PROPERTIES_::/g, traversedProperties) - .replace( - '::_PROPERTIES_MAP_::', - properties - .map(({name: propertyName, typeAnnotation: {params}}) => - proprertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()), - ) - .join('\n'), - ) - .replace(/::_MODULE_NAME_::/g, name); + .map((hasteModuleName: string) => { + const nativeModule = nativeModules[hasteModuleName]; + const { + aliases, + spec: {properties}, + moduleNames, + } = nativeModule; + const resolveAlias = createAliasResolver(aliases); + const hostFunctions = properties.map(property => + serializePropertyIntoHostFunction( + hasteModuleName, + property, + resolveAlias, + ), + ); + + return ModuleTemplate({ + hasteModuleName, + hostFunctions, + // TODO: What happens when there are more than one NativeModule requires? + moduleName: moduleNames[0], + methods: properties.map( + ({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => { + const [{params}] = unwrapNullable(nullableTypeAnnotation); + return { + methodName: propertyName, + paramCount: params.length, + }; + }, + ), + }); }) .join('\n'); const fileName = 'NativeModules.cpp'; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName); + const replacedTemplate = FileTemplate({ + modules, + libraryName, + }); return new Map([[fileName, replacedTemplate]]); }, }; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index 7342ad01a7c32a..2b50bd76b827c6 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -11,29 +11,39 @@ 'use strict'; import type { + Nullable, SchemaType, - FunctionTypeAnnotationParamTypeAnnotation, - FunctionTypeAnnotationReturn, - TypeAliasTypeAnnotation, - ObjectTypeAliasTypeShape, + NativeModuleTypeAnnotation, + NativeModuleFunctionTypeAnnotation, } from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); +const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; -const moduleTemplate = ` -class JSI_EXPORT Native::_MODULE_NAME_::CxxSpecJSI : public TurboModule { +const ModuleClassDeclarationTemplate = ({ + hasteModuleName, + moduleProperties, +}: $ReadOnly<{hasteModuleName: string, moduleProperties: string}>) => { + return `class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule { protected: - Native::_MODULE_NAME_::CxxSpecJSI(std::shared_ptr jsInvoker); + ${hasteModuleName}CxxSpecJSI(std::shared_ptr jsInvoker); public: -::_MODULE_PROPERTIES_:: +${moduleProperties} };`; +}; -const template = `/** - * Copyright (c) Facebook, Inc. and its affiliates. +const FileTemplate = ({ + modules, +}: $ReadOnly<{ + modules: string, +}>) => { + return `/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -47,26 +57,28 @@ const template = `/** namespace facebook { namespace react { -::_MODULES_:: +${modules} } // namespace react } // namespace facebook `; +}; function translatePrimitiveJSTypeToCpp( - typeAnnotation: - | FunctionTypeAnnotationParamTypeAnnotation - | FunctionTypeAnnotationReturn - | TypeAliasTypeAnnotation, + nullableTypeAnnotation: Nullable, createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + resolveAlias: AliasResolver, ) { - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + const [typeAnnotation] = unwrapNullable( + nullableTypeAnnotation, + ); + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return 'double'; @@ -79,6 +91,9 @@ function translatePrimitiveJSTypeToCpp( case 'StringTypeAnnotation': return 'jsi::String'; case 'NumberTypeAnnotation': + return 'double'; + case 'DoubleTypeAnnotation': + return 'double'; case 'FloatTypeAnnotation': return 'double'; case 'Int32TypeAnnotation': @@ -86,17 +101,17 @@ function translatePrimitiveJSTypeToCpp( case 'BooleanTypeAnnotation': return 'bool'; case 'GenericObjectTypeAnnotation': + return 'jsi::Object'; case 'ObjectTypeAnnotation': return 'jsi::Object'; case 'ArrayTypeAnnotation': return 'jsi::Array'; case 'FunctionTypeAnnotation': return 'jsi::Function'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'jsi::Value'; default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); + (realTypeAnnotation.type: empty); throw new Error(createErrorMessage(realTypeAnnotation.type)); } } @@ -108,32 +123,32 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) - .map(name => { - const {aliases, properties} = nativeModules[name]; + .map(hasteModuleName => { + const { + aliases, + spec: {properties}, + } = nativeModules[hasteModuleName]; + const resolveAlias = createAliasResolver(aliases); + const traversedProperties = properties .map(prop => { - const traversedArgs = prop.typeAnnotation.params + const [ + propTypeAnnotation, + ] = unwrapNullable( + prop.typeAnnotation, + ); + const traversedArgs = propTypeAnnotation.params .map(param => { const translatedParam = translatePrimitiveJSTypeToCpp( param.typeAnnotation, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, - aliases, + resolveAlias, ); const isObject = translatedParam.startsWith('jsi::'); return ( @@ -148,10 +163,10 @@ module.exports = { .replace( '::_RETURN_VALUE_::', translatePrimitiveJSTypeToCpp( - prop.typeAnnotation.returnTypeAnnotation, + propTypeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, - aliases, + resolveAlias, ), ) .replace( @@ -160,15 +175,16 @@ module.exports = { ); }) .join('\n'); - return moduleTemplate - .replace(/::_MODULE_PROPERTIES_::/g, traversedProperties) - .replace(/::_MODULE_NAME_::/g, name) - .replace('::_PROPERTIES_MAP_::', ''); + + return ModuleClassDeclarationTemplate({ + hasteModuleName, + moduleProperties: traversedProperties, + }); }) .join('\n'); const fileName = 'NativeModules.h'; - const replacedTemplate = template.replace(/::_MODULES_::/g, modules); + const replacedTemplate = FileTemplate({modules}); return new Map([[fileName, replacedTemplate]]); }, diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js deleted file mode 100644 index c9f173df868e37..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js +++ /dev/null @@ -1,415 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type { - SchemaType, - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../CodegenSchema'; - -const { - translateObjectsForStructs, - capitalizeFirstLetter, - getNamespacedStructName, -} = require('./ObjCppUtils/GenerateStructs'); - -const {getTypeAliasTypeAnnotation} = require('./Utils'); - -type FilesOutput = Map; - -const moduleTemplate = ` /** - * ObjC++ class for module '::_MODULE_NAME_::' - */ - class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public ObjCTurboModule { - public: - Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms); - };`; - -const protocolTemplate = `::_STRUCTS_:: - -@protocol Native::_MODULE_NAME_::Spec -::_MODULE_PROPERTIES_:: -@end -`; - -const callbackArgs = prop => - prop.typeAnnotation.returnTypeAnnotation.type === - 'GenericPromiseTypeAnnotation' - ? `${ - prop.typeAnnotation.params.length === 0 ? '' : '\n resolve' - }:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject` - : ''; - -const template = ` -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * ${'@'}generated by codegen project: GenerateModuleHObjCpp.js - */ - -#ifndef __cplusplus -#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. -#endif - -#import - -#import - -#import - -#import -#import -#import - -#import -#import -#import - -#import - -::_PROTOCOLS_:: - -namespace facebook { - namespace react { -::_MODULES_:: - } // namespace react -} // namespace facebook -`; - -type ObjectForGeneratingStructs = $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, -|}>; - -const constants = `- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants;`; - -function translatePrimitiveJSTypeToObjCType( - param: FunctionTypeAnnotationParam, - createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -) { - const {nullable, typeAnnotation} = param; - - function wrapIntoNullableIfNeeded(generatedType: string) { - return nullable ? `${generatedType} _Nullable` : generatedType; - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return nullable ? 'NSNumber *' : 'double'; - default: - (realTypeAnnotation.name: empty); - throw new Error(createErrorMessage(realTypeAnnotation.name)); - } - case 'StringTypeAnnotation': - return wrapIntoNullableIfNeeded('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return nullable ? 'NSNumber *' : 'double'; - case 'BooleanTypeAnnotation': - return nullable ? 'NSNumber * _Nullable' : 'BOOL'; - case 'ObjectTypeAnnotation': - if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { - return getNamespacedStructName(typeAnnotation.name) + ' &'; - } - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'GenericObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'ArrayTypeAnnotation': - return wrapIntoNullableIfNeeded('NSArray *'); - case 'FunctionTypeAnnotation': - return 'RCTResponseSenderBlock'; - default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); - throw new Error(createErrorMessage(realTypeAnnotation.type)); - } -} - -function translatePrimitiveJSTypeToObjCTypeForReturn( - typeAnnotation: FunctionTypeAnnotationReturn, - createErrorMessage: (typeName: string) => string, -) { - function wrapIntoNullableIfNeeded(generatedType: string) { - return typeAnnotation.nullable - ? `${generatedType} _Nullable` - : generatedType; - } - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { - case 'RootTag': - return wrapIntoNullableIfNeeded('NSNumber *'); - default: - (typeAnnotation.name: empty); - throw new Error(createErrorMessage(typeAnnotation.name)); - } - case 'VoidTypeAnnotation': - case 'GenericPromiseTypeAnnotation': - return 'void'; - case 'StringTypeAnnotation': - return wrapIntoNullableIfNeeded('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return wrapIntoNullableIfNeeded('NSNumber *'); - case 'BooleanTypeAnnotation': - return typeAnnotation.nullable ? 'NSNumber * _Nullable' : 'BOOL'; - case 'GenericObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'ArrayTypeAnnotation': - return wrapIntoNullableIfNeeded('NSArray> *'); - case 'ObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error(createErrorMessage(typeAnnotation.type)); - } -} - -function handleArrayOfObjects( - objectForGeneratingStructs: Array, - propOrParam: FunctionTypeAnnotationParam, - name: string, -) { - if ( - propOrParam.typeAnnotation.type === 'ArrayTypeAnnotation' && - propOrParam.typeAnnotation.elementType - ) { - const typeAnnotation = propOrParam.typeAnnotation.elementType; - const type = typeAnnotation.type; - - if ( - type === 'ObjectTypeAnnotation' && - typeAnnotation.properties && - typeAnnotation.properties.length > 0 - ) { - objectForGeneratingStructs.push({ - name, - object: { - type: 'ObjectTypeAnnotation', - properties: typeAnnotation.properties, - }, - }); - } - } -} - -const methodImplementationTemplate = - '- (::_RETURN_VALUE_::) ::_PROPERTY_NAME_::::_ARGS_::;'; - -module.exports = { - generate( - libraryName: string, - schema: SchemaType, - moduleSpecName: string, - ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .sort() - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); - - const modules = Object.keys(nativeModules) - .map(name => moduleTemplate.replace(/::_MODULE_NAME_::/g, name)) - .join('\n'); - - const protocols = Object.keys(nativeModules) - .sort() - .map(name => { - const objectForGeneratingStructs: Array = []; - const {aliases, properties} = nativeModules[name]; - const implementations = properties - .map(prop => { - const nativeArgs = prop.typeAnnotation.params - .map((param, i) => { - let paramObjCType; - if ( - param.typeAnnotation.type === 'ObjectTypeAnnotation' && - param.typeAnnotation.properties - ) { - const variableName = - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name); - const structName = 'Spec' + variableName; - objectForGeneratingStructs.push({ - name: structName, - object: { - type: 'ObjectTypeAnnotation', - properties: param.typeAnnotation.properties, - }, - }); - paramObjCType = getNamespacedStructName(structName) + ' &'; - - param.typeAnnotation.properties.map(aProp => { - return handleArrayOfObjects( - objectForGeneratingStructs, - aProp, - 'Spec' + - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name) + - capitalizeFirstLetter(aProp.name) + - 'Element', - ); - }); - } else if ( - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ) { - const typeAnnotation = getTypeAliasTypeAnnotation( - param.typeAnnotation.name, - aliases, - ); - if (typeAnnotation.type === 'ObjectTypeAnnotation') { - paramObjCType = - getNamespacedStructName(param.typeAnnotation.name) + ' &'; - } else { - throw Error( - `Unsupported type for "${param.typeAnnotation.name}". Found: ${typeAnnotation.type}`, - ); - } - } else { - paramObjCType = translatePrimitiveJSTypeToObjCType( - param, - typeName => - `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, - aliases, - ); - - handleArrayOfObjects( - objectForGeneratingStructs, - param, - 'Spec' + - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name) + - 'Element', - ); - } - return `${i === 0 ? '' : param.name}:(${paramObjCType})${ - param.name - }`; - }) - .join('\n ') - .concat(callbackArgs(prop)); - const {returnTypeAnnotation} = prop.typeAnnotation; - if ( - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties - ) { - objectForGeneratingStructs.push({ - name: 'Spec' + capitalizeFirstLetter(prop.name) + 'ReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: returnTypeAnnotation.properties, - }, - }); - } - const implementation = methodImplementationTemplate - .replace('::_PROPERTY_NAME_::', prop.name) - .replace( - '::_RETURN_VALUE_::', - translatePrimitiveJSTypeToObjCTypeForReturn( - returnTypeAnnotation, - typeName => - `Unsupported return type for ${prop.name}. Found: ${typeName}`, - ), - ) - .replace('::_ARGS_::', nativeArgs); - if (prop.name === 'getConstants') { - if ( - prop.typeAnnotation.returnTypeAnnotation.properties && - prop.typeAnnotation.returnTypeAnnotation.properties.length === 0 - ) { - return ''; - } - return constants.replace(/::_MODULE_NAME_::/, name); - } - return implementation; - }) - .join('\n'); - - Object.keys(aliases) - .reverse() - .map((aliasName, i) => { - const alias = aliases[aliasName]; - - let paramObjCType = ''; - - switch (alias.type) { - case 'ObjectTypeAnnotation': - if (alias.properties) { - objectForGeneratingStructs.push({ - name: aliasName, - object: { - type: 'ObjectTypeAnnotation', - properties: alias.properties, - }, - }); - paramObjCType = getNamespacedStructName(alias.name) + ' &'; - } - break; - default: - throw Error( - `Unsupported type for "${aliasName}". Found: ${alias.type}`, - ); - } - return `${i === 0 ? '' : aliasName}:(${paramObjCType})${aliasName}`; - }) - .join('\n'); - - return protocolTemplate - .replace( - /::_STRUCTS_::/g, - translateObjectsForStructs( - objectForGeneratingStructs, - name, - aliases, - ), - ) - .replace(/::_MODULE_PROPERTIES_::/g, implementations) - .replace(/::_MODULE_NAME_::/g, name) - .replace('::_PROPERTIES_MAP_::', ''); - }) - .join('\n'); - - const fileName = `${moduleSpecName}.h`; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_PROTOCOLS_::/g, protocols); - - return new Map([[fileName, replacedTemplate]]); - }, -}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js index 5054146e4ffc56..3f7f81897497e3 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js @@ -11,18 +11,33 @@ 'use strict'; import type { - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - NativeModuleMethodTypeShape, - ObjectTypeAliasTypeShape, + Nullable, + NamedShape, SchemaType, + NativeModulePropertyShape, + NativeModuleReturnTypeAnnotation, + NativeModuleFunctionTypeAnnotation, + NativeModuleParamTypeAnnotation, } from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); + +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); +const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; -const moduleTemplate = `/** - * Copyright (c) Facebook, Inc. and its affiliates. +function FileTemplate( + config: $ReadOnly<{ + packageName: string, + className: string, + methods: string, + imports: string, + }>, +): string { + const {packageName, className, methods, imports} = config; + return ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. @@ -32,44 +47,83 @@ const moduleTemplate = `/** * @nolint */ -package ::_PACKAGENAME_::; +package ${packageName}; -::_IMPORTS_:: +${imports} -public abstract class ::_CLASSNAME_:: extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public ::_CLASSNAME_::(ReactApplicationContext reactContext) { +public abstract class ${className} extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public ${className}(ReactApplicationContext reactContext) { super(reactContext); } -::_METHODS_:: +${methods} } `; +} + +function MethodTemplate( + config: $ReadOnly<{ + abstract: boolean, + methodBody: ?string, + methodJavaAnnotation: string, + methodName: string, + translatedReturnType: string, + traversedArgs: Array, + }>, +): string { + const { + abstract, + methodBody, + methodJavaAnnotation, + methodName, + translatedReturnType, + traversedArgs, + } = config; + const methodQualifier = abstract ? 'abstract ' : ''; + const methodClosing = abstract + ? ';' + : methodBody != null && methodBody.length > 0 + ? ` { ${methodBody} }` + : ' {}'; + return ` ${methodJavaAnnotation} + public ${methodQualifier}${translatedReturnType} ${methodName}(${traversedArgs.join( + ', ', + )})${methodClosing}`; +} + +type Param = NamedShape>; function translateFunctionParamToJavaType( - param: FunctionTypeAnnotationParam, + param: Param, createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + resolveAlias: AliasResolver, imports: Set, ): string { - const {nullable, typeAnnotation} = param; + const {optional, typeAnnotation: nullableTypeAnnotation} = param; + const [ + typeAnnotation, + nullable, + ] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !optional && !nullable; function wrapIntoNullableIfNeeded(generatedType: string) { - if (nullable) { + if (!isRequired) { imports.add('javax.annotation.Nullable'); return `@Nullable ${generatedType}`; } return generatedType; } - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': - return nullable ? 'Double' : 'double'; + return !isRequired ? 'Double' : 'double'; default: (realTypeAnnotation.name: empty); throw new Error(createErrorMessage(realTypeAnnotation.name)); @@ -77,11 +131,15 @@ function translateFunctionParamToJavaType( case 'StringTypeAnnotation': return wrapIntoNullableIfNeeded('String'); case 'NumberTypeAnnotation': + return !isRequired ? 'Double' : 'double'; case 'FloatTypeAnnotation': + return !isRequired ? 'Double' : 'double'; + case 'DoubleTypeAnnotation': + return !isRequired ? 'Double' : 'double'; case 'Int32TypeAnnotation': - return nullable ? 'Double' : 'double'; + return !isRequired ? 'Double' : 'double'; case 'BooleanTypeAnnotation': - return nullable ? 'Boolean' : 'boolean'; + return !isRequired ? 'Boolean' : 'boolean'; case 'ObjectTypeAnnotation': imports.add('com.facebook.react.bridge.ReadableMap'); if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { @@ -100,16 +158,23 @@ function translateFunctionParamToJavaType( imports.add('com.facebook.react.bridge.Callback'); return 'Callback'; default: + (realTypeAnnotation.type: empty); throw new Error(createErrorMessage(realTypeAnnotation.type)); } } function translateFunctionReturnTypeToJavaType( - returnTypeAnnotation: FunctionTypeAnnotationReturn, + nullableReturnTypeAnnotation: Nullable, createErrorMessage: (typeName: string) => string, + resolveAlias: AliasResolver, imports: Set, ): string { - const {nullable} = returnTypeAnnotation; + const [ + returnTypeAnnotation, + nullable, + ] = unwrapNullable( + nullableReturnTypeAnnotation, + ); function wrapIntoNullableIfNeeded(generatedType: string) { if (nullable) { @@ -119,23 +184,32 @@ function translateFunctionReturnTypeToJavaType( return generatedType; } - // TODO: Support aliased return type. This doesn't exist in React Native Android yet. - switch (returnTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (returnTypeAnnotation.name) { + let realTypeAnnotation = returnTypeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (realTypeAnnotation.name) { case 'RootTag': return nullable ? 'Double' : 'double'; default: - (returnTypeAnnotation.name: empty); - throw new Error(createErrorMessage(returnTypeAnnotation.name)); + (realTypeAnnotation.name: empty); + throw new Error(createErrorMessage(realTypeAnnotation.name)); } case 'VoidTypeAnnotation': - case 'GenericPromiseTypeAnnotation': + return 'void'; + case 'PromiseTypeAnnotation': return 'void'; case 'StringTypeAnnotation': return wrapIntoNullableIfNeeded('String'); case 'NumberTypeAnnotation': + return nullable ? 'Double' : 'double'; case 'FloatTypeAnnotation': + return nullable ? 'Double' : 'double'; + case 'DoubleTypeAnnotation': + return nullable ? 'Double' : 'double'; case 'Int32TypeAnnotation': return nullable ? 'Double' : 'double'; case 'BooleanTypeAnnotation': @@ -150,24 +224,82 @@ function translateFunctionReturnTypeToJavaType( imports.add('com.facebook.react.bridge.WritableArray'); return 'WritableArray'; default: - throw new Error(createErrorMessage(returnTypeAnnotation.type)); + (realTypeAnnotation.type: empty); + throw new Error(createErrorMessage(realTypeAnnotation.type)); + } +} + +function getFalsyReturnStatementFromReturnType( + nullableReturnTypeAnnotation: Nullable, + createErrorMessage: (typeName: string) => string, + resolveAlias: AliasResolver, +): string { + const [ + returnTypeAnnotation, + nullable, + ] = unwrapNullable( + nullableReturnTypeAnnotation, + ); + + let realTypeAnnotation = returnTypeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (realTypeAnnotation.name) { + case 'RootTag': + return 'return 0.0;'; + default: + (realTypeAnnotation.name: empty); + throw new Error(createErrorMessage(realTypeAnnotation.name)); + } + case 'VoidTypeAnnotation': + return ''; + case 'PromiseTypeAnnotation': + return ''; + case 'NumberTypeAnnotation': + return nullable ? 'return null;' : 'return 0;'; + case 'FloatTypeAnnotation': + return nullable ? 'return null;' : 'return 0.0;'; + case 'DoubleTypeAnnotation': + return nullable ? 'return null;' : 'return 0.0;'; + case 'Int32TypeAnnotation': + return nullable ? 'return null;' : 'return 0;'; + case 'BooleanTypeAnnotation': + return nullable ? 'return null;' : 'return false;'; + case 'StringTypeAnnotation': + return nullable ? 'return null;' : 'return "";'; + case 'ObjectTypeAnnotation': + return 'return null;'; + case 'GenericObjectTypeAnnotation': + return 'return null;'; + case 'ArrayTypeAnnotation': + return 'return null;'; + default: + (realTypeAnnotation.type: empty); + throw new Error(createErrorMessage(realTypeAnnotation.type)); } } // Build special-cased runtime check for getConstants(). function buildGetConstantsMethod( - method: NativeModuleMethodTypeShape, + method: NativeModulePropertyShape, imports: Set, ): string { + const [ + methodTypeAnnotation, + ] = unwrapNullable(method.typeAnnotation); if ( - method.typeAnnotation.returnTypeAnnotation.type === 'ObjectTypeAnnotation' + methodTypeAnnotation.returnTypeAnnotation.type === 'ObjectTypeAnnotation' ) { const requiredProps = []; const optionalProps = []; const rawProperties = - method.typeAnnotation.returnTypeAnnotation.properties || []; + methodTypeAnnotation.returnTypeAnnotation.properties || []; rawProperties.forEach(p => { - if (p.optional) { + if (p.optional || p.typeAnnotation.type === 'NullableTypeAnnotation') { optionalProps.push(p.name); } else { requiredProps.push(p.name); @@ -235,26 +367,26 @@ module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { const files = new Map(); - // TODO: Allow package configuration. - const packageName = 'com.facebook.fbreact.specs.beta'; - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } + const nativeModules = getModules(schema); - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); + const normalizedPackageName = + packageName == null ? 'com.facebook.fbreact.specs' : packageName; + const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`; - Object.keys(nativeModules).forEach(name => { - const {aliases, properties} = nativeModules[name]; - const className = `Native${name}Spec`; + Object.keys(nativeModules).forEach(hasteModuleName => { + const { + aliases, + excludedPlatforms, + spec: {properties}, + } = nativeModules[hasteModuleName]; + if (excludedPlatforms != null && excludedPlatforms.includes('android')) { + return; + } + const resolveAlias = createAliasResolver(aliases); + const className = `${hasteModuleName}Spec`; const imports: Set = new Set([ // Always required. @@ -263,6 +395,7 @@ module.exports = { 'com.facebook.react.bridge.ReactMethod', 'com.facebook.react.bridge.ReactModuleWithSpec', 'com.facebook.react.turbomodule.core.interfaces.TurboModule', + 'com.facebook.proguard.annotations.DoNotStrip', ]); const methods = properties.map(method => { @@ -270,27 +403,34 @@ module.exports = { return buildGetConstantsMethod(method, imports); } + const [ + methodTypeAnnotation, + ] = unwrapNullable( + method.typeAnnotation, + ); + // Handle return type const translatedReturnType = translateFunctionReturnTypeToJavaType( - method.typeAnnotation.returnTypeAnnotation, + methodTypeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for method ${method.name}. Found: ${typeName}`, + resolveAlias, imports, ); const returningPromise = - method.typeAnnotation.returnTypeAnnotation.type === - 'GenericPromiseTypeAnnotation'; + methodTypeAnnotation.returnTypeAnnotation.type === + 'PromiseTypeAnnotation'; const isSyncMethod = - method.typeAnnotation.returnTypeAnnotation.type !== + methodTypeAnnotation.returnTypeAnnotation.type !== 'VoidTypeAnnotation' && !returningPromise; // Handle method args - const traversedArgs = method.typeAnnotation.params.map(param => { + const traversedArgs = methodTypeAnnotation.params.map(param => { const translatedParam = translateFunctionParamToJavaType( param, typeName => `Unsupported type for param "${param.name}" in ${method.name}. Found: ${typeName}`, - aliases, + resolveAlias, imports, ); return `${translatedParam} ${param.name}`; @@ -304,26 +444,36 @@ module.exports = { const methodJavaAnnotation = `@ReactMethod${ isSyncMethod ? '(isBlockingSynchronousMethod = true)' : '' - }`; - return ` ${methodJavaAnnotation} - public abstract ${translatedReturnType} ${method.name}(${traversedArgs.join( - ', ', - )});`; + }\n @DoNotStrip`; + const methodBody = method.optional + ? getFalsyReturnStatementFromReturnType( + methodTypeAnnotation.returnTypeAnnotation, + typeName => + `Cannot build falsy return statement for return type for method ${method.name}. Found: ${typeName}`, + resolveAlias, + ) + : null; + return MethodTemplate({ + abstract: !method.optional, + methodBody, + methodJavaAnnotation, + methodName: method.name, + translatedReturnType, + traversedArgs, + }); }); files.set( - `${className}.java`, - moduleTemplate - .replace( - /::_IMPORTS_::/g, - Array.from(imports) - .sort() - .map(p => `import ${p};`) - .join('\n'), - ) - .replace(/::_PACKAGENAME_::/g, packageName) - .replace(/::_CLASSNAME_::/g, className) - .replace(/::_METHODS_::/g, methods.filter(m => !!m).join('\n\n')), + `${outputDir}/${className}.java`, + FileTemplate({ + packageName: normalizedPackageName, + className, + methods: methods.filter(Boolean).join('\n\n'), + imports: Array.from(imports) + .sort() + .map(p => `import ${p};`) + .join('\n'), + }), ); }); diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js index 45182b9bbc4c00..6f01ed4002edbf 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js @@ -11,42 +11,95 @@ 'use strict'; import type { - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - NativeModuleShape, - ObjectTypeAliasTypeShape, + Nullable, + NamedShape, SchemaType, + NativeModulePropertyShape, + NativeModuleReturnTypeAnnotation, + NativeModuleParamTypeAnnotation, + NativeModuleFunctionTypeAnnotation, } from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); +const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; -const propertyHeaderTemplate = - 'static facebook::jsi::Value __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; +type JSReturnType = + | 'VoidKind' + | 'StringKind' + | 'BooleanKind' + | 'NumberKind' + | 'PromiseKind' + | 'ObjectKind' + | 'ArrayKind'; -const propertyCastTemplate = - 'static_cast(turboModule).invokeJavaMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", "::_SIGNATURE_::", args, count);'; - -const propertyTemplate = ` -${propertyHeaderTemplate} - return ${propertyCastTemplate} +const HostFunctionTemplate = ({ + hasteModuleName, + propertyName, + jniSignature, + jsReturnType, +}: $ReadOnly<{ + hasteModuleName: string, + propertyName: string, + jniSignature: string, + jsReturnType: JSReturnType, +}>) => { + return `static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${propertyName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count); }`; +}; -const propertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; - -const moduleTemplate = ` -::_TURBOMODULE_METHOD_INVOKERS_:: - -Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const JavaTurboModule::InitParams ¶ms) +const ModuleClassConstructorTemplate = ({ + hasteModuleName, + methods, +}: $ReadOnly<{ + hasteModuleName: string, + methods: $ReadOnlyArray<{ + propertyName: string, + argCount: number, + }>, +}>) => { + return ` +${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { -::_PROPERTIES_MAP_:: +${methods + .map(({propertyName, argCount}) => { + return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`; + }) + .join('\n')} }`.trim(); +}; + +const ModuleLookupTemplate = ({ + moduleName, + hasteModuleName, +}: $ReadOnly<{moduleName: string, hasteModuleName: string}>) => { + return ` if (moduleName == "${moduleName}") { + return std::make_shared<${hasteModuleName}SpecJSI>(params); + }`; +}; -const template = ` +const FileTemplate = ({ + libraryName, + include, + modules, + moduleLookups, +}: $ReadOnly<{ + libraryName: string, + include: string, + modules: string, + moduleLookups: $ReadOnlyArray< + $ReadOnly<{ + hasteModuleName: string, + moduleName: string, + }>, + >, +}>) => { + return ` /** - * Copyright (c) Facebook, Inc. and its affiliates. + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -54,29 +107,44 @@ const template = ` * ${'@'}generated by codegen project: GenerateModuleJniCpp.js */ -#include ::_INCLUDE_:: +#include ${include} namespace facebook { namespace react { -::_MODULES_:: +${modules} + +std::shared_ptr ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { +${moduleLookups.map(ModuleLookupTemplate).join('\n')} + return nullptr; +} } // namespace react } // namespace facebook `; +}; function translateReturnTypeToKind( - typeAnnotation: FunctionTypeAnnotationReturn, -): string { - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { + nullableTypeAnnotation: Nullable, + resolveAlias: AliasResolver, +): JSReturnType { + const [typeAnnotation] = unwrapNullable( + nullableTypeAnnotation, + ); + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (realTypeAnnotation.name) { case 'RootTag': return 'NumberKind'; default: - (typeAnnotation.name: empty); + (realTypeAnnotation.name: empty); throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, + `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': @@ -86,62 +154,72 @@ function translateReturnTypeToKind( case 'BooleanTypeAnnotation': return 'BooleanKind'; case 'NumberTypeAnnotation': + return 'NumberKind'; case 'DoubleTypeAnnotation': + return 'NumberKind'; case 'FloatTypeAnnotation': + return 'NumberKind'; case 'Int32TypeAnnotation': return 'NumberKind'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'PromiseKind'; case 'GenericObjectTypeAnnotation': + return 'ObjectKind'; case 'ObjectTypeAnnotation': return 'ObjectKind'; case 'ArrayTypeAnnotation': return 'ArrayKind'; default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); + (realTypeAnnotation.type: empty); throw new Error( - `Unknown prop type for returning value, found: ${typeAnnotation.type}"`, + `Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`, ); } } +type Param = NamedShape>; + function translateParamTypeToJniType( - param: FunctionTypeAnnotationParam, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + param: Param, + resolveAlias: AliasResolver, ): string { - const {nullable, typeAnnotation} = param; + const {optional, typeAnnotation: nullableTypeAnnotation} = param; + const [ + typeAnnotation, + nullable, + ] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !optional && !nullable; - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': + case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': - return 'D'; + return !isRequired ? 'Ljava/lang/Double;' : 'D'; default: (realTypeAnnotation.name: empty); throw new Error( `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } - case 'VoidTypeAnnotation': - return 'V'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; case 'BooleanTypeAnnotation': - return nullable ? 'Ljava/lang/Boolean' : 'Z'; + return !isRequired ? 'Ljava/lang/Boolean;' : 'Z'; case 'NumberTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': - return nullable ? 'Ljava/lang/Double;' : 'D'; - case 'GenericPromiseTypeAnnotation': - return 'Lcom/facebook/react/bridge/Promise;'; + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'GenericObjectTypeAnnotation': + return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ArrayTypeAnnotation': @@ -149,6 +227,7 @@ function translateParamTypeToJniType( case 'FunctionTypeAnnotation': return 'Lcom/facebook/react/bridge/Callback;'; default: + (realTypeAnnotation.type: empty); throw new Error( `Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`, ); @@ -156,19 +235,25 @@ function translateParamTypeToJniType( } function translateReturnTypeToJniType( - typeAnnotation: FunctionTypeAnnotationReturn, + nullableTypeAnnotation: Nullable, + resolveAlias: AliasResolver, ): string { - const {nullable} = typeAnnotation; + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (realTypeAnnotation.name) { case 'RootTag': - return 'D'; + return nullable ? 'Ljava/lang/Double;' : 'D'; default: - (typeAnnotation.name: empty); + (realTypeAnnotation.name: empty); throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, + `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': @@ -176,158 +261,202 @@ function translateReturnTypeToJniType( case 'StringTypeAnnotation': return 'Ljava/lang/String;'; case 'BooleanTypeAnnotation': - return nullable ? 'Ljava/lang/Boolean' : 'Z'; + return nullable ? 'Ljava/lang/Boolean;' : 'Z'; case 'NumberTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'Lcom/facebook/react/bridge/Promise;'; case 'GenericObjectTypeAnnotation': + return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ArrayTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableArray;'; default: + (realTypeAnnotation.type: empty); throw new Error( - `Unknown prop type for method return type, found: ${typeAnnotation.type}"`, + `Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`, ); } } function translateMethodTypeToJniSignature( - property, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + property: NativeModulePropertyShape, + resolveAlias: AliasResolver, ): string { const {name, typeAnnotation} = property; - const {returnTypeAnnotation} = typeAnnotation; + let [ + {returnTypeAnnotation, params}, + ] = unwrapNullable(typeAnnotation); - const params = [...typeAnnotation.params]; + params = [...params]; let processedReturnTypeAnnotation = returnTypeAnnotation; - const isPromiseReturn = - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation'; + const isPromiseReturn = returnTypeAnnotation.type === 'PromiseTypeAnnotation'; if (isPromiseReturn) { processedReturnTypeAnnotation = { - nullable: false, type: 'VoidTypeAnnotation', }; } const argsSignatureParts = params.map(t => { - return translateParamTypeToJniType(t, aliases); + return translateParamTypeToJniType(t, resolveAlias); }); if (isPromiseReturn) { // Additional promise arg for this case. - argsSignatureParts.push(translateReturnTypeToJniType(returnTypeAnnotation)); + argsSignatureParts.push( + translateReturnTypeToJniType(returnTypeAnnotation, resolveAlias), + ); } const argsSignature = argsSignatureParts.join(''); const returnSignature = name === 'getConstants' ? 'Ljava/util/Map;' - : translateReturnTypeToJniType(processedReturnTypeAnnotation); + : translateReturnTypeToJniType( + processedReturnTypeAnnotation, + resolveAlias, + ); return `(${argsSignature})${returnSignature}`; } function translateMethodForImplementation( - property, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + hasteModuleName: string, + property: NativeModulePropertyShape, + resolveAlias: AliasResolver, ): string { - const {returnTypeAnnotation} = property.typeAnnotation; - - const numberOfParams = - property.typeAnnotation.params.length + - (returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' ? 1 : 0); - const translatedArguments = property.typeAnnotation.params - .map(param => param.name) - .concat( - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' - ? ['promise'] - : [], - ) - .slice(1) - .join(':') - .concat(':'); + const [ + propertyTypeAnnotation, + ] = unwrapNullable( + property.typeAnnotation, + ); + const {returnTypeAnnotation} = propertyTypeAnnotation; + if ( property.name === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 ) { return ''; } - return propertyTemplate - .replace(/::_KIND_::/g, translateReturnTypeToKind(returnTypeAnnotation)) - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace( - /::_ARGS_::/g, - numberOfParams === 0 - ? '' - : (numberOfParams === 1 ? '' : ':') + translatedArguments, - ) - .replace( - /::_SIGNATURE_::/g, - translateMethodTypeToJniSignature(property, aliases), - ); + + return HostFunctionTemplate({ + hasteModuleName, + propertyName: property.name, + jniSignature: translateMethodTypeToJniSignature(property, resolveAlias), + jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), + }); } module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { - const nativeModules: {[name: string]: NativeModuleShape, ...} = Object.keys( - schema.modules, - ) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } + const nativeModules = getModules(schema); - return modules; + const modules = Object.keys(nativeModules) + .filter(hasteModuleName => { + const module = nativeModules[hasteModuleName]; + return !( + module.excludedPlatforms != null && + module.excludedPlatforms.includes('android') + ); }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); + .sort() + .map(hasteModuleName => { + const { + aliases, + spec: {properties}, + } = nativeModules[hasteModuleName]; + const resolveAlias = createAliasResolver(aliases); - const modules = Object.keys(nativeModules) - .map(name => { - const {aliases, properties} = nativeModules[name]; const translatedMethods = properties - .map(property => translateMethodForImplementation(property, aliases)) - .join('\n'); - return moduleTemplate - .replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) - .replace( - '::_PROPERTIES_MAP_::', - properties - .map( - ({ - name: propertyName, - typeAnnotation: {params, returnTypeAnnotation}, - }) => + .map(property => + translateMethodForImplementation( + hasteModuleName, + property, + resolveAlias, + ), + ) + .join('\n\n'); + + return ( + translatedMethods + + '\n\n' + + ModuleClassConstructorTemplate({ + hasteModuleName, + methods: properties + .map(({name: propertyName, typeAnnotation}) => { + const [ + {returnTypeAnnotation, params}, + ] = unwrapNullable( + typeAnnotation, + ); + + if ( propertyName === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 - ? '' - : propertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()), - ) - .join('\n'), - ) - .replace(/::_MODULE_NAME_::/g, name); + ) { + return null; + } + + return { + propertyName, + argCount: params.length, + }; + }) + .filter(Boolean), + }) + ); }) .join('\n'); - const fileName = `${moduleSpecName}-generated.cpp`; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName) - .replace(/::_INCLUDE_::/g, `"${moduleSpecName}.h"`); - return new Map([[fileName, replacedTemplate]]); + const moduleLookups = Object.keys(nativeModules) + .filter(hasteModuleName => { + const module = nativeModules[hasteModuleName]; + return !( + module.excludedPlatforms != null && + module.excludedPlatforms.includes('android') + ); + }) + .sort((a, b) => { + const moduleA = nativeModules[a]; + const moduleB = nativeModules[b]; + const nameA = moduleA.moduleNames[0]; + const nameB = moduleB.moduleNames[0]; + if (nameA < nameB) { + return -1; + } else if (nameA > nameB) { + return 1; + } + return 0; + }) + .flatMap<{moduleName: string, hasteModuleName: string}>( + (hasteModuleName: string) => { + const {moduleNames} = nativeModules[hasteModuleName]; + return moduleNames.map(moduleName => ({ + moduleName, + hasteModuleName, + })); + }, + ); + + const fileName = `${libraryName}-generated.cpp`; + const replacedTemplate = FileTemplate({ + modules: modules, + libraryName: libraryName.replace(/-/g, '_'), + moduleLookups, + include: `"${libraryName}.h"`, + }); + return new Map([[`jni/${fileName}`, replacedTemplate]]); }, }; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 8b27ad3cb39b7f..43aee3cb585b63 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -14,18 +14,28 @@ import type {SchemaType} from '../../CodegenSchema'; type FilesOutput = Map; -const moduleTemplate = `/** - * JNI C++ class for module '::_MODULE_NAME_::' +const {getModules} = require('./Utils'); + +const ModuleClassDeclarationTemplate = ({ + hasteModuleName, +}: $ReadOnly<{hasteModuleName: string}>) => { + return `/** + * JNI C++ class for module '${hasteModuleName}' */ -class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public JavaTurboModule { +class JSI_EXPORT ${hasteModuleName}SpecJSI : public JavaTurboModule { public: - Native::_MODULE_NAME_::SpecJSI(const JavaTurboModule::InitParams ¶ms); + ${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams ¶ms); }; `; +}; -const template = ` +const HeaderFileTemplate = ({ + modules, + libraryName, +}: $ReadOnly<{modules: string, libraryName: string}>) => { + return ` /** - * Copyright (c) Facebook, Inc. and its affiliates. + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -33,46 +43,88 @@ const template = ` * ${'@'}generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { -::_MODULES_:: +${modules} + +std::shared_ptr ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); } // namespace react } // namespace facebook `; +}; + +// Note: this Android.mk template includes dependencies for both NativeModule and components. +const AndroidMkTemplate = ({libraryName}: $ReadOnly<{libraryName: string}>) => { + return `# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_${libraryName} + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/${libraryName}/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/${libraryName} + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\ + -DLOG_TAG=\\"ReactNative\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) +`; +}; module.exports = { generate( libraryName: string, schema: SchemaType, - moduleSpecName: string, + packageName?: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .sort() - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); - + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) - .map(name => moduleTemplate.replace(/::_MODULE_NAME_::/g, name)) + .filter(hasteModuleName => { + const module = nativeModules[hasteModuleName]; + return !( + module.excludedPlatforms != null && + module.excludedPlatforms.includes('android') + ); + }) + .sort() + .map(hasteModuleName => ModuleClassDeclarationTemplate({hasteModuleName})) .join('\n'); - const fileName = `${moduleSpecName}.h`; - const replacedTemplate = template.replace(/::_MODULES_::/g, modules); - - return new Map([[fileName, replacedTemplate]]); + const fileName = `${libraryName}.h`; + const replacedTemplate = HeaderFileTemplate({ + modules: modules, + libraryName: libraryName.replace(/-/g, '_'), + }); + return new Map([ + [`jni/${fileName}`, replacedTemplate], + [ + 'jni/Android.mk', + AndroidMkTemplate({ + libraryName: `${libraryName.toLowerCase()}`, + }), + ], + ]); }, }; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js deleted file mode 100644 index 8b60d07e127429..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js +++ /dev/null @@ -1,320 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type {SchemaType, NativeModuleShape} from '../../CodegenSchema'; - -const {capitalizeFirstLetter} = require('./ObjCppUtils/GenerateStructs'); -const {flatObjects} = require('./ObjCppUtils/Utils'); -const {getTypeAliasTypeAnnotation} = require('./Utils'); - -type FilesOutput = Map; - -const propertyHeaderTemplate = - ' static facebook::jsi::Value __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; - -const propertyCastTemplate = `static_cast(turboModule) - .invokeObjCMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", @selector(::_PROPERTY_NAME_::::_ARGS_::), args, count);`; - -const propertyTemplate = ` -${propertyHeaderTemplate} - return ${propertyCastTemplate} - }`; - -const propertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; - -const moduleTemplate = ` - ::_TURBOMODULE_METHOD_INVOKERS_:: - - Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - ::_PROPERTIES_MAP_::::_CONVERSION_SELECTORS_:: - }`.trim(); - -const getterTemplate = ` -@implementation RCTCxxConvert (Native::_MODULE_NAME_::_::_GETTER_NAME_::) -+ (RCTManagedPointer *)JS_Native::_MODULE_NAME_::_::_GETTER_NAME_:::(id)json -{ - return facebook::react::managedPointer(json); -} -@end -`; - -const argConvertionTemplate = - '\n setMethodArgConversionSelector(@"::_ARG_NAME_::", ::_ARG_NUMBER_::, @"JS_Native::_MODULE_NAME_::_::_SELECTOR_NAME_:::");'; - -const template = ` -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * ${'@'}generated by codegen project: GenerateModuleMm.js - */ - -#include <::_INCLUDE_::> -#import - -::_GETTERS_:: -namespace facebook { - namespace react { -::_MODULES_:: - } // namespace react -} // namespace facebook -`; - -function translateReturnTypeToKind(typeAnnotation): string { - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { - case 'RootTag': - return 'NumberKind'; - default: - (typeAnnotation.name: empty); - throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, - ); - } - case 'VoidTypeAnnotation': - return 'VoidKind'; - case 'StringTypeAnnotation': - return 'StringKind'; - case 'BooleanTypeAnnotation': - return 'BooleanKind'; - case 'NumberTypeAnnotation': - case 'DoubleTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return 'NumberKind'; - case 'GenericPromiseTypeAnnotation': - return 'PromiseKind'; - case 'GenericObjectTypeAnnotation': - case 'ObjectTypeAnnotation': - return 'ObjectKind'; - case 'ArrayTypeAnnotation': - return 'ArrayKind'; - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error( - `Unknown prop type for returning value, found: ${typeAnnotation.type}"`, - ); - } -} - -function translateMethodForImplementation(property): string { - const {returnTypeAnnotation} = property.typeAnnotation; - - const numberOfParams = - property.typeAnnotation.params.length + - (returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' ? 2 : 0); - const translatedArguments = property.typeAnnotation.params - .map(param => param.name) - .concat( - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' - ? ['resolve', 'reject'] - : [], - ) - .slice(1) - .join(':') - .concat(':'); - if ( - property.name === 'getConstants' && - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && - returnTypeAnnotation.properties.length === 0 - ) { - return ''; - } - return propertyTemplate - .replace(/::_KIND_::/g, translateReturnTypeToKind(returnTypeAnnotation)) - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace( - /::_ARGS_::/g, - numberOfParams === 0 - ? '' - : (numberOfParams === 1 ? '' : ':') + translatedArguments, - ); -} - -module.exports = { - generate( - libraryName: string, - schema: SchemaType, - moduleSpecName: string, - ): FilesOutput { - const nativeModules: {[name: string]: NativeModuleShape, ...} = Object.keys( - schema.modules, - ) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); - - const gettersImplementations = Object.keys(nativeModules) - .reduce((acc, moduleName: string) => { - const module: NativeModuleShape = nativeModules[moduleName]; - return acc.concat( - flatObjects( - module.properties - .reduce((moduleAcc, property) => { - const {returnTypeAnnotation} = property.typeAnnotation; - if (returnTypeAnnotation.type === 'ObjectTypeAnnotation') { - const {properties} = returnTypeAnnotation; - if (properties) { - moduleAcc.push({ - name: - 'Spec' + - capitalizeFirstLetter(property.name) + - 'ReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: properties, - }, - }); - } - } - if (property.typeAnnotation.params) { - return moduleAcc.concat( - property.typeAnnotation.params - .map(param => { - if ( - param.typeAnnotation.type === 'ObjectTypeAnnotation' - ) { - const {properties} = param.typeAnnotation; - if (properties) { - return { - name: - 'Spec' + - capitalizeFirstLetter(property.name) + - capitalizeFirstLetter(param.name), - object: { - type: 'ObjectTypeAnnotation', - properties: properties, - }, - }; - } - } - }) - .filter(Boolean), - ); - } - return moduleAcc; - }, []) - .concat( - Object.keys(module.aliases).map(aliasName => { - const alias = getTypeAliasTypeAnnotation( - aliasName, - module.aliases, - ); - return { - name: aliasName, - object: {type: alias.type, properties: alias.properties}, - }; - }), - ), - false, - module.aliases, - ) - .map(object => - getterTemplate - .replace(/::_GETTER_NAME_::/g, object.name) - .replace(/::_MODULE_NAME_::/g, moduleName), - ) - .join('\n'), - ); - }, []) - .join('\n'); - - const modules = Object.keys(nativeModules) - .map(name => { - const {aliases, properties} = nativeModules[name]; - const translatedMethods = properties - .map(property => translateMethodForImplementation(property)) - .join('\n'); - return moduleTemplate - .replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) - .replace( - '::_PROPERTIES_MAP_::', - properties - .map( - ({ - name: propertyName, - typeAnnotation: {params, returnTypeAnnotation}, - }) => - propertyName === 'getConstants' && - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && - returnTypeAnnotation.properties.length === 0 - ? '' - : propertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()), - ) - .join('\n'), - ) - .replace( - '::_CONVERSION_SELECTORS_::', - properties - .map(({name: propertyName, typeAnnotation: {params}}) => - params - .map((param, index) => { - const typeAnnotation = - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation( - param.typeAnnotation.name, - aliases, - ) - : param.typeAnnotation; - const selectorName = - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? param.typeAnnotation.name - : 'Spec' + - capitalizeFirstLetter(propertyName) + - capitalizeFirstLetter(param.name); - - if ( - typeAnnotation.type === 'ObjectTypeAnnotation' && - typeAnnotation.properties - ) { - return argConvertionTemplate - .replace('::_SELECTOR_NAME_::', selectorName) - .replace('::_ARG_NUMBER_::', index.toString()) - .replace('::_ARG_NAME_::', propertyName); - } - - return ''; - }) - .join(''), - ) - .join(''), - ) - .replace(/::_MODULE_NAME_::/g, name); - }) - .join('\n'); - - const fileName = `${moduleSpecName}-generated.mm`; - const replacedTemplate = template - .replace(/::_GETTERS_::/g, gettersImplementations) - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName) - .replace(/::_INCLUDE_::/g, `${moduleSpecName}/${moduleSpecName}.h`); - return new Map([[fileName, replacedTemplate]]); - }, -}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js new file mode 100644 index 00000000000000..a4377a64e4e40e --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js @@ -0,0 +1,199 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type { + Nullable, + NativeModuleObjectTypeAnnotation, + NativeModuleStringTypeAnnotation, + NativeModuleNumberTypeAnnotation, + NativeModuleInt32TypeAnnotation, + NativeModuleDoubleTypeAnnotation, + NativeModuleFloatTypeAnnotation, + NativeModuleBooleanTypeAnnotation, + NativeModuleGenericObjectTypeAnnotation, + ReservedTypeAnnotation, + NativeModuleTypeAliasTypeAnnotation, + NativeModuleArrayTypeAnnotation, + NativeModuleBaseTypeAnnotation, +} from '../../../CodegenSchema'; + +import type {AliasResolver} from '../Utils'; + +const {capitalize} = require('../../Utils'); +const { + unwrapNullable, + wrapNullable, +} = require('../../../parsers/flow/modules/utils'); + +type StructContext = 'CONSTANTS' | 'REGULAR'; + +export type RegularStruct = $ReadOnly<{ + context: 'REGULAR', + name: string, + properties: $ReadOnlyArray, +}>; + +export type ConstantsStruct = $ReadOnly<{ + context: 'CONSTANTS', + name: string, + properties: $ReadOnlyArray, +}>; + +export type Struct = RegularStruct | ConstantsStruct; + +export type StructProperty = $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: Nullable, +}>; + +export type StructTypeAnnotation = + | NativeModuleStringTypeAnnotation + | NativeModuleNumberTypeAnnotation + | NativeModuleInt32TypeAnnotation + | NativeModuleDoubleTypeAnnotation + | NativeModuleFloatTypeAnnotation + | NativeModuleBooleanTypeAnnotation + | NativeModuleGenericObjectTypeAnnotation + | ReservedTypeAnnotation + | NativeModuleTypeAliasTypeAnnotation + | NativeModuleArrayTypeAnnotation>; + +class StructCollector { + _structs: Map = new Map(); + + process( + structName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + nullableTypeAnnotation: Nullable, + ): Nullable { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + switch (typeAnnotation.type) { + case 'ObjectTypeAnnotation': { + this._insertStruct( + structName, + structContext, + resolveAlias, + typeAnnotation, + ); + return wrapNullable(nullable, { + type: 'TypeAliasTypeAnnotation', + name: structName, + }); + } + case 'ArrayTypeAnnotation': { + if (typeAnnotation.elementType == null) { + return wrapNullable(nullable, { + type: 'ArrayTypeAnnotation', + }); + } + + return wrapNullable(nullable, { + type: 'ArrayTypeAnnotation', + elementType: this.process( + structName + 'Element', + structContext, + resolveAlias, + typeAnnotation.elementType, + ), + }); + } + case 'TypeAliasTypeAnnotation': { + this._insertAlias(typeAnnotation.name, structContext, resolveAlias); + return wrapNullable(nullable, typeAnnotation); + } + default: { + return wrapNullable(nullable, typeAnnotation); + } + } + } + + _insertAlias( + aliasName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + ): void { + const usedStruct = this._structs.get(aliasName); + if (usedStruct == null) { + this._insertStruct( + aliasName, + structContext, + resolveAlias, + resolveAlias(aliasName), + ); + } else if (usedStruct.context !== structContext) { + throw new Error( + `Tried to use alias '${aliasName}' in a getConstants() return type and inside a regular struct.`, + ); + } + } + + _insertStruct( + structName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + objectTypeAnnotation: NativeModuleObjectTypeAnnotation, + ): void { + const properties = objectTypeAnnotation.properties.map< + $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: Nullable, + }>, + >(property => { + const propertyStructName = structName + capitalize(property.name); + + return { + ...property, + typeAnnotation: this.process( + propertyStructName, + structContext, + resolveAlias, + property.typeAnnotation, + ), + }; + }); + + switch (structContext) { + case 'REGULAR': + this._structs.set(structName, { + name: structName, + context: 'REGULAR', + properties: properties, + }); + break; + case 'CONSTANTS': + this._structs.set(structName, { + name: structName, + context: 'CONSTANTS', + properties: properties, + }); + break; + default: + (structContext: empty); + throw new Error(`Detected an invalid struct context: ${structContext}`); + } + } + + getAllStructs(): $ReadOnlyArray { + return [...this._structs.values()]; + } + + getStruct(name: string): ?Struct { + return this._structs.get(name); + } +} + +module.exports = { + StructCollector, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js new file mode 100644 index 00000000000000..ffbfea1b8cc701 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {StructProperty} from './StructCollector'; + +function getSafePropertyName(property: StructProperty): string { + if (property.name === 'id') { + return `${property.name}_`; + } + return property.name; +} + +function getNamespacedStructName( + hasteModuleName: string, + structName: string, +): string { + return `JS::${hasteModuleName}::${structName}`; +} + +module.exports = { + getSafePropertyName, + getNamespacedStructName, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js new file mode 100644 index 00000000000000..d11a5a8c23d88c --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js @@ -0,0 +1,266 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +const {getSafePropertyName, getNamespacedStructName} = require('../Utils'); +const {capitalize} = require('../../../Utils'); + +import type {Nullable} from '../../../../CodegenSchema'; +import type {StructTypeAnnotation, ConstantsStruct} from '../StructCollector'; +import type {StructSerilizationOutput} from './serializeStruct'; + +const {unwrapNullable} = require('../../../../parsers/flow/modules/utils'); + +const StructTemplate = ({ + hasteModuleName, + structName, + builderInputProps, +}: $ReadOnly<{ + hasteModuleName: string, + structName: string, + builderInputProps: string, +}>) => `namespace JS { + namespace ${hasteModuleName} { + struct ${structName} { + + struct Builder { + struct Input { + ${builderInputProps} + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ${structName} */ + Builder(${structName} i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ${structName} fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ${structName}(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +}`; + +const MethodTemplate = ({ + hasteModuleName, + structName, + properties, +}: $ReadOnly<{ + hasteModuleName: string, + structName: string, + properties: string, +}>) => `inline JS::${hasteModuleName}::${structName}::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; +${properties} + return d; +}) {} +inline JS::${hasteModuleName}::${structName}::Builder::Builder(${structName} i) : _factory(^{ + return i.unsafeRawValue(); +}) {}`; + +function toObjCType( + hasteModuleName: string, + nullableTypeAnnotation: Nullable, + isOptional: boolean = false, +): string { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !nullable && !isOptional; + const wrapFollyOptional = (type: string) => { + return isRequired ? type : `folly::Optional<${type}>`; + }; + + switch (typeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapFollyOptional('double'); + default: + (typeAnnotation.name: empty); + throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); + } + case 'StringTypeAnnotation': + return 'NSString *'; + case 'NumberTypeAnnotation': + return wrapFollyOptional('double'); + case 'FloatTypeAnnotation': + return wrapFollyOptional('double'); + case 'Int32TypeAnnotation': + return wrapFollyOptional('double'); + case 'DoubleTypeAnnotation': + return wrapFollyOptional('double'); + case 'BooleanTypeAnnotation': + return wrapFollyOptional('bool'); + case 'GenericObjectTypeAnnotation': + return isRequired ? 'id ' : 'id _Nullable '; + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return isRequired ? 'id ' : 'id _Nullable '; + } + + return wrapFollyOptional( + `std::vector<${toObjCType( + hasteModuleName, + typeAnnotation.elementType, + )}>`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + hasteModuleName, + structName, + ); + return wrapFollyOptional(`${namespacedStructName}::Builder`); + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } +} + +function toObjCValue( + hasteModuleName: string, + nullableTypeAnnotation: Nullable, + value: string, + depth: number, + isOptional: boolean = false, +): string { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !nullable && !isOptional; + + function wrapPrimitive(type: string) { + return !isRequired + ? `${value}.hasValue() ? @((${type})${value}.value()) : nil` + : `@(${value})`; + } + + switch (typeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapPrimitive('double'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } + case 'StringTypeAnnotation': + return value; + case 'NumberTypeAnnotation': + return wrapPrimitive('double'); + case 'FloatTypeAnnotation': + return wrapPrimitive('double'); + case 'Int32TypeAnnotation': + return wrapPrimitive('double'); + case 'DoubleTypeAnnotation': + return wrapPrimitive('double'); + case 'BooleanTypeAnnotation': + return wrapPrimitive('BOOL'); + case 'GenericObjectTypeAnnotation': + return value; + case 'ArrayTypeAnnotation': + const {elementType} = typeAnnotation; + if (elementType == null) { + return value; + } + + const localVarName = `el${'_'.repeat(depth + 1)}`; + const elementObjCType = toObjCType(hasteModuleName, elementType); + const elementObjCValue = toObjCValue( + hasteModuleName, + elementType, + localVarName, + depth + 1, + ); + + const RCTConvertVecToArray = transformer => { + return `RCTConvert${ + !isRequired ? 'Optional' : '' + }VecToArray(${value}, ${transformer})`; + }; + + return RCTConvertVecToArray( + `^id(${elementObjCType} ${localVarName}) { return ${elementObjCValue}; }`, + ); + case 'TypeAliasTypeAnnotation': + return !isRequired + ? `${value}.hasValue() ? ${value}.value().buildUnsafeRawValue() : nil` + : `${value}.buildUnsafeRawValue()`; + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC value: ${typeAnnotation.type}"`, + ); + } +} + +function serializeConstantsStruct( + hasteModuleName: string, + struct: ConstantsStruct, +): StructSerilizationOutput { + const declaration = StructTemplate({ + hasteModuleName, + structName: struct.name, + builderInputProps: struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const safePropName = getSafePropertyName(property); + const objCType = toObjCType(hasteModuleName, typeAnnotation, optional); + + if (!optional) { + return `RCTRequired<${objCType}> ${safePropName};`; + } + + const space = ' '.repeat(objCType.endsWith('*') ? 0 : 1); + return `${objCType}${space}${safePropName};`; + }) + .join('\n '), + }); + + const methods = MethodTemplate({ + hasteModuleName, + structName: struct.name, + properties: struct.properties + .map(property => { + const {typeAnnotation, optional, name: propName} = property; + const safePropName = getSafePropertyName(property); + const objCValue = toObjCValue( + hasteModuleName, + typeAnnotation, + safePropName, + 0, + optional, + ); + + let varDecl = `auto ${safePropName} = i.${safePropName}`; + if (!optional) { + varDecl += '.get()'; + } + + const assignment = `d[@"${propName}"] = ` + objCValue; + return ` ${varDecl};\n ${assignment};`; + }) + .join('\n'), + }); + + return {declaration, methods}; +} + +module.exports = { + serializeConstantsStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js new file mode 100644 index 00000000000000..90b4c7f114c10a --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js @@ -0,0 +1,256 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +const {getSafePropertyName, getNamespacedStructName} = require('../Utils'); +const {capitalize} = require('../../../Utils'); + +import type {Nullable} from '../../../../CodegenSchema'; +import type {StructTypeAnnotation, RegularStruct} from '../StructCollector'; +import type {StructSerilizationOutput} from './serializeStruct'; + +const {unwrapNullable} = require('../../../../parsers/flow/modules/utils'); + +const StructTemplate = ({ + hasteModuleName, + structName, + structProperties, +}: $ReadOnly<{ + hasteModuleName: string, + structName: string, + structProperties: string, +}>) => `namespace JS { + namespace ${hasteModuleName} { + struct ${structName} { + ${structProperties} + + ${structName}(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (${hasteModuleName}_${structName}) ++ (RCTManagedPointer *)JS_${hasteModuleName}_${structName}:(id)json; +@end`; + +const MethodTemplate = ({ + returnType, + returnValue, + hasteModuleName, + structName, + propertyName, + safePropertyName, +}: $ReadOnly<{ + returnType: string, + returnValue: string, + hasteModuleName: string, + structName: string, + propertyName: string, + safePropertyName: string, +}>) => `inline ${returnType}JS::${hasteModuleName}::${structName}::${safePropertyName}() const +{ + id const p = _v[@"${propertyName}"]; + return ${returnValue}; +}`; + +function toObjCType( + hasteModuleName: string, + nullableTypeAnnotation: Nullable, + isOptional: boolean = false, +): string { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !nullable && !isOptional; + const wrapFollyOptional = (type: string) => { + return isRequired ? type : `folly::Optional<${type}>`; + }; + + switch (typeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapFollyOptional('double'); + default: + (typeAnnotation.name: empty); + throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); + } + case 'StringTypeAnnotation': + return 'NSString *'; + case 'NumberTypeAnnotation': + return wrapFollyOptional('double'); + case 'FloatTypeAnnotation': + return wrapFollyOptional('double'); + case 'Int32TypeAnnotation': + return wrapFollyOptional('double'); + case 'DoubleTypeAnnotation': + return wrapFollyOptional('double'); + case 'BooleanTypeAnnotation': + return wrapFollyOptional('bool'); + case 'GenericObjectTypeAnnotation': + return isRequired ? 'id ' : 'id _Nullable'; + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return isRequired ? 'id ' : 'id _Nullable'; + } + return wrapFollyOptional( + `facebook::react::LazyVector<${toObjCType( + hasteModuleName, + typeAnnotation.elementType, + )}>`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + hasteModuleName, + structName, + ); + return wrapFollyOptional(namespacedStructName); + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } +} + +function toObjCValue( + hasteModuleName: string, + nullableTypeAnnotation: Nullable, + value: string, + depth: number, + isOptional: boolean = false, +): string { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + const isRequired = !nullable && !isOptional; + const RCTBridgingTo = (type: string, arg?: string) => { + const args = [value, arg].filter(Boolean).join(', '); + return isRequired + ? `RCTBridgingTo${type}(${args})` + : `RCTBridgingToOptional${type}(${args})`; + }; + + switch (typeAnnotation.type) { + case 'ReservedTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return RCTBridgingTo('Double'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } + case 'StringTypeAnnotation': + return RCTBridgingTo('String'); + case 'NumberTypeAnnotation': + return RCTBridgingTo('Double'); + case 'FloatTypeAnnotation': + return RCTBridgingTo('Double'); + case 'Int32TypeAnnotation': + return RCTBridgingTo('Double'); + case 'DoubleTypeAnnotation': + return RCTBridgingTo('Double'); + case 'BooleanTypeAnnotation': + return RCTBridgingTo('Bool'); + case 'GenericObjectTypeAnnotation': + return value; + case 'ArrayTypeAnnotation': + const {elementType} = typeAnnotation; + if (elementType == null) { + return value; + } + + const localVarName = `itemValue_${depth}`; + const elementObjCType = toObjCType(hasteModuleName, elementType); + const elementObjCValue = toObjCValue( + hasteModuleName, + elementType, + localVarName, + depth + 1, + ); + + return RCTBridgingTo( + 'Vec', + `^${elementObjCType}(id ${localVarName}) { return ${elementObjCValue}; }`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + hasteModuleName, + structName, + ); + + return !isRequired + ? `(${value} == nil ? folly::none : folly::make_optional(${namespacedStructName}(${value})))` + : `${namespacedStructName}(${value})`; + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC value: ${typeAnnotation.type}"`, + ); + } +} + +function serializeRegularStruct( + hasteModuleName: string, + struct: RegularStruct, +): StructSerilizationOutput { + const declaration = StructTemplate({ + hasteModuleName: hasteModuleName, + structName: struct.name, + structProperties: struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const safePropName = getSafePropertyName(property); + const returnType = toObjCType( + hasteModuleName, + typeAnnotation, + optional, + ); + + const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1); + return `${returnType}${padding}${safePropName}() const;`; + }) + .join('\n '), + }); + + const methods = struct.properties + .map(property => { + const {typeAnnotation, optional, name: propName} = property; + const safePropertyName = getSafePropertyName(property); + const returnType = toObjCType(hasteModuleName, typeAnnotation, optional); + const returnValue = toObjCValue( + hasteModuleName, + typeAnnotation, + 'p', + 0, + optional, + ); + + const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1); + return MethodTemplate({ + hasteModuleName, + structName: struct.name, + returnType: returnType + padding, + returnValue: returnValue, + propertyName: propName, + safePropertyName, + }); + }) + .join('\n'); + + return {methods, declaration}; +} + +module.exports = { + serializeRegularStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js new file mode 100644 index 00000000000000..170ac77c8fe863 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {Struct} from '../StructCollector'; + +const {serializeConstantsStruct} = require('./serializeConstantsStruct'); +const {serializeRegularStruct} = require('./serializeRegularStruct'); + +export type StructSerilizationOutput = $ReadOnly<{ + methods: string, + declaration: string, +}>; + +function serializeStruct( + hasteModuleName: string, + struct: Struct, +): StructSerilizationOutput { + if (struct.context === 'REGULAR') { + return serializeRegularStruct(hasteModuleName, struct); + } + return serializeConstantsStruct(hasteModuleName, struct); +} + +module.exports = { + serializeStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js new file mode 100644 index 00000000000000..eae698f52ace35 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js @@ -0,0 +1,210 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {SchemaType} from '../../../CodegenSchema'; +import type {MethodSerializationOutput} from './serializeMethod'; + +const {createAliasResolver, getModules} = require('../Utils'); + +const {StructCollector} = require('./StructCollector'); +const {serializeStruct} = require('./header/serializeStruct'); +const {serializeMethod} = require('./serializeMethod'); +const {serializeModuleSource} = require('./source/serializeModule'); + +type FilesOutput = Map; + +const ModuleDeclarationTemplate = ({ + hasteModuleName, + structDeclarations, + protocolMethods, +}: $ReadOnly<{ + hasteModuleName: string, + structDeclarations: string, + protocolMethods: string, +}>) => `${structDeclarations} +@protocol ${hasteModuleName}Spec + +${protocolMethods} + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module '${hasteModuleName}' + */ + class JSI_EXPORT ${hasteModuleName}SpecJSI : public ObjCTurboModule { + public: + ${hasteModuleName}SpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook`; + +const HeaderFileTemplate = ({ + moduleDeclarations, + structInlineMethods, +}: $ReadOnly<{ + moduleDeclarations: string, + structInlineMethods: string, +}>) => `/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +${moduleDeclarations} +${structInlineMethods} +`; + +const SourceFileTemplate = ({ + headerFileName, + moduleImplementations, +}: $ReadOnly<{ + headerFileName: string, + moduleImplementations: string, +}>) => `/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#import "${headerFileName}" + +${moduleImplementations} +`; + +module.exports = { + generate( + libraryName: string, + schema: SchemaType, + packageName?: string, + ): FilesOutput { + const nativeModules = getModules(schema); + + const moduleDeclarations: Array = []; + const structInlineMethods: Array = []; + const moduleImplementations: Array = []; + + const hasteModuleNames: Array = Object.keys(nativeModules).sort(); + for (const hasteModuleName of hasteModuleNames) { + const { + aliases, + excludedPlatforms, + spec: {properties}, + } = nativeModules[hasteModuleName]; + if (excludedPlatforms != null && excludedPlatforms.includes('iOS')) { + continue; + } + const resolveAlias = createAliasResolver(aliases); + const structCollector = new StructCollector(); + + const methodSerializations: Array = []; + const serializeProperty = property => { + methodSerializations.push( + ...serializeMethod( + hasteModuleName, + property, + structCollector, + resolveAlias, + ), + ); + }; + + /** + * Note: As we serialize NativeModule methods, we insert structs into + * StructCollector, as we encounter them. + */ + properties + .filter(property => property.name !== 'getConstants') + .forEach(serializeProperty); + properties + .filter(property => property.name === 'getConstants') + .forEach(serializeProperty); + + const generatedStructs = structCollector.getAllStructs(); + const structStrs = []; + const methodStrs = []; + + for (const struct of generatedStructs) { + const {methods, declaration} = serializeStruct(hasteModuleName, struct); + structStrs.push(declaration); + methodStrs.push(methods); + } + + moduleDeclarations.push( + ModuleDeclarationTemplate({ + hasteModuleName: hasteModuleName, + structDeclarations: structStrs.join('\n'), + protocolMethods: methodSerializations + .map(({protocolMethod}) => protocolMethod) + .join('\n'), + }), + ); + + structInlineMethods.push(methodStrs.join('\n')); + + moduleImplementations.push( + serializeModuleSource( + hasteModuleName, + generatedStructs, + methodSerializations.filter( + ({selector}) => selector !== '@selector(constantsToExport)', + ), + ), + ); + } + + const headerFileName = `${libraryName}.h`; + const headerFile = HeaderFileTemplate({ + moduleDeclarations: moduleDeclarations.join('\n'), + structInlineMethods: structInlineMethods.join('\n'), + }); + + const sourceFileName = `${libraryName}-generated.mm`; + const sourceFile = SourceFileTemplate({ + headerFileName, + moduleImplementations: moduleImplementations.join('\n'), + }); + + return new Map([ + [headerFileName, headerFile], + [sourceFileName, sourceFile], + ]); + }, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js new file mode 100644 index 00000000000000..4d948b6f6ece30 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js @@ -0,0 +1,447 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type { + Nullable, + NamedShape, + NativeModuleParamTypeAnnotation, + NativeModuleReturnTypeAnnotation, + NativeModulePropertyShape, +} from '../../../CodegenSchema'; + +import type {AliasResolver} from '../Utils'; + +const invariant = require('invariant'); +const {StructCollector} = require('./StructCollector'); +const {getNamespacedStructName} = require('./Utils'); +const {capitalize} = require('../../Utils'); +const { + wrapNullable, + unwrapNullable, +} = require('../../../parsers/flow/modules/utils'); + +const ProtocolMethodTemplate = ({ + returnObjCType, + methodName, + params, +}: $ReadOnly<{ + returnObjCType: string, + methodName: string, + params: string, +}>) => `- (${returnObjCType})${methodName}${params};`; + +export type StructParameterRecord = $ReadOnly<{ + paramIndex: number, + structName: string, +}>; + +type ReturnJSType = + | 'VoidKind' + | 'BooleanKind' + | 'PromiseKind' + | 'ObjectKind' + | 'ArrayKind' + | 'NumberKind' + | 'StringKind'; + +export type MethodSerializationOutput = $ReadOnly<{ + methodName: string, + protocolMethod: string, + selector: string, + structParamRecords: $ReadOnlyArray, + returnJSType: ReturnJSType, + argCount: number, +}>; + +function serializeMethod( + hasteModuleName: string, + property: NativeModulePropertyShape, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnlyArray { + const {name: methodName, typeAnnotation: nullableTypeAnnotation} = property; + const [propertyTypeAnnotation] = unwrapNullable(nullableTypeAnnotation); + const {params} = propertyTypeAnnotation; + + if (methodName === 'getConstants') { + return serializeConstantsProtocolMethods( + hasteModuleName, + property, + structCollector, + resolveAlias, + ); + } + + const methodParams: Array<{paramName: string, objCType: string}> = []; + const structParamRecords: Array = []; + + params.forEach((param, index) => { + const structName = getParamStructName(methodName, param); + const {objCType, isStruct} = getParamObjCType( + hasteModuleName, + methodName, + param, + structName, + structCollector, + resolveAlias, + ); + + methodParams.push({paramName: param.name, objCType}); + + if (isStruct) { + structParamRecords.push({paramIndex: index, structName}); + } + }); + + // Unwrap returnTypeAnnotation, so we check if the return type is Promise + // TODO(T76719514): Disallow nullable PromiseTypeAnnotations + const [returnTypeAnnotation] = unwrapNullable( + propertyTypeAnnotation.returnTypeAnnotation, + ); + + if (returnTypeAnnotation.type === 'PromiseTypeAnnotation') { + methodParams.push( + {paramName: 'resolve', objCType: 'RCTPromiseResolveBlock'}, + {paramName: 'reject', objCType: 'RCTPromiseRejectBlock'}, + ); + } + + /** + * Build Protocol Method + **/ + const returnObjCType = getReturnObjCType( + methodName, + propertyTypeAnnotation.returnTypeAnnotation, + ); + const paddingMax = `- (${returnObjCType})${methodName}`.length; + + const objCParams = methodParams.reduce( + ($objCParams, {objCType, paramName}, i) => { + const rhs = `(${objCType})${paramName}`; + const padding = ' '.repeat(Math.max(0, paddingMax - paramName.length)); + return i === 0 + ? `:${rhs}` + : `${$objCParams}\n${padding}${paramName}:${rhs}`; + }, + '', + ); + + const protocolMethod = ProtocolMethodTemplate({ + methodName, + returnObjCType, + params: objCParams, + }); + + /** + * Build ObjC Selector + */ + const selector = methodParams + .map(({paramName}) => paramName) + .reduce(($selector, paramName, i) => { + return i === 0 ? `${$selector}:` : `${$selector}${paramName}:`; + }, methodName); + + /** + * Build JS Return type + */ + const returnJSType = getReturnJSType(methodName, returnTypeAnnotation); + + return [ + { + methodName, + protocolMethod, + selector: `@selector(${selector})`, + structParamRecords, + returnJSType, + argCount: params.length, + }, + ]; +} + +type Param = NamedShape>; + +function getParamStructName(methodName: string, param: Param): string { + const [typeAnnotation] = unwrapNullable(param.typeAnnotation); + if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { + return typeAnnotation.name; + } + + return `Spec${capitalize(methodName)}${capitalize(param.name)}`; +} + +function getParamObjCType( + hasteModuleName: string, + methodName: string, + param: Param, + structName: string, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnly<{objCType: string, isStruct: boolean}> { + const {name: paramName, typeAnnotation: nullableTypeAnnotation} = param; + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + const notRequired = param.optional || nullable; + + function wrapIntoNullableIfNeeded(generatedType: string) { + return nullable ? `${generatedType} _Nullable` : generatedType; + } + + const isStruct = (objCType: string) => ({ + isStruct: true, + objCType, + }); + + const notStruct = (objCType: string) => ({ + isStruct: false, + objCType, + }); + + // Handle types that can only be in parameters + switch (typeAnnotation.type) { + case 'FunctionTypeAnnotation': { + return notStruct('RCTResponseSenderBlock'); + } + case 'ArrayTypeAnnotation': { + /** + * Array in params always codegen NSArray * + * + * TODO(T73933406): Support codegen for Arrays of structs and primitives + * + * For example: + * Array => NSArray + * type Animal = {}; + * Array => NSArray, etc. + */ + return notStruct(wrapIntoNullableIfNeeded('NSArray *')); + } + } + + const [structTypeAnnotation] = unwrapNullable( + structCollector.process( + structName, + 'REGULAR', + resolveAlias, + wrapNullable(nullable, typeAnnotation), + ), + ); + + invariant( + structTypeAnnotation.type !== 'ArrayTypeAnnotation', + 'ArrayTypeAnnotations should have been processed earlier', + ); + + switch (structTypeAnnotation.type) { + case 'TypeAliasTypeAnnotation': { + /** + * TODO(T73943261): Support nullable object literals and aliases? + */ + return isStruct( + getNamespacedStructName(hasteModuleName, structTypeAnnotation.name) + + ' &', + ); + } + case 'ReservedTypeAnnotation': + switch (structTypeAnnotation.name) { + case 'RootTag': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + default: + (structTypeAnnotation.name: empty); + throw new Error( + `Unsupported type for param "${paramName}" in ${methodName}. Found: ${structTypeAnnotation.type}`, + ); + } + case 'StringTypeAnnotation': + return notStruct(wrapIntoNullableIfNeeded('NSString *')); + case 'NumberTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'FloatTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'DoubleTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'Int32TypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'BooleanTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'BOOL'); + case 'GenericObjectTypeAnnotation': + return notStruct(wrapIntoNullableIfNeeded('NSDictionary *')); + default: + (structTypeAnnotation.type: empty); + throw new Error( + `Unsupported type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function getReturnObjCType( + methodName: string, + nullableTypeAnnotation: Nullable, +) { + const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); + + function wrapIntoNullableIfNeeded(generatedType: string) { + return nullable ? `${generatedType} _Nullable` : generatedType; + } + + switch (typeAnnotation.type) { + case 'VoidTypeAnnotation': + return 'void'; + case 'PromiseTypeAnnotation': + return 'void'; + case 'ObjectTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + case 'TypeAliasTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return wrapIntoNullableIfNeeded('NSArray> *'); + } + + return wrapIntoNullableIfNeeded( + `NSArray<${getReturnObjCType( + methodName, + typeAnnotation.elementType, + )}> *`, + ); + case 'ReservedTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapIntoNullableIfNeeded('NSNumber *'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.name}`, + ); + } + case 'StringTypeAnnotation': + // TODO: Can NSString * returns not be _Nullable? + // In the legacy codegen, we don't surround NSSTring * with _Nullable + return wrapIntoNullableIfNeeded('NSString *'); + case 'NumberTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'FloatTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'DoubleTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'Int32TypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'BooleanTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'GenericObjectTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + default: + (typeAnnotation.type: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function getReturnJSType( + methodName: string, + nullableTypeAnnotation: Nullable, +): ReturnJSType { + const [typeAnnotation] = unwrapNullable(nullableTypeAnnotation); + switch (typeAnnotation.type) { + case 'VoidTypeAnnotation': + return 'VoidKind'; + case 'PromiseTypeAnnotation': + return 'PromiseKind'; + case 'ObjectTypeAnnotation': + return 'ObjectKind'; + case 'TypeAliasTypeAnnotation': + return 'ObjectKind'; + case 'ArrayTypeAnnotation': + return 'ArrayKind'; + case 'ReservedTypeAnnotation': + return 'NumberKind'; + case 'StringTypeAnnotation': + return 'StringKind'; + case 'NumberTypeAnnotation': + return 'NumberKind'; + case 'FloatTypeAnnotation': + return 'NumberKind'; + case 'DoubleTypeAnnotation': + return 'NumberKind'; + case 'Int32TypeAnnotation': + return 'NumberKind'; + case 'BooleanTypeAnnotation': + return 'BooleanKind'; + case 'GenericObjectTypeAnnotation': + return 'ObjectKind'; + default: + (typeAnnotation.type: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function serializeConstantsProtocolMethods( + hasteModuleName: string, + property: NativeModulePropertyShape, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnlyArray { + const [propertyTypeAnnotation] = unwrapNullable(property.typeAnnotation); + if (propertyTypeAnnotation.params.length !== 0) { + throw new Error( + `${hasteModuleName}.getConstants() may only accept 0 arguments.`, + ); + } + + const {returnTypeAnnotation} = propertyTypeAnnotation; + if (returnTypeAnnotation.type !== 'ObjectTypeAnnotation') { + throw new Error( + `${hasteModuleName}.getConstants() may only return an object literal: {...}.`, + ); + } + + if (returnTypeAnnotation.properties.length === 0) { + return []; + } + + const realTypeAnnotation = structCollector.process( + 'Constants', + 'CONSTANTS', + resolveAlias, + returnTypeAnnotation, + ); + + invariant( + realTypeAnnotation.type === 'TypeAliasTypeAnnotation', + "Unable to generate C++ struct from module's getConstants() method return type.", + ); + + const returnObjCType = `facebook::react::ModuleConstants`; + + return ['constantsToExport', 'getConstants'].map( + methodName => { + const protocolMethod = ProtocolMethodTemplate({ + methodName, + returnObjCType, + params: '', + }); + + return { + methodName, + protocolMethod, + returnJSType: 'ObjectKind', + selector: `@selector(${methodName})`, + structParamRecords: [], + argCount: 0, + }; + }, + ); +} + +module.exports = { + serializeMethod, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js new file mode 100644 index 00000000000000..14796e88a65d67 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js @@ -0,0 +1,121 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {Struct} from '../StructCollector'; +import type { + MethodSerializationOutput, + StructParameterRecord, +} from '../serializeMethod'; + +const ModuleTemplate = ({ + hasteModuleName, + structs, + methodSerializationOutputs, +}: $ReadOnly<{ + hasteModuleName: string, + structs: $ReadOnlyArray, + methodSerializationOutputs: $ReadOnlyArray, +}>) => `${structs + .map(struct => + RCTCxxConvertCategoryTemplate({hasteModuleName, structName: struct.name}), + ) + .join('\n')} +namespace facebook { + namespace react { + ${methodSerializationOutputs + .map(serializedMethodParts => + InlineHostFunctionTemplate({ + hasteModuleName, + methodName: serializedMethodParts.methodName, + returnJSType: serializedMethodParts.returnJSType, + selector: serializedMethodParts.selector, + }), + ) + .join('\n')} + + ${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + ${methodSerializationOutputs + .map(({methodName, structParamRecords, argCount}) => + MethodMapEntryTemplate({ + hasteModuleName, + methodName, + structParamRecords, + argCount, + }), + ) + .join('\n' + ' '.repeat(8))} + } + } // namespace react +} // namespace facebook`; + +const RCTCxxConvertCategoryTemplate = ({ + hasteModuleName, + structName, +}: $ReadOnly<{ + hasteModuleName: string, + structName: string, +}>) => `@implementation RCTCxxConvert (${hasteModuleName}_${structName}) ++ (RCTManagedPointer *)JS_${hasteModuleName}_${structName}:(id)json +{ + return facebook::react::managedPointer(json); +} +@end`; + +const InlineHostFunctionTemplate = ({ + hasteModuleName, + methodName, + returnJSType, + selector, +}: $ReadOnly<{ + hasteModuleName: string, + methodName: string, + returnJSType: string, + selector: string, +}>) => ` + static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${methodName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ${returnJSType}, "${methodName}", ${selector}, args, count); + }`; + +const MethodMapEntryTemplate = ({ + hasteModuleName, + methodName, + structParamRecords, + argCount, +}: $ReadOnly<{ + hasteModuleName: string, + methodName: string, + structParamRecords: $ReadOnlyArray, + argCount: number, +}>) => ` + methodMap_["${methodName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${methodName}}; + ${structParamRecords + .map(({paramIndex, structName}) => { + return `setMethodArgConversionSelector(@"${methodName}", ${paramIndex}, @"JS_${hasteModuleName}_${structName}:");`; + }) + .join('\n' + ' '.repeat(8))}`; + +function serializeModuleSource( + hasteModuleName: string, + structs: $ReadOnlyArray, + methodSerializationOutputs: $ReadOnlyArray, +): string { + return ModuleTemplate({ + hasteModuleName, + structs: structs.filter(({context}) => context !== 'CONSTANTS'), + methodSerializationOutputs, + }); +} + +module.exports = { + serializeModuleSource, +}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js deleted file mode 100644 index c9e1d817a296d1..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const { - flatObjects, - capitalizeFirstLetter, - getSafePropertyName, -} = require('./Utils'); -const {getTypeAliasTypeAnnotation} = require('../Utils'); -const {generateStructsForConstants} = require('./GenerateStructsForConstants'); - -const template = ` -::_CONSTANTS_::::_STRUCTS_::::_INLINES_:: -`; - -const structTemplate = ` -namespace JS { - namespace Native::_MODULE_NAME_:: { - struct ::_STRUCT_NAME_:: { - ::_STRUCT_PROPERTIES_:: - - ::_STRUCT_NAME_::(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (Native::_MODULE_NAME_::_::_STRUCT_NAME_::) -+ (RCTManagedPointer *)JS_Native::_MODULE_NAME_::_::_STRUCT_NAME_:::(id)json; -@end -`; - -const inlineTemplate = ` -inline ::_RETURN_TYPE_::JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::::_PROPERTY_NAME_::() const -{ - id const p = _v[@"::_PROPERTY_NAME_::"]; - return ::_RETURN_VALUE_::; -} -`; - -function getNamespacedStructName(structName: string): string { - return `JS::Native::_MODULE_NAME_::::${structName}`; -} - -function getElementTypeForArray( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - if (typeAnnotation.type !== 'ArrayTypeAnnotation') { - throw new Error( - `Cannot get array element type for non-array type ${typeAnnotation.type}`, - ); - } - - if (!typeAnnotation.elementType) { - return 'id'; - } - - const type = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.elementType.name, aliases) - .type - : typeAnnotation.elementType.type; - switch (type) { - case 'StringTypeAnnotation': - return 'NSString *'; - case 'DoubleTypeAnnotation': - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return 'double'; - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? typeAnnotation.elementType.name - : `${property.name}Element`; - return getNamespacedStructName(structName); - case 'GenericObjectTypeAnnotation': - // TODO(T67565166): Generic objects are not type safe and should be disallowed in the schema. This case should throw an error once it is disallowed in schema. - console.error( - `Warning: Generic objects are not type safe and should be avoided whenever possible (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return 'id'; - case 'BooleanTypeAnnotation': - case 'AnyObjectTypeAnnotation': - case 'AnyTypeAnnotation': - case 'ArrayTypeAnnotation': - case 'FunctionTypeAnnotation': - case 'ReservedFunctionValueTypeAnnotation': - case 'ReservedPropTypeAnnotation': - case 'StringEnumTypeAnnotation': - throw new Error(`Unsupported array element type, found: ${type}"`); - default: - (type: empty); - throw new Error(`Unknown array element type, found: ${type}"`); - } -} - -function getInlineMethodSignature( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - function markOptionalTypeIfNecessary(type: string) { - if (property.optional) { - return `folly::Optional<${type}>`; - } - return type; - } - - // TODO(T67672788): Workaround for values key in NativeLinking which lacks a typeAnnotation. id is not type safe! - if (!typeAnnotation) { - console.error( - `Warning: Unsafe type found (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return `id ${getSafePropertyName(property)}() const;`; - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - const variableName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? `${capitalizeFirstLetter(typeAnnotation.name)}` - : `${capitalizeFirstLetter(name)}${capitalizeFirstLetter( - getSafePropertyName(property), - )}`; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return `double ${getSafePropertyName(property)}() const;`; - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - return `NSString *${getSafePropertyName(property)}() const;`; - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return `${markOptionalTypeIfNecessary('double')} ${getSafePropertyName( - property, - )}() const;`; - case 'BooleanTypeAnnotation': - return `${markOptionalTypeIfNecessary('bool')} ${getSafePropertyName( - property, - )}() const;`; - case 'ObjectTypeAnnotation': - return `${markOptionalTypeIfNecessary( - getNamespacedStructName(variableName), - )} ${getSafePropertyName(property)}() const;`; - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return `id ${ - property.optional ? '_Nullable ' : ' ' - }${getSafePropertyName(property)}() const;`; - case 'ArrayTypeAnnotation': - return `${markOptionalTypeIfNecessary( - `facebook::react::LazyVector<${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}>`, - )} ${getSafePropertyName(property)}() const;`; - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function getInlineMethodImplementation( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - function markOptionalTypeIfNecessary(type: string): string { - if (property.optional) { - return `folly::Optional<${type}> `; - } - return `${type} `; - } - function markOptionalValueIfNecessary(value: string): string { - if (property.optional) { - return `RCTBridgingToOptional${capitalizeFirstLetter(value)}`; - } - return `RCTBridgingTo${capitalizeFirstLetter(value)}`; - } - function bridgeArrayElementValueIfNecessary(element: string): string { - // TODO(T67898313): Workaround for NativeLinking's use of union type - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - if (typeAnnotation.type !== 'ArrayTypeAnnotation') { - throw new Error( - `Cannot get array element type for non-array type ${typeAnnotation.type}`, - ); - } - - if (!typeAnnotation.elementType) { - throw new Error(`Cannot get array element type for ${name}`); - } - - const type = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.elementType.name, aliases) - .type - : typeAnnotation.elementType.type; - - switch (type) { - case 'StringTypeAnnotation': - return `RCTBridgingToString(${element})`; - case 'DoubleTypeAnnotation': - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return `RCTBridgingToDouble(${element})`; - case 'BooleanTypeAnnotation': - return `RCTBridgingToBool(${element})`; - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? `${typeAnnotation.elementType.name}(${element})` - : `${getSafePropertyName(property)}Element(${element})`; - return getNamespacedStructName(structName); - case 'GenericObjectTypeAnnotation': - return element; - case 'AnyObjectTypeAnnotation': - case 'AnyTypeAnnotation': - case 'ArrayTypeAnnotation': - case 'FunctionTypeAnnotation': - case 'ReservedFunctionValueTypeAnnotation': - case 'ReservedPropTypeAnnotation': - case 'StringEnumTypeAnnotation': - case 'TupleTypeAnnotation': - throw new Error(`Unsupported array element type, found: ${type}"`); - default: - (type: empty); - throw new Error(`Unknown array element type, found: ${type}"`); - } - } - - // TODO(T67672788): Workaround for values key in NativeLinking which lacks a typeAnnotation. id is not type safe! - if (!typeAnnotation) { - console.error( - `Warning: Unsafe type found (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - property.optional ? 'id _Nullable ' : 'id ', - ) - .replace(/::_RETURN_VALUE_::/, 'p'); - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'double ') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToDouble(p)'); - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'NSString *') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToString(p)'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('double')) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('double')}(p)`, - ); - case 'BooleanTypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('bool')) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('bool')}(p)`, - ); - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - property.optional ? 'id _Nullable ' : 'id ', - ) - .replace(/::_RETURN_VALUE_::/, 'p'); - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? `${capitalizeFirstLetter(typeAnnotation.name)}` - : `${name}${capitalizeFirstLetter(getSafePropertyName(property))}`; - const namespacedStructName = getNamespacedStructName(structName); - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - markOptionalTypeIfNecessary(namespacedStructName), - ) - .replace( - /::_RETURN_VALUE_::/, - property.optional - ? `(p == nil ? folly::none : folly::make_optional(${namespacedStructName}(p)))` - : `${namespacedStructName}(p)`, - ); - case 'ArrayTypeAnnotation': - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - markOptionalTypeIfNecessary( - `facebook::react::LazyVector<${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}>`, - ), - ) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('vec')}(p, ^${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}(id itemValue_0) { return ${bridgeArrayElementValueIfNecessary( - 'itemValue_0', - )}; })`, - ); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function translateObjectsForStructs( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const flattenObjects = flatObjects(annotations, false, aliases); - - const translatedInlineMethods = flattenObjects - .reduce( - (acc, object) => - acc.concat( - object.properties.map(property => - getInlineMethodImplementation( - property, - object.name, - moduleName, - aliases, - ) - .replace(/::_PROPERTY_NAME_::/g, getSafePropertyName(property)) - .replace(/::_STRUCT_NAME_::/g, object.name), - ), - ), - [], - ) - .join('\n'); - - const translatedStructs = flattenObjects - .map(object => { - return structTemplate - .replace( - /::_STRUCT_PROPERTIES_::/g, - object.properties - .map(property => - getInlineMethodSignature( - property, - object.name, - moduleName, - aliases, - ), - ) - .join('\n '), - ) - .replace(/::_STRUCT_NAME_::/g, object.name); - }) - .reverse() - .join('\n'); - const translatedConstants = generateStructsForConstants(annotations, aliases); - - return template - .replace(/::_STRUCTS_::/, translatedStructs) - .replace(/::_INLINES_::/, translatedInlineMethods) - .replace(/::_CONSTANTS_::/, translatedConstants); -} -module.exports = { - translateObjectsForStructs, - capitalizeFirstLetter, - getNamespacedStructName, -}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js deleted file mode 100644 index 0433152f7f627d..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js +++ /dev/null @@ -1,275 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const {flatObjects, capitalizeFirstLetter} = require('./Utils'); -const {getTypeAliasTypeAnnotation} = require('../Utils'); - -const structTemplate = ` -namespace JS { - namespace Native::_MODULE_NAME_:: { - struct ::_STRUCT_NAME_:: { - - struct Builder { - struct Input { - ::_INPUT_:: - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ::_STRUCT_NAME_:: */ - Builder(::_STRUCT_NAME_:: i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ::_STRUCT_NAME_:: fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ::_STRUCT_NAME_::(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - ::_PROPERTIES_:: - return d; -}) {} -inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(::_STRUCT_NAME_:: i) : _factory(^{ - return i.unsafeRawValue(); -}) {}`; - -function getBuilderInputFieldDeclaration( - property: ObjectParamTypeAnnotation, - name: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - function markRequiredIfNecessary(annotation) { - if (!property.optional) { - return 'RCTRequired<' + annotation + '> ' + property.name + ';'; - } - return 'folly::Optional<' + annotation + '> ' + property.name + ';'; - } - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - const variableName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? typeAnnotation.name - : `${name}${capitalizeFirstLetter(property.name)}`; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return markRequiredIfNecessary('double'); - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - if (property.optional) { - return 'NSString *' + property.name + ';'; - } - return markRequiredIfNecessary('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return markRequiredIfNecessary('double'); - case 'BooleanTypeAnnotation': - return markRequiredIfNecessary('bool'); - case 'ObjectTypeAnnotation': - return markRequiredIfNecessary( - `JS::Native::_MODULE_NAME_::::${variableName}::Builder`, - ); - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - if (property.optional) { - return 'id _Nullable ' + property.name + ';'; - } - return markRequiredIfNecessary('id'); - case 'ArrayTypeAnnotation': - return markRequiredIfNecessary('std::vector>'); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function safeGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${name}; - `.trim(); -} - -function arrayGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = RCTConvert${ - optional ? 'Optional' : '' - }VecToArray(${name}, ^id(id el_) { return el_; }); - `.trim(); -} - -function boolGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? @((BOOL)${name}.value()) : nil` - : `@(${name})` - }; - `.trim(); -} - -function numberGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? @((double)${name}.value()) : nil` - : `@(${name})` - }; - `.trim(); -} - -function unsafeGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? ${name}.value().buildUnsafeRawValue() : nil` - : `${name}.buildUnsafeRawValue()` - }; - `.trim(); -} - -function getObjectProperty( - property: ObjectParamTypeAnnotation, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - const type = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases).type - : typeAnnotation.type; - - switch (type) { - case 'ReservedFunctionValueTypeAnnotation': - if (typeAnnotation.name == null) { - throw new Error(`Prop type ${type} has no name.`); - } - switch (typeAnnotation.name) { - case 'RootTag': - return numberGetter(property.name, property.optional); - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.name: empty); - throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); - } - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return numberGetter(property.name, property.optional); - case 'BooleanTypeAnnotation': - return boolGetter(property.name, property.optional); - case 'StringTypeAnnotation': - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return safeGetter(property.name, property.optional); - case 'ObjectTypeAnnotation': - return unsafeGetter(property.name, property.optional); - case 'ArrayTypeAnnotation': - return arrayGetter(property.name, property.optional); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${type}"`); - } -} - -function generateStructsForConstants( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - return flatObjects(annotations, true, aliases) - .reduce( - (acc, object) => - acc.concat( - structTemplate - .replace( - /::_INPUT_::/g, - object.properties - .map(property => - getBuilderInputFieldDeclaration( - property, - object.name, - aliases, - ), - ) - .join('\n '), - ) - .replace( - /::_PROPERTIES_::/g, - object.properties - .map(property => getObjectProperty(property, aliases)) - .join('\n'), - ) - .replace(/::_STRUCT_NAME_::/g, object.name), - ), - [], - ) - .reverse() - .join('\n') - .replace(/SpecGetConstantsReturnType/g, 'Constants') - .replace(/GetConstantsReturnType/g, 'Constants'); -} -module.exports = { - generateStructsForConstants, - capitalizeFirstLetter, -}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js deleted file mode 100644 index fd4dca38468dad..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict - * @format - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('../Utils'); - -function capitalizeFirstLetter(string: string): string { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -function flatObjects( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - forConstants: boolean = false, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): $ReadOnlyArray< - $ReadOnly<{| - name: string, - properties: $ReadOnlyArray, - |}>, -> { - let objectTypesToFlatten: Array<{| - properties: $ReadOnlyArray, - name: string, - |}> = annotations - .map(annotation => { - if (annotation.object.type === 'TypeAliasTypeAnnotation') { - const alias = getTypeAliasTypeAnnotation(annotation.name, aliases); - return {name: annotation.name, properties: alias.properties}; - } - return { - name: annotation.name, - properties: annotation.object.properties, - }; - }) - .filter( - annotation => - (annotation.name === 'SpecGetConstantsReturnType') === forConstants, - ) - .filter( - annotation => - annotation.name !== 'SpecGetConstantsReturnType' || - annotation.properties.length > 0, - ); - - let flattenObjects: Array<{| - properties: $ReadOnlyArray, - name: string, - |}> = []; - - while (objectTypesToFlatten.length !== 0) { - const oldObjectTypesToFlatten = objectTypesToFlatten; - objectTypesToFlatten = []; - flattenObjects = flattenObjects.concat( - oldObjectTypesToFlatten.map(object => { - const {properties} = object; - if (properties !== undefined) { - objectTypesToFlatten = objectTypesToFlatten.concat( - properties.reduce((acc, curr) => { - if ( - curr.typeAnnotation && - curr.typeAnnotation.type === 'ObjectTypeAnnotation' && - curr.typeAnnotation.properties - ) { - return acc.concat({ - properties: curr.typeAnnotation.properties, - name: object.name + capitalizeFirstLetter(curr.name), - }); - } - return acc; - }, []), - ); - } - return object; - }), - ); - } - - return flattenObjects; -} - -function getSafePropertyName(property: ObjectParamTypeAnnotation): string { - if (property.name === 'id') { - return `${property.name}_`; - } - return property.name; -} - -module.exports = { - flatObjects, - capitalizeFirstLetter, - getSafePropertyName, -}; diff --git a/packages/react-native-codegen/src/generators/modules/Utils.js b/packages/react-native-codegen/src/generators/modules/Utils.js index 8ce5c95416f610..10017bb420bb0c 100644 --- a/packages/react-native-codegen/src/generators/modules/Utils.js +++ b/packages/react-native-codegen/src/generators/modules/Utils.js @@ -10,35 +10,44 @@ 'use strict'; -import type {ObjectTypeAliasTypeShape} from '../../CodegenSchema'; +import type { + SchemaType, + NativeModuleAliasMap, + NativeModuleObjectTypeAnnotation, + NativeModuleSchema, +} from '../../CodegenSchema'; -function getTypeAliasTypeAnnotation( - name: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): $ReadOnly { - const typeAnnotation = aliases[name]; - if (!typeAnnotation) { - throw Error(`No type annotation found for "${name}" in schema`); - } - if (typeAnnotation.type === 'ObjectTypeAnnotation') { - if (typeAnnotation.properties) { - return typeAnnotation; - } +const invariant = require('invariant'); - throw new Error( - `Unsupported type for "${name}". Please provide properties.`, - ); - } - // $FlowFixMe[incompatible-type] - if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { - return getTypeAliasTypeAnnotation(typeAnnotation.name, aliases); - } +export type AliasResolver = ( + aliasName: string, +) => NativeModuleObjectTypeAnnotation; - throw Error( - `Unsupported type annotation in alias "${name}", found: ${typeAnnotation.type}`, +function createAliasResolver(aliasMap: NativeModuleAliasMap): AliasResolver { + return (aliasName: string) => { + const alias = aliasMap[aliasName]; + invariant(alias != null, `Unable to resolve type alias '${aliasName}'.`); + return alias; + }; +} + +function getModules( + schema: SchemaType, +): $ReadOnly<{[hasteModuleName: string]: NativeModuleSchema}> { + return Object.keys(schema.modules).reduce<{[string]: NativeModuleSchema}>( + (modules, hasteModuleName: string) => { + const module = schema.modules[hasteModuleName]; + if (module == null || module.type === 'Component') { + return modules; + } + modules[hasteModuleName] = module; + return modules; + }, + {}, ); } module.exports = { - getTypeAliasTypeAnnotation, + createAliasResolver, + getModules, }; diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index cea663c8b1b425..eb1f8ddd6f1edf 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -14,965 +14,481 @@ import type {SchemaType} from '../../../CodegenSchema.js'; const EMPTY_NATIVE_MODULES: SchemaType = { modules: { - SampleTurboModule: { - nativeModules: { - SampleTurboModule: { - aliases: {}, - properties: [], - }, + NativeSampleTurboModule: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [], }, + moduleNames: ['SampleTurboModule'], }, }, }; const SIMPLE_NATIVE_MODULES: SchemaType = { modules: { - SampleTurboModule: { - nativeModules: { - SampleTurboModule: { - aliases: {}, - properties: [ - { - name: 'getConstants', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'const1', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'const2', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'const3', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - params: [], - optional: false, - }, - }, - { - name: 'voidFunc', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [], - optional: false, - }, - }, - { - name: 'getBool', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'BooleanTypeAnnotation', - }, - params: [ + NativeSampleTurboModule: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [ + { + name: 'getConstants', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ { - nullable: false, - name: 'arg', + optional: false, + name: 'const1', typeAnnotation: { type: 'BooleanTypeAnnotation', }, }, - ], - optional: false, - }, - }, - { - name: 'getNumber', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'NumberTypeAnnotation', - }, - params: [ { - nullable: false, - name: 'arg', + optional: false, + name: 'const2', typeAnnotation: { type: 'NumberTypeAnnotation', }, }, - ], - optional: false, - }, - }, - { - name: 'getString', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'StringTypeAnnotation', - }, - params: [ { - nullable: false, - name: 'arg', + optional: false, + name: 'const3', typeAnnotation: { type: 'StringTypeAnnotation', }, }, ], - optional: false, }, + params: [], }, - { - name: 'getArray', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ArrayTypeAnnotation', - elementType: { - type: 'AnyTypeAnnotation', - }, - }, - params: [ - { - name: 'arg', - nullable: false, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'AnyTypeAnnotation', - }, - }, - }, - ], - optional: false, + }, + { + name: 'voidFunc', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', }, + params: [], }, - { - name: 'getObject', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'GenericObjectTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'arg', - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }, - ], - optional: false, + }, + { + name: 'getBool', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'BooleanTypeAnnotation', }, - }, - { - name: 'getRootTag', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - params: [ - { - nullable: false, - name: 'arg', - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, + params: [ + { + optional: false, + name: 'arg', + typeAnnotation: { + type: 'BooleanTypeAnnotation', }, - ], - optional: false, - }, - }, - { - name: 'getValue', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'GenericObjectTypeAnnotation', }, - params: [ - { - nullable: false, - name: 'x', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - nullable: false, - name: 'y', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - nullable: false, - name: 'z', - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }, - ], - optional: false, - }, + ], }, - { - name: 'getValueWithCallback', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - name: 'callback', - nullable: false, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - }, - }, - ], - optional: false, + }, + { + name: 'getNumber', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'NumberTypeAnnotation', }, - }, - { - name: 'getValueWithPromise', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'GenericPromiseTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'error', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, + params: [ + { + optional: false, + name: 'arg', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, - ], - optional: false, - }, - }, - ], - }, - }, - }, - }, -}; - -const TWO_MODULES_SAME_FILE: SchemaType = { - modules: { - NativeSampleTurboModule: { - nativeModules: { - SampleTurboModule: { - aliases: {}, - properties: [ - { - name: 'voidFunc', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [], - optional: false, - }, - }, - ], - }, - Sample2TurboModule: { - aliases: {}, - properties: [ - { - name: 'voidFunc', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', }, - params: [], - optional: false, - }, + ], }, - ], - }, - }, - }, - }, -}; - -const TWO_MODULES_DIFFERENT_FILES: SchemaType = { - modules: { - NativeSampleTurboModule: { - nativeModules: { - SampleTurboModule: { - aliases: {}, - properties: [ - { - name: 'voidFunc', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [], - optional: false, + }, + { + name: 'getString', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'StringTypeAnnotation', }, - }, - ], - }, - }, - }, - NativeSampleTurboModule2: { - nativeModules: { - Sample2TurboModule: { - aliases: {}, - properties: [ - { - name: 'getConstants', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ObjectTypeAnnotation', - properties: [], + params: [ + { + optional: false, + name: 'arg', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, }, - params: [], - optional: false, - }, + ], }, - { - name: 'voidFunc', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', + }, + { + name: 'getArray', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'GenericObjectTypeAnnotation', }, - params: [], - optional: false, }, - }, - ], - }, - }, - }, - }, -}; + params: [ + { + name: 'arg', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', -const COMPLEX_OBJECTS: SchemaType = { - modules: { - NativeSampleTurboModule: { - nativeModules: { - SampleTurboModule: { - aliases: {}, - properties: [ - { - name: 'difficult', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'D', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'E', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'F', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - params: [ - { - nullable: false, - name: 'A', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'D', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'E', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'D', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'E', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'F', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'id', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - { - optional: false, - name: 'F', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - }, - ], - optional: false, - }, - }, - { - name: 'optionals', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'A', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: true, - name: 'optionalNumberProperty', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'optionalArrayProperty', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'NumberTypeAnnotation', - }, - }, - }, - { - optional: true, - name: 'optionalObjectProperty', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'x', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'y', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - { - optional: true, - name: 'optionalGenericObjectProperty', - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }, - { - optional: true, - name: 'optionalBooleanTypeProperty', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - ], + elementType: { + type: 'GenericObjectTypeAnnotation', }, }, - ], - optional: false, - }, - }, - { - name: 'optionalMethod', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', }, - params: [ - { - nullable: false, - name: 'options', - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }, - { - name: 'callback', - nullable: false, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - }, - }, - { - name: 'extras', - nullable: true, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'key', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'value', - }, - ], - }, - }, - }, - ], - optional: true, - }, - }, - { - name: 'getArrays', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'options', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'arrayOfNumbers', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'NumberTypeAnnotation', - }, - }, - }, - { - optional: true, - name: 'optionalArrayOfNumbers', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'NumberTypeAnnotation', - }, - }, - }, - { - optional: false, - name: 'arrayOfStrings', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'StringTypeAnnotation', - }, - }, - }, - { - optional: true, - name: 'optionalArrayOfStrings', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'StringTypeAnnotation', - }, - }, - }, - { - optional: false, - name: 'arrayOfObjects', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'numberProperty', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - }, - ], - }, - }, - ], - optional: false, - }, + ], }, - ], - }, - }, - }, - }, -}; - -const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { - modules: { - AliasTurboModule: { - nativeModules: { - AliasTurboModule: { - aliases: { - Options: { - properties: [ - { - optional: false, - name: 'offset', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'x', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'y', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - { - optional: false, - name: 'size', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'width', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'height', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - { - optional: true, - name: 'displaySize', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'width', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'height', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - ], - }, - }, - { - optional: true, - name: 'resizeMode', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, + }, + { + name: 'getObject', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + params: [ { - optional: true, - name: 'allowExternalStorage', + optional: false, + name: 'arg', typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'GenericObjectTypeAnnotation', }, }, ], - type: 'ObjectTypeAnnotation', }, }, - properties: [ - { - name: 'getConstants', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ObjectTypeAnnotation', - properties: [], - }, - params: [], - optional: false, - }, - }, - { - name: 'cropImage', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'cropData', - typeAnnotation: { - type: 'TypeAliasTypeAnnotation', - name: 'Options', - }, - }, - ], - optional: false, + { + name: 'getRootTag', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ReservedTypeAnnotation', + name: 'RootTag', }, - }, - ], - }, - }, - }, - }, -}; - -const REAL_MODULE_EXAMPLE: SchemaType = { - modules: { - NativeCameraRollManager: { - nativeModules: { - CameraRollManager: { - aliases: { - PhotoIdentifierImage: { - type: 'ObjectTypeAnnotation', - properties: [ + params: [ { optional: false, - name: 'uri', + name: 'arg', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'ReservedTypeAnnotation', + name: 'RootTag', }, }, + ], + }, + }, + { + name: 'getValue', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + params: [ { optional: false, - name: 'playableDuration', + name: 'x', typeAnnotation: { type: 'NumberTypeAnnotation', }, }, { optional: false, - name: 'width', + name: 'y', typeAnnotation: { - type: 'NumberTypeAnnotation', + type: 'StringTypeAnnotation', }, }, { optional: false, - name: 'height', + name: 'z', typeAnnotation: { - type: 'NumberTypeAnnotation', + type: 'GenericObjectTypeAnnotation', }, }, + ], + }, + }, + { + name: 'getValueWithCallback', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ { - optional: true, - name: 'isStored', + name: 'callback', + optional: false, typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, + ], + }, + }, + { + name: 'getValueWithPromise', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'PromiseTypeAnnotation', + }, + params: [ { optional: false, - name: 'filename', + name: 'error', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'BooleanTypeAnnotation', }, }, ], }, - PhotoIdentifier: { - type: 'ObjectTypeAnnotation', - properties: [ + }, + ], + }, + moduleNames: ['SampleTurboModule'], + }, + }, +}; + +const TWO_MODULES_DIFFERENT_FILES: SchemaType = { + modules: { + NativeSampleTurboModule: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [ + { + name: 'voidFunc', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [], + }, + }, + ], + }, + moduleNames: ['SampleTurboModule'], + }, + NativeSampleTurboModule2: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [ + { + name: 'getConstants', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [], + }, + params: [], + }, + }, + { + name: 'voidFunc', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [], + }, + }, + ], + }, + moduleNames: ['SampleTurboModule2'], + }, + }, +}; + +const COMPLEX_OBJECTS: SchemaType = { + modules: { + NativeSampleTurboModule: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [ + { + name: 'difficult', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'D', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + { + optional: false, + name: 'E', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'F', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + ], + }, + params: [ { optional: false, - name: 'node', + name: 'A', typeAnnotation: { type: 'ObjectTypeAnnotation', properties: [ { optional: false, - name: 'image', + name: 'D', typeAnnotation: { - type: 'TypeAliasTypeAnnotation', - name: 'PhotoIdentifierImage', + type: 'BooleanTypeAnnotation', }, }, { optional: false, - name: 'type', + name: 'E', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'D', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + { + optional: false, + name: 'E', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'F', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'id', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + ], }, }, { optional: false, - name: 'group_name', + name: 'F', typeAnnotation: { type: 'StringTypeAnnotation', }, }, + ], + }, + }, + ], + }, + }, + { + name: 'optionals', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ + { + optional: false, + name: 'A', + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ { - optional: false, - name: 'timestamp', + optional: true, + name: 'optionalNumberProperty', typeAnnotation: { type: 'NumberTypeAnnotation', }, }, { - optional: false, - name: 'location', + optional: true, + name: 'optionalArrayProperty', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'NumberTypeAnnotation', + }, + }, + }, + { + optional: true, + name: 'optionalObjectProperty', typeAnnotation: { type: 'ObjectTypeAnnotation', properties: [ { optional: false, - name: 'longitude', + name: 'x', typeAnnotation: { type: 'NumberTypeAnnotation', }, }, { optional: false, - name: 'latitude', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'altitude', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'heading', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'speed', + name: 'y', typeAnnotation: { type: 'NumberTypeAnnotation', }, @@ -980,50 +496,157 @@ const REAL_MODULE_EXAMPLE: SchemaType = { ], }, }, + { + optional: true, + name: 'optionalGenericObjectProperty', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + }, + { + optional: true, + name: 'optionalBooleanTypeProperty', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, ], }, }, ], }, - PhotoIdentifiersPage: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'edges', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'TypeAliasTypeAnnotation', - name: 'PhotoIdentifier', + }, + { + name: 'optionalMethod', + optional: true, + typeAnnotation: { + type: 'NullableTypeAnnotation', + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ + { + optional: false, + name: 'options', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', }, }, - }, + { + name: 'callback', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + }, + }, + { + name: 'extras', + optional: true, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'key', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'value', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + { + name: 'getArrays', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ { optional: false, - name: 'page_info', + name: 'options', typeAnnotation: { type: 'ObjectTypeAnnotation', properties: [ { optional: false, - name: 'has_next_page', + name: 'arrayOfNumbers', typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'ArrayTypeAnnotation', + elementType: { + type: 'NumberTypeAnnotation', + }, }, }, { optional: true, - name: 'start_cursor', + name: 'optionalArrayOfNumbers', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'ArrayTypeAnnotation', + elementType: { + type: 'NumberTypeAnnotation', + }, + }, + }, + { + optional: false, + name: 'arrayOfStrings', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, }, }, { optional: true, - name: 'end_cursor', + name: 'optionalArrayOfStrings', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, + }, + }, + { + optional: false, + name: 'arrayOfObjects', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'ArrayTypeAnnotation', + elementType: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'numberProperty', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + ], + }, }, }, ], @@ -1031,289 +654,675 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, ], }, - GetPhotosParams: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'first', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'after', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: true, - name: 'groupName', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: true, - name: 'groupTypes', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: true, - name: 'assetType', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: true, - name: 'maxSize', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: true, - name: 'mimeTypes', - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'StringTypeAnnotation', - }, - }, - }, - ], - }, }, + ], + }, + moduleNames: ['SampleTurboModule'], + }, + }, +}; + +const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { + modules: { + AliasTurboModule: { + type: 'NativeModule', + aliases: { + Options: { + type: 'ObjectTypeAnnotation', properties: [ { - name: 'getConstants', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'ObjectTypeAnnotation', - properties: [], - }, - params: [], - optional: false, - }, - }, - { - name: 'getPhotos', + optional: false, + name: 'offset', typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', - nullable: false, - }, - params: [ + type: 'ObjectTypeAnnotation', + properties: [ { - nullable: false, - name: 'params', + optional: false, + name: 'x', typeAnnotation: { - type: 'TypeAliasTypeAnnotation', - name: 'GetPhotosParams', + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'y', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, }, ], - optional: false, }, }, { - name: 'saveToCameraRoll', + optional: false, + name: 'size', typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', - nullable: false, - }, - params: [ + type: 'ObjectTypeAnnotation', + properties: [ { - nullable: false, - name: 'uri', + optional: false, + name: 'width', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'NumberTypeAnnotation', }, }, { - nullable: false, - name: 'type', + optional: false, + name: 'height', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'NumberTypeAnnotation', }, }, ], - optional: false, }, }, { - name: 'deletePhotos', + optional: true, + name: 'displaySize', typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', - nullable: false, - }, - params: [ + type: 'ObjectTypeAnnotation', + properties: [ { - name: 'assets', - nullable: false, + optional: false, + name: 'width', typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'StringTypeAnnotation', - }, + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'height', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, }, ], - optional: false, + }, + }, + { + optional: true, + name: 'resizeMode', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'allowExternalStorage', + typeAnnotation: { + type: 'BooleanTypeAnnotation', }, }, ], }, }, + spec: { + properties: [ + { + name: 'getConstants', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [], + }, + params: [], + }, + }, + { + name: 'cropImage', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ + { + optional: false, + name: 'cropData', + typeAnnotation: { + type: 'TypeAliasTypeAnnotation', + name: 'Options', + }, + }, + ], + }, + }, + ], + }, + moduleNames: ['AliasTurboModule'], }, - NativeImagePickerIOS: { - nativeModules: { - ImagePickerIOS: { - aliases: {}, + }, +}; + +const REAL_MODULE_EXAMPLE: SchemaType = { + modules: { + NativeCameraRollManager: { + type: 'NativeModule', + aliases: { + PhotoIdentifierImage: { + type: 'ObjectTypeAnnotation', properties: [ { - name: 'openCameraDialog', + optional: false, + name: 'uri', typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'playableDuration', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'width', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'height', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'isStored', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + { + optional: false, + name: 'filename', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + ], + }, + PhotoIdentifier: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'node', + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'image', + typeAnnotation: { + type: 'TypeAliasTypeAnnotation', + name: 'PhotoIdentifierImage', + }, + }, + { + optional: false, + name: 'type', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'group_name', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'timestamp', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, { - nullable: false, - name: 'config', + optional: false, + name: 'location', typeAnnotation: { type: 'ObjectTypeAnnotation', properties: [ { optional: false, - name: 'unmirrorFrontFacingCamera', + name: 'longitude', typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'NumberTypeAnnotation', }, }, { optional: false, - name: 'videoMode', + name: 'latitude', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'altitude', typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'heading', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'speed', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, }, ], }, }, + ], + }, + }, + ], + }, + PhotoIdentifiersPage: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'edges', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'TypeAliasTypeAnnotation', + name: 'PhotoIdentifier', + }, + }, + }, + { + optional: false, + name: 'page_info', + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [ { - name: 'successCallback', - nullable: false, + optional: false, + name: 'has_next_page', typeAnnotation: { - type: 'FunctionTypeAnnotation', + type: 'BooleanTypeAnnotation', }, }, { - name: 'cancelCallback', - nullable: false, + optional: true, + name: 'start_cursor', typeAnnotation: { - type: 'FunctionTypeAnnotation', + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'end_cursor', + typeAnnotation: { + type: 'StringTypeAnnotation', }, }, ], - optional: false, + }, + }, + ], + }, + GetPhotosParams: { + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'first', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'after', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'groupName', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'groupTypes', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'assetType', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'maxSize', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: true, + name: 'mimeTypes', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, }, }, ], }, }, - }, - NativeExceptionsManager: { - nativeModules: { - ExceptionsManager: { - aliases: { - StackFrame: { - properties: [ + spec: { + properties: [ + { + name: 'getConstants', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: [], + }, + params: [], + }, + }, + { + name: 'getPhotos', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'PromiseTypeAnnotation', + }, + params: [ { - optional: true, - name: 'column', + optional: false, + name: 'params', typeAnnotation: { - type: 'NumberTypeAnnotation', + type: 'TypeAliasTypeAnnotation', + name: 'GetPhotosParams', }, }, + ], + }, + }, + { + name: 'saveToCameraRoll', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'PromiseTypeAnnotation', + }, + params: [ { optional: false, - name: 'file', + name: 'uri', typeAnnotation: { type: 'StringTypeAnnotation', }, }, - { - optional: true, - name: 'lineNumber', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, { optional: false, - name: 'methodName', + name: 'type', typeAnnotation: { type: 'StringTypeAnnotation', }, }, + ], + }, + }, + { + name: 'deletePhotos', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'PromiseTypeAnnotation', + }, + params: [ { - optional: true, - name: 'collapse', + name: 'assets', + optional: false, typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'ArrayTypeAnnotation', + elementType: { + type: 'StringTypeAnnotation', + }, }, }, ], - type: 'ObjectTypeAnnotation', }, - ExceptionData: { - properties: [ + }, + ], + }, + moduleNames: ['CameraRollManager'], + }, + NativeImagePickerIOS: { + type: 'NativeModule', + aliases: {}, + spec: { + properties: [ + { + name: 'openCameraDialog', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ { optional: false, - name: 'message', + name: 'config', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'ObjectTypeAnnotation', + properties: [ + { + optional: false, + name: 'unmirrorFrontFacingCamera', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + { + optional: false, + name: 'videoMode', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + ], }, }, { + name: 'successCallback', optional: false, - name: 'originalMessage', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, { + name: 'cancelCallback', optional: false, - name: 'name', typeAnnotation: { - type: 'StringTypeAnnotation', + type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }, + ], + }, + }, + ], + }, + moduleNames: ['ImagePickerIOS'], + excludedPlatforms: ['android'], + }, + NativeExceptionsManager: { + type: 'NativeModule', + aliases: { + StackFrame: { + properties: [ + { + optional: true, + name: 'column', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'file', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'lineNumber', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'methodName', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: true, + name: 'collapse', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + ], + type: 'ObjectTypeAnnotation', + }, + ExceptionData: { + properties: [ + { + optional: false, + name: 'message', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'originalMessage', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'name', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'componentStack', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + optional: false, + name: 'stack', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'TypeAliasTypeAnnotation', + name: 'StackFrame', + }, + }, + }, + { + optional: false, + name: 'id', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + optional: false, + name: 'isFatal', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + { + optional: true, + name: 'extraData', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + }, + }, + ], + type: 'ObjectTypeAnnotation', + }, + }, + spec: { + properties: [ + { + name: 'reportFatalException', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ { optional: false, - name: 'componentStack', + name: 'message', typeAnnotation: { type: 'StringTypeAnnotation', }, }, { - optional: false, name: 'stack', + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', elementType: { @@ -1324,117 +1333,64 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, { optional: false, - name: 'id', + name: 'exceptionId', typeAnnotation: { type: 'NumberTypeAnnotation', }, }, + ], + }, + }, + { + name: 'reportSoftException', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ { optional: false, - name: 'isFatal', + name: 'message', typeAnnotation: { - type: 'BooleanTypeAnnotation', + type: 'StringTypeAnnotation', }, }, { - optional: true, - name: 'extraData', + name: 'stack', + optional: false, typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }, - ], - type: 'ObjectTypeAnnotation', - }, - }, - properties: [ - { - name: 'reportFatalException', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'message', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - name: 'stack', - nullable: false, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'TypeAliasTypeAnnotation', - name: 'StackFrame', - }, - }, - }, - { - nullable: false, - name: 'exceptionId', - typeAnnotation: { - type: 'NumberTypeAnnotation', + type: 'ArrayTypeAnnotation', + elementType: { + type: 'TypeAliasTypeAnnotation', + name: 'StackFrame', }, }, - ], - optional: false, - }, - }, - { - name: 'reportSoftException', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', }, - params: [ - { - nullable: false, - name: 'message', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - name: 'stack', - nullable: false, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'TypeAliasTypeAnnotation', - name: 'StackFrame', - }, - }, - }, - { - nullable: false, - name: 'exceptionId', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, + { + optional: false, + name: 'exceptionId', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, - ], - optional: false, - }, + }, + ], }, - { - name: 'reportException', + }, + { + name: 'reportException', + optional: true, + typeAnnotation: { + type: 'NullableTypeAnnotation', typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { - nullable: false, type: 'VoidTypeAnnotation', }, params: [ { - nullable: false, + optional: false, name: 'data', typeAnnotation: { type: 'TypeAliasTypeAnnotation', @@ -1442,68 +1398,69 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, }, ], - optional: true, }, }, - { - name: 'updateExceptionMessage', - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation: { - nullable: false, - type: 'VoidTypeAnnotation', - }, - params: [ - { - nullable: false, - name: 'message', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, + }, + { + name: 'updateExceptionMessage', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [ + { + optional: false, + name: 'message', + typeAnnotation: { + type: 'StringTypeAnnotation', }, - { - name: 'stack', - nullable: false, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: { - type: 'TypeAliasTypeAnnotation', - name: 'StackFrame', - }, + }, + { + name: 'stack', + optional: false, + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'TypeAliasTypeAnnotation', + name: 'StackFrame', }, }, - { - nullable: false, - name: 'exceptionId', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, + }, + { + optional: false, + name: 'exceptionId', + typeAnnotation: { + type: 'NumberTypeAnnotation', }, - ], - optional: false, - }, + }, + ], }, - { - name: 'dismissRedbox', + }, + { + name: 'dismissRedbox', + optional: true, + typeAnnotation: { + type: 'NullableTypeAnnotation', typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { - nullable: false, type: 'VoidTypeAnnotation', }, params: [], - optional: true, }, }, - ], - }, + }, + ], }, + moduleNames: ['ExceptionsManager'], }, }, }; + module.exports = { COMPLEX_OBJECTS, - TWO_MODULES_SAME_FILE, TWO_MODULES_DIFFERENT_FILES, EMPTY_NATIVE_MODULES, SIMPLE_NATIVE_MODULES, diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js deleted file mode 100644 index 2de452b87c2c39..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type {ObjectParamTypeAnnotation} from '../../../CodegenSchema.js'; -const SIMPLE_STRUCT: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, -> = [ - { - name: 'SpecSampleFuncReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'a', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'b', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'c', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'd', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'e', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'f', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'g', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'h', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'i', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'j', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - }, - ], - }, - }, - { - optional: false, - name: 'k', - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }, - ], - }, - }, -]; - -const SIMPLE_CONSTANTS: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, -> = [ - { - name: 'SpecGetConstantsReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'a', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'b', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'c', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'd', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'e', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'f', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'g', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'h', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'i', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'j', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - }, - ], - }, - }, - { - optional: false, - name: 'k', - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }, - ], - }, - }, -]; -module.exports = { - SIMPLE_STRUCT, - SIMPLE_CONSTANTS, -}; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleCpp-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleCpp-test.js index 6dbe02f952f13a..a03ef0508b7851 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleCpp-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleCpp-test.js @@ -22,7 +22,11 @@ describe('GenerateModuleCpp', () => { it(`can generate fixture ${fixtureName}`, () => { expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleH-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleH-test.js index 658221b56298f4..3acbc7f638f94c 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleH-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleH-test.js @@ -22,7 +22,11 @@ describe('GenerateModuleH', () => { it(`can generate fixture ${fixtureName}`, () => { expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js index b41441cb2daf7c..4544348ccff62c 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js @@ -12,7 +12,7 @@ 'use strict'; const fixtures = require('../__test_fixtures__/fixtures.js'); -const generator = require('../GenerateModuleHObjCpp.js'); +const generator = require('../GenerateModuleObjCpp'); describe('GenerateModuleHObjCpp', () => { Object.keys(fixtures) @@ -21,8 +21,13 @@ describe('GenerateModuleHObjCpp', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { + const output = generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ); expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + new Map([[`${fixtureName}.h`, output.get(`${fixtureName}.h`)]]), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJavaSpec-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJavaSpec-test.js index 5ccb87d2d4b672..854d21388c18a8 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJavaSpec-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJavaSpec-test.js @@ -22,7 +22,11 @@ describe('GenerateModuleJavaSpec', () => { it(`can generate fixture ${fixtureName}`, () => { expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniCpp-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniCpp-test.js index e6030bca0fc2d1..0dfc249f71458f 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniCpp-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniCpp-test.js @@ -22,7 +22,11 @@ describe('GenerateModuleJniCpp', () => { it(`can generate fixture ${fixtureName}`, () => { expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniH-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniH-test.js index dcbd78a42c604d..4e9e116b9619cb 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniH-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleJniH-test.js @@ -22,7 +22,11 @@ describe('GenerateModuleJniH', () => { it(`can generate fixture ${fixtureName}`, () => { expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js index 5bfd8c79e07682..0d3fd81dd20694 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js @@ -12,7 +12,7 @@ 'use strict'; const fixtures = require('../__test_fixtures__/fixtures.js'); -const generator = require('../GenerateModuleMm.js'); +const generator = require('../GenerateModuleObjCpp'); describe('GenerateModuleMm', () => { Object.keys(fixtures) @@ -21,8 +21,18 @@ describe('GenerateModuleMm', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { + const output = generator.generate( + fixtureName, + fixture, + 'com.facebook.fbreact.specs', + ); expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + new Map([ + [ + `${fixtureName}-generated.mm`, + output.get(`${fixtureName}-generated.mm`), + ], + ]), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index 41d445cb0895b1..4b0e7d22201dcf 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -2,8 +2,7 @@ exports[`GenerateModuleCpp can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -20,17 +19,14 @@ namespace react { static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->difficult(rt, args[0].getObject(rt)); } - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->optionals(rt, args[0].getObject(rt)); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->optionalMethod(rt, args[0].getObject(rt), std::move(args[1].getObject(rt).getFunction(rt)), args[2].getObject(rt).getArray(rt)); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArrays(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getArrays(rt, args[0].getObject(rt)); return jsi::Value::undefined(); @@ -53,8 +49,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared exports[`GenerateModuleCpp can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -84,8 +79,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared exports[`GenerateModuleCpp can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -99,19 +93,18 @@ Map { namespace facebook { namespace react { -static jsi::Value __hostFunction_NativeAliasTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->getConstants(rt); +static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getConstants(rt); } - -static jsi::Value __hostFunction_NativeAliasTurboModuleCxxSpecJSI_cropImage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - static_cast(&turboModule)->cropImage(rt, args[0].getObject(rt)); +static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_cropImage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->cropImage(rt, args[0].getObject(rt)); return jsi::Value::undefined(); } -NativeAliasTurboModuleCxxSpecJSI::NativeAliasTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) +AliasTurboModuleCxxSpecJSI::AliasTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule(\\"AliasTurboModule\\", jsInvoker) { - methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeAliasTurboModuleCxxSpecJSI_getConstants}; - methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleCxxSpecJSI_cropImage}; + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_AliasTurboModuleCxxSpecJSI_getConstants}; + methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleCxxSpecJSI_cropImage}; } @@ -123,8 +116,7 @@ NativeAliasTurboModuleCxxSpecJSI::NativeAliasTurboModuleCxxSpecJSI(std::shared_p exports[`GenerateModuleCpp can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -158,7 +150,6 @@ NativeCameraRollManagerCxxSpecJSI::NativeCameraRollManagerCxxSpecJSI(std::shared methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerCxxSpecJSI_saveToCameraRoll}; methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerCxxSpecJSI_deletePhotos}; } - static jsi::Value __hostFunction_NativeImagePickerIOSCxxSpecJSI_openCameraDialog(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->openCameraDialog(rt, args[0].getObject(rt), std::move(args[1].getObject(rt).getFunction(rt)), std::move(args[2].getObject(rt).getFunction(rt))); return jsi::Value::undefined(); @@ -168,27 +159,22 @@ NativeImagePickerIOSCxxSpecJSI::NativeImagePickerIOSCxxSpecJSI(std::shared_ptr(&turboModule)->reportFatalException(rt, args[0].getString(rt), args[1].getObject(rt).getArray(rt), args[2].getNumber()); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportSoftException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->reportSoftException(rt, args[0].getString(rt), args[1].getObject(rt).getArray(rt), args[2].getNumber()); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->reportException(rt, args[0].getObject(rt)); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_updateExceptionMessage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->updateExceptionMessage(rt, args[0].getString(rt), args[1].getObject(rt).getArray(rt), args[2].getNumber()); return jsi::Value::undefined(); } - static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_dismissRedbox(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->dismissRedbox(rt); return jsi::Value::undefined(); @@ -212,8 +198,7 @@ NativeExceptionsManagerCxxSpecJSI::NativeExceptionsManagerCxxSpecJSI(std::shared exports[`GenerateModuleCpp can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -230,7 +215,6 @@ namespace react { static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getConstants(rt); } - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->voidFunc(rt); return jsi::Value::undefined(); @@ -256,7 +240,6 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(js static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue(rt, args[0].getNumber(), args[1].getString(rt), args[2].getObject(rt)); } - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback(rt, std::move(args[0].getObject(rt).getFunction(rt))); return jsi::Value::undefined(); @@ -289,8 +272,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared exports[`GenerateModuleCpp can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "NativeModules.cpp" => " -/** + "NativeModules.cpp" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -304,7 +286,6 @@ Map { namespace facebook { namespace react { - static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->voidFunc(rt); return jsi::Value::undefined(); @@ -314,64 +295,18 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared : TurboModule(\\"SampleTurboModule\\", jsInvoker) { methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc}; } -static jsi::Value __hostFunction_NativeSample2TurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->getConstants(rt); -} - -static jsi::Value __hostFunction_NativeSample2TurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - static_cast(&turboModule)->voidFunc(rt); - return jsi::Value::undefined(); -} - -NativeSample2TurboModuleCxxSpecJSI::NativeSample2TurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) - : TurboModule(\\"Sample2TurboModule\\", jsInvoker) { - methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleCxxSpecJSI_getConstants}; - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleCxxSpecJSI_voidFunc}; -} - - -} // namespace react -} // namespace facebook -", -} -`; - -exports[`GenerateModuleCpp can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "NativeModules.cpp" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleH.js - */ - -#include - -namespace facebook { -namespace react { - - -static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - static_cast(&turboModule)->voidFunc(rt); - return jsi::Value::undefined(); +static jsi::Value __hostFunction_NativeSampleTurboModule2CxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getConstants(rt); } - -NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) - : TurboModule(\\"SampleTurboModule\\", jsInvoker) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc}; -} - -static jsi::Value __hostFunction_NativeSample2TurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - static_cast(&turboModule)->voidFunc(rt); +static jsi::Value __hostFunction_NativeSampleTurboModule2CxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->voidFunc(rt); return jsi::Value::undefined(); } -NativeSample2TurboModuleCxxSpecJSI::NativeSample2TurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) - : TurboModule(\\"Sample2TurboModule\\", jsInvoker) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleCxxSpecJSI_voidFunc}; +NativeSampleTurboModule2CxxSpecJSI::NativeSampleTurboModule2CxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule(\\"SampleTurboModule2\\", jsInvoker) { + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2CxxSpecJSI_getConstants}; + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2CxxSpecJSI_voidFunc}; } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index fbdcb15bae2c68..318f5c85f43ed1 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -17,7 +17,6 @@ Map { namespace facebook { namespace react { - class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -53,7 +52,6 @@ Map { namespace facebook { namespace react { - class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -86,10 +84,9 @@ Map { namespace facebook { namespace react { - -class JSI_EXPORT NativeAliasTurboModuleCxxSpecJSI : public TurboModule { +class JSI_EXPORT AliasTurboModuleCxxSpecJSI : public TurboModule { protected: - NativeAliasTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); + AliasTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); public: virtual jsi::Object getConstants(jsi::Runtime &rt) = 0; @@ -120,7 +117,6 @@ Map { namespace facebook { namespace react { - class JSI_EXPORT NativeCameraRollManagerCxxSpecJSI : public TurboModule { protected: NativeCameraRollManagerCxxSpecJSI(std::shared_ptr jsInvoker); @@ -132,7 +128,6 @@ virtual jsi::Value saveToCameraRoll(jsi::Runtime &rt, const jsi::String &uri, co virtual jsi::Value deletePhotos(jsi::Runtime &rt, const jsi::Array &assets) = 0; }; - class JSI_EXPORT NativeImagePickerIOSCxxSpecJSI : public TurboModule { protected: NativeImagePickerIOSCxxSpecJSI(std::shared_ptr jsInvoker); @@ -141,7 +136,6 @@ public: virtual void openCameraDialog(jsi::Runtime &rt, const jsi::Object &config, const jsi::Function &successCallback, const jsi::Function &cancelCallback) = 0; }; - class JSI_EXPORT NativeExceptionsManagerCxxSpecJSI : public TurboModule { protected: NativeExceptionsManagerCxxSpecJSI(std::shared_ptr jsInvoker); @@ -178,7 +172,6 @@ Map { namespace facebook { namespace react { - class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -221,7 +214,6 @@ Map { namespace facebook { namespace react { - class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -230,10 +222,9 @@ public: virtual void voidFunc(jsi::Runtime &rt) = 0; }; - -class JSI_EXPORT NativeSample2TurboModuleCxxSpecJSI : public TurboModule { +class JSI_EXPORT NativeSampleTurboModule2CxxSpecJSI : public TurboModule { protected: - NativeSample2TurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); + NativeSampleTurboModule2CxxSpecJSI(std::shared_ptr jsInvoker); public: virtual jsi::Object getConstants(jsi::Runtime &rt) = 0; @@ -246,45 +237,3 @@ virtual void voidFunc(jsi::Runtime &rt) = 0; ", } `; - -exports[`GenerateModuleH can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "NativeModules.h" => "/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleH.js - */ - -#pragma once - -#include - -namespace facebook { -namespace react { - -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { -protected: - NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); - -public: -virtual void voidFunc(jsi::Runtime &rt) = 0; - -}; - -class JSI_EXPORT NativeSample2TurboModuleCxxSpecJSI : public TurboModule { -protected: - NativeSample2TurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); - -public: -virtual void voidFunc(jsi::Runtime &rt) = 0; - -}; - -} // namespace react -} // namespace facebook -", -} -`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index 939b9bcea8d2f2..232d40e7dc114b 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -2,55 +2,32 @@ exports[`GenerateModuleHObjCpp can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "SampleSpec.h" => " -/** + "COMPLEX_OBJECTS.h" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleHObjCpp.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif - -#import - #import - -#import - #import #import #import - #import #import #import - #import - - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecOptionalsAOptionalObjectProperty { - double x() const; - double y() const; - - SpecOptionalsAOptionalObjectProperty(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json; -@end - +#import +#import namespace JS { namespace NativeSampleTurboModule { @@ -70,64 +47,39 @@ namespace JS { @interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json; @end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecGetArraysOptionsArrayOfObjectsElement { - double numberProperty() const; - - SpecGetArraysOptionsArrayOfObjectsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json; -@end - - namespace JS { namespace NativeSampleTurboModule { - struct SpecGetArraysOptions { - facebook::react::LazyVector arrayOfNumbers() const; - folly::Optional> optionalArrayOfNumbers() const; - facebook::react::LazyVector arrayOfStrings() const; - folly::Optional> optionalArrayOfStrings() const; - facebook::react::LazyVector arrayOfObjects() const; + struct SpecDifficultA { + bool D() const; + JS::NativeSampleTurboModule::SpecDifficultAE E() const; + NSString *F() const; - SpecGetArraysOptions(NSDictionary *const v) : _v(v) {} + SpecDifficultA(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json; @end - - namespace JS { namespace NativeSampleTurboModule { - struct SpecOptionalMethodExtrasElement { - NSString *key() const; - id value() const; + struct SpecOptionalsAOptionalObjectProperty { + double x() const; + double y() const; - SpecOptionalMethodExtrasElement(NSDictionary *const v) : _v(v) {} + SpecOptionalsAOptionalObjectProperty(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalMethodExtrasElement) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalMethodExtrasElement:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json; @end - - namespace JS { namespace NativeSampleTurboModule { struct SpecOptionalsA { @@ -147,356 +99,263 @@ namespace JS { @interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json; @end - - namespace JS { namespace NativeSampleTurboModule { - struct SpecDifficultReturnType { - bool D() const; - double E() const; - NSString *F() const; + struct SpecGetArraysOptionsArrayOfObjectsElement { + double numberProperty() const; - SpecDifficultReturnType(NSDictionary *const v) : _v(v) {} + SpecGetArraysOptionsArrayOfObjectsElement(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultReturnType:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json; @end - - namespace JS { namespace NativeSampleTurboModule { - struct SpecDifficultA { - bool D() const; - JS::NativeSampleTurboModule::SpecDifficultAE E() const; - NSString *F() const; + struct SpecGetArraysOptions { + facebook::react::LazyVector arrayOfNumbers() const; + folly::Optional> optionalArrayOfNumbers() const; + facebook::react::LazyVector arrayOfStrings() const; + folly::Optional> optionalArrayOfStrings() const; + facebook::react::LazyVector arrayOfObjects() const; - SpecDifficultA(NSDictionary *const v) : _v(v) {} + SpecGetArraysOptions(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json; @end +@protocol NativeSampleTurboModuleSpec -inline bool JS::NativeSampleTurboModule::SpecDifficultA::D() const +- (NSDictionary *)difficult:(JS::NativeSampleTurboModule::SpecDifficultA &)A; +- (void)optionals:(JS::NativeSampleTurboModule::SpecOptionalsA &)A; +- (void)optionalMethod:(NSDictionary *)options + callback:(RCTResponseSenderBlock)callback + extras:(NSArray *)extras; +- (void)getArrays:(JS::NativeSampleTurboModule::SpecGetArraysOptions &)options; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeSampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +inline bool JS::NativeSampleTurboModule::SpecDifficultAE::D() const { id const p = _v[@\\"D\\"]; return RCTBridgingToBool(p); } - - -inline JS::NativeSampleTurboModule::SpecDifficultAE JS::NativeSampleTurboModule::SpecDifficultA::E() const +inline double JS::NativeSampleTurboModule::SpecDifficultAE::E() const { id const p = _v[@\\"E\\"]; - return JS::NativeSampleTurboModule::SpecDifficultAE(p); + return RCTBridgingToDouble(p); } - - -inline NSString *JS::NativeSampleTurboModule::SpecDifficultA::F() const +inline NSString *JS::NativeSampleTurboModule::SpecDifficultAE::F() const { id const p = _v[@\\"F\\"]; return RCTBridgingToString(p); } - - -inline bool JS::NativeSampleTurboModule::SpecDifficultReturnType::D() const +inline double JS::NativeSampleTurboModule::SpecDifficultAE::id_() const +{ + id const p = _v[@\\"id\\"]; + return RCTBridgingToDouble(p); +} +inline bool JS::NativeSampleTurboModule::SpecDifficultA::D() const { id const p = _v[@\\"D\\"]; return RCTBridgingToBool(p); } - - -inline double JS::NativeSampleTurboModule::SpecDifficultReturnType::E() const +inline JS::NativeSampleTurboModule::SpecDifficultAE JS::NativeSampleTurboModule::SpecDifficultA::E() const { id const p = _v[@\\"E\\"]; - return RCTBridgingToDouble(p); + return JS::NativeSampleTurboModule::SpecDifficultAE(p); } - - -inline NSString *JS::NativeSampleTurboModule::SpecDifficultReturnType::F() const +inline NSString *JS::NativeSampleTurboModule::SpecDifficultA::F() const { id const p = _v[@\\"F\\"]; return RCTBridgingToString(p); } - - +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::x() const +{ + id const p = _v[@\\"x\\"]; + return RCTBridgingToDouble(p); +} +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::y() const +{ + id const p = _v[@\\"y\\"]; + return RCTBridgingToDouble(p); +} inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalNumberProperty() const { id const p = _v[@\\"optionalNumberProperty\\"]; return RCTBridgingToOptionalDouble(p); } - - inline folly::Optional> JS::NativeSampleTurboModule::SpecOptionalsA::optionalArrayProperty() const { id const p = _v[@\\"optionalArrayProperty\\"]; return RCTBridgingToOptionalVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); }); } - - inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalObjectProperty() const { id const p = _v[@\\"optionalObjectProperty\\"]; return (p == nil ? folly::none : folly::make_optional(JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty(p))); } - - inline id _Nullable JS::NativeSampleTurboModule::SpecOptionalsA::optionalGenericObjectProperty() const { id const p = _v[@\\"optionalGenericObjectProperty\\"]; return p; } - - inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalBooleanTypeProperty() const { id const p = _v[@\\"optionalBooleanTypeProperty\\"]; return RCTBridgingToOptionalBool(p); } - - -inline NSString *JS::NativeSampleTurboModule::SpecOptionalMethodExtrasElement::key() const -{ - id const p = _v[@\\"key\\"]; - return RCTBridgingToString(p); -} - - -inline id JS::NativeSampleTurboModule::SpecOptionalMethodExtrasElement::value() const +inline double JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement::numberProperty() const { - id const p = _v[@\\"value\\"]; - return p; + id const p = _v[@\\"numberProperty\\"]; + return RCTBridgingToDouble(p); } - - inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfNumbers() const { id const p = _v[@\\"arrayOfNumbers\\"]; return RCTBridgingToVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); }); } - - inline folly::Optional> JS::NativeSampleTurboModule::SpecGetArraysOptions::optionalArrayOfNumbers() const { id const p = _v[@\\"optionalArrayOfNumbers\\"]; return RCTBridgingToOptionalVec(p, ^double(id itemValue_0) { return RCTBridgingToDouble(itemValue_0); }); } - - inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfStrings() const { id const p = _v[@\\"arrayOfStrings\\"]; return RCTBridgingToVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); } - - inline folly::Optional> JS::NativeSampleTurboModule::SpecGetArraysOptions::optionalArrayOfStrings() const { id const p = _v[@\\"optionalArrayOfStrings\\"]; return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); } - - -inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfObjects() const +inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfObjects() const { id const p = _v[@\\"arrayOfObjects\\"]; - return RCTBridgingToVec(p, ^JS::NativeSampleTurboModule::arrayOfObjectsElement(id itemValue_0) { return JS::NativeSampleTurboModule::arrayOfObjectsElement(itemValue_0); }); -} - - -inline double JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement::numberProperty() const -{ - id const p = _v[@\\"numberProperty\\"]; - return RCTBridgingToDouble(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecDifficultAE::D() const -{ - id const p = _v[@\\"D\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecDifficultAE::E() const -{ - id const p = _v[@\\"E\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecDifficultAE::F() const -{ - id const p = _v[@\\"F\\"]; - return RCTBridgingToString(p); + return RCTBridgingToVec(p, ^JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(id itemValue_0) { return JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(itemValue_0); }); } - - -inline double JS::NativeSampleTurboModule::SpecDifficultAE::id_() const -{ - id const p = _v[@\\"id_\\"]; - return RCTBridgingToDouble(p); +", } +`; +exports[`GenerateModuleHObjCpp can generate fixture EMPTY_NATIVE_MODULES 1`] = ` +Map { + "EMPTY_NATIVE_MODULES.h" => "/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ -inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::x() const -{ - id const p = _v[@\\"x\\"]; - return RCTBridgingToDouble(p); -} +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import -inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::y() const -{ - id const p = _v[@\\"y\\"]; - return RCTBridgingToDouble(p); -} +@protocol NativeSampleTurboModuleSpec -@protocol NativeSampleTurboModuleSpec -- (NSDictionary *) difficult:(JS::NativeSampleTurboModule::SpecDifficultA &)A; -- (void) optionals:(JS::NativeSampleTurboModule::SpecOptionalsA &)A; -- (void) optionalMethod:(NSDictionary *)options - callback:(RCTResponseSenderBlock)callback - extras:(NSArray * _Nullable)extras; -- (void) getArrays:(JS::NativeSampleTurboModule::SpecGetArraysOptions &)options; @end - - namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'NativeSampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook + ", } `; -exports[`GenerateModuleHObjCpp can generate fixture EMPTY_NATIVE_MODULES 1`] = ` +exports[`GenerateModuleHObjCpp can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "SampleSpec.h" => " -/** + "NATIVE_MODULES_WITH_TYPE_ALIASES.h" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleHObjCpp.js - */ - -#ifndef __cplusplus -#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. -#endif - -#import - -#import - -#import - -#import -#import -#import - -#import -#import -#import - -#import - - - - - -@protocol NativeSampleTurboModuleSpec - -@end - - -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SampleTurboModule' - */ - class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook -", -} -`; - -exports[`GenerateModuleHObjCpp can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` -Map { - "SampleSpec.h" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. + * @generated by codegen project: GenerateModuleObjCpp * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleHObjCpp.js + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif - -#import - #import - -#import - #import #import #import - #import #import #import - #import - - +#import +#import namespace JS { - namespace NativeAliasTurboModule { - struct OptionsDisplaySize { - double width() const; - double height() const; + namespace AliasTurboModule { + struct OptionsOffset { + double x() const; + double y() const; - OptionsDisplaySize(NSDictionary *const v) : _v(v) {} + OptionsOffset(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeAliasTurboModule_OptionsDisplaySize) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsDisplaySize:(id)json; +@interface RCTCxxConvert (AliasTurboModule_OptionsOffset) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsOffset:(id)json; @end - - namespace JS { - namespace NativeAliasTurboModule { + namespace AliasTurboModule { struct OptionsSize { double width() const; double height() const; @@ -508,35 +367,31 @@ namespace JS { } } -@interface RCTCxxConvert (NativeAliasTurboModule_OptionsSize) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsSize:(id)json; +@interface RCTCxxConvert (AliasTurboModule_OptionsSize) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsSize:(id)json; @end - - namespace JS { - namespace NativeAliasTurboModule { - struct OptionsOffset { - double x() const; - double y() const; + namespace AliasTurboModule { + struct OptionsDisplaySize { + double width() const; + double height() const; - OptionsOffset(NSDictionary *const v) : _v(v) {} + OptionsDisplaySize(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeAliasTurboModule_OptionsOffset) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsOffset:(id)json; +@interface RCTCxxConvert (AliasTurboModule_OptionsDisplaySize) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsDisplaySize:(id)json; @end - - namespace JS { - namespace NativeAliasTurboModule { + namespace AliasTurboModule { struct Options { - JS::NativeAliasTurboModule::OptionsOffset offset() const; - JS::NativeAliasTurboModule::OptionsSize size() const; - folly::Optional displaySize() const; + JS::AliasTurboModule::OptionsOffset offset() const; + JS::AliasTurboModule::OptionsSize size() const; + folly::Optional displaySize() const; NSString *resizeMode() const; folly::Optional allowExternalStorage() const; @@ -547,756 +402,402 @@ namespace JS { } } -@interface RCTCxxConvert (NativeAliasTurboModule_Options) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_Options:(id)json; +@interface RCTCxxConvert (AliasTurboModule_Options) ++ (RCTManagedPointer *)JS_AliasTurboModule_Options:(id)json; @end +@protocol AliasTurboModuleSpec -inline JS::NativeAliasTurboModule::OptionsOffset JS::NativeAliasTurboModule::Options::offset() const -{ - id const p = _v[@\\"offset\\"]; - return JS::NativeAliasTurboModule::OptionsOffset(p); -} - - -inline JS::NativeAliasTurboModule::OptionsSize JS::NativeAliasTurboModule::Options::size() const -{ - id const p = _v[@\\"size\\"]; - return JS::NativeAliasTurboModule::OptionsSize(p); -} - - -inline folly::Optional JS::NativeAliasTurboModule::Options::displaySize() const -{ - id const p = _v[@\\"displaySize\\"]; - return (p == nil ? folly::none : folly::make_optional(JS::NativeAliasTurboModule::OptionsDisplaySize(p))); -} - - -inline NSString *JS::NativeAliasTurboModule::Options::resizeMode() const -{ - id const p = _v[@\\"resizeMode\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeAliasTurboModule::Options::allowExternalStorage() const -{ - id const p = _v[@\\"allowExternalStorage\\"]; - return RCTBridgingToOptionalBool(p); -} - +- (void)cropImage:(JS::AliasTurboModule::Options &)cropData; -inline double JS::NativeAliasTurboModule::OptionsOffset::x() const +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'AliasTurboModule' + */ + class JSI_EXPORT AliasTurboModuleSpecJSI : public ObjCTurboModule { + public: + AliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +inline double JS::AliasTurboModule::OptionsOffset::x() const { id const p = _v[@\\"x\\"]; return RCTBridgingToDouble(p); } - - -inline double JS::NativeAliasTurboModule::OptionsOffset::y() const +inline double JS::AliasTurboModule::OptionsOffset::y() const { id const p = _v[@\\"y\\"]; return RCTBridgingToDouble(p); } - - -inline double JS::NativeAliasTurboModule::OptionsSize::width() const +inline double JS::AliasTurboModule::OptionsSize::width() const { id const p = _v[@\\"width\\"]; return RCTBridgingToDouble(p); } - - -inline double JS::NativeAliasTurboModule::OptionsSize::height() const +inline double JS::AliasTurboModule::OptionsSize::height() const { id const p = _v[@\\"height\\"]; return RCTBridgingToDouble(p); } - - -inline double JS::NativeAliasTurboModule::OptionsDisplaySize::width() const +inline double JS::AliasTurboModule::OptionsDisplaySize::width() const { id const p = _v[@\\"width\\"]; return RCTBridgingToDouble(p); } - - -inline double JS::NativeAliasTurboModule::OptionsDisplaySize::height() const +inline double JS::AliasTurboModule::OptionsDisplaySize::height() const { id const p = _v[@\\"height\\"]; return RCTBridgingToDouble(p); } - - - -@protocol NativeAliasTurboModuleSpec - -- (void) cropImage:(JS::NativeAliasTurboModule::Options &)cropData; -@end - - -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AliasTurboModule' - */ - class JSI_EXPORT NativeAliasTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeAliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook +inline JS::AliasTurboModule::OptionsOffset JS::AliasTurboModule::Options::offset() const +{ + id const p = _v[@\\"offset\\"]; + return JS::AliasTurboModule::OptionsOffset(p); +} +inline JS::AliasTurboModule::OptionsSize JS::AliasTurboModule::Options::size() const +{ + id const p = _v[@\\"size\\"]; + return JS::AliasTurboModule::OptionsSize(p); +} +inline folly::Optional JS::AliasTurboModule::Options::displaySize() const +{ + id const p = _v[@\\"displaySize\\"]; + return (p == nil ? folly::none : folly::make_optional(JS::AliasTurboModule::OptionsDisplaySize(p))); +} +inline NSString *JS::AliasTurboModule::Options::resizeMode() const +{ + id const p = _v[@\\"resizeMode\\"]; + return RCTBridgingToOptionalString(p); +} +inline folly::Optional JS::AliasTurboModule::Options::allowExternalStorage() const +{ + id const p = _v[@\\"allowExternalStorage\\"]; + return RCTBridgingToOptionalBool(p); +} ", } `; exports[`GenerateModuleHObjCpp can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "SampleSpec.h" => " -/** + "REAL_MODULE_EXAMPLE.h" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleHObjCpp.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif - -#import - #import - -#import - #import #import #import - #import #import #import - #import - - +#import +#import namespace JS { namespace NativeCameraRollManager { - struct PhotoIdentifierNodeLocation { - double longitude() const; - double latitude() const; - folly::Optional altitude() const; - folly::Optional heading() const; - folly::Optional speed() const; - - PhotoIdentifierNodeLocation(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json; -@end - + struct GetPhotosParams { + double first() const; + NSString *after() const; + NSString *groupName() const; + NSString *groupTypes() const; + NSString *assetType() const; + folly::Optional maxSize() const; + folly::Optional> mimeTypes() const; -namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifierNode { - JS::NativeCameraRollManager::PhotoIdentifierImage image() const; - NSString *type() const; - NSString *group_name() const; - double timestamp() const; - JS::NativeCameraRollManager::PhotoIdentifierNodeLocation location() const; - - PhotoIdentifierNode(NSDictionary *const v) : _v(v) {} + GetPhotosParams(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json; +@interface RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) ++ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json; @end +@protocol NativeCameraRollManagerSpec +- (void)getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)saveToCameraRoll:(NSString *)uri + type:(NSString *)type + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)deletePhotos:(NSArray *)assets + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; -namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifiersPagePage_info { - bool has_next_page() const; - NSString *start_cursor() const; - NSString *end_cursor() const; - - PhotoIdentifiersPagePage_info(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json; @end - - +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeCameraRollManager' + */ + class JSI_EXPORT NativeCameraRollManagerSpecJSI : public ObjCTurboModule { + public: + NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifierImage { - NSString *uri() const; - double playableDuration() const; - double width() const; - double height() const; - folly::Optional isStored() const; - NSString *filename() const; + namespace NativeExceptionsManager { + struct StackFrame { + folly::Optional column() const; + NSString *file() const; + folly::Optional lineNumber() const; + NSString *methodName() const; + folly::Optional collapse() const; - PhotoIdentifierImage(NSDictionary *const v) : _v(v) {} + StackFrame(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json; +@interface RCTCxxConvert (NativeExceptionsManager_StackFrame) ++ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json; @end - - namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifier { - JS::NativeCameraRollManager::PhotoIdentifierNode node() const; + namespace NativeExceptionsManager { + struct ExceptionData { + NSString *message() const; + NSString *originalMessage() const; + NSString *name() const; + NSString *componentStack() const; + facebook::react::LazyVector stack() const; + double id_() const; + bool isFatal() const; + id _Nullable extraData() const; - PhotoIdentifier(NSDictionary *const v) : _v(v) {} + ExceptionData(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json; +@interface RCTCxxConvert (NativeExceptionsManager_ExceptionData) ++ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json; @end +@protocol NativeExceptionsManagerSpec +- (void)reportFatalException:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)reportSoftException:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)reportException:(JS::NativeExceptionsManager::ExceptionData &)data; +- (void)updateExceptionMessage:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)dismissRedbox; +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeExceptionsManager' + */ + class JSI_EXPORT NativeExceptionsManagerSpecJSI : public ObjCTurboModule { + public: + NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifiersPage { - facebook::react::LazyVector edges() const; - JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info page_info() const; + namespace NativeImagePickerIOS { + struct SpecOpenCameraDialogConfig { + bool unmirrorFrontFacingCamera() const; + bool videoMode() const; - PhotoIdentifiersPage(NSDictionary *const v) : _v(v) {} + SpecOpenCameraDialogConfig(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json; +@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) ++ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json; @end +@protocol NativeImagePickerIOSSpec +- (void)openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config + successCallback:(RCTResponseSenderBlock)successCallback + cancelCallback:(RCTResponseSenderBlock)cancelCallback; -namespace JS { - namespace NativeCameraRollManager { - struct GetPhotosParams { - double first() const; - NSString *after() const; - NSString *groupName() const; - NSString *groupTypes() const; - NSString *assetType() const; - folly::Optional maxSize() const; - folly::Optional> mimeTypes() const; - - GetPhotosParams(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json; @end - +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NativeImagePickerIOS' + */ + class JSI_EXPORT NativeImagePickerIOSSpecJSI : public ObjCTurboModule { + public: + NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook inline double JS::NativeCameraRollManager::GetPhotosParams::first() const { id const p = _v[@\\"first\\"]; return RCTBridgingToDouble(p); } - - inline NSString *JS::NativeCameraRollManager::GetPhotosParams::after() const { id const p = _v[@\\"after\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } - - inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupName() const { id const p = _v[@\\"groupName\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } - - inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupTypes() const { id const p = _v[@\\"groupTypes\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } - - inline NSString *JS::NativeCameraRollManager::GetPhotosParams::assetType() const { id const p = _v[@\\"assetType\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } - - inline folly::Optional JS::NativeCameraRollManager::GetPhotosParams::maxSize() const { id const p = _v[@\\"maxSize\\"]; return RCTBridgingToOptionalDouble(p); } - - inline folly::Optional> JS::NativeCameraRollManager::GetPhotosParams::mimeTypes() const { id const p = _v[@\\"mimeTypes\\"]; return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); }); } - - -inline facebook::react::LazyVector JS::NativeCameraRollManager::PhotoIdentifiersPage::edges() const -{ - id const p = _v[@\\"edges\\"]; - return RCTBridgingToVec(p, ^JS::NativeCameraRollManager::PhotoIdentifier(id itemValue_0) { return JS::NativeCameraRollManager::PhotoIdentifier(itemValue_0); }); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info JS::NativeCameraRollManager::PhotoIdentifiersPage::page_info() const -{ - id const p = _v[@\\"page_info\\"]; - return JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierNode JS::NativeCameraRollManager::PhotoIdentifier::node() const -{ - id const p = _v[@\\"node\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierNode(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::uri() const -{ - id const p = _v[@\\"uri\\"]; - return RCTBridgingToString(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::playableDuration() const -{ - id const p = _v[@\\"playableDuration\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::width() const -{ - id const p = _v[@\\"width\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::height() const -{ - id const p = _v[@\\"height\\"]; - return RCTBridgingToDouble(p); -} - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierImage::isStored() const -{ - id const p = _v[@\\"isStored\\"]; - return RCTBridgingToOptionalBool(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::filename() const -{ - id const p = _v[@\\"filename\\"]; - return RCTBridgingToString(p); -} - - -inline bool JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::has_next_page() const -{ - id const p = _v[@\\"has_next_page\\"]; - return RCTBridgingToBool(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::start_cursor() const -{ - id const p = _v[@\\"start_cursor\\"]; - return RCTBridgingToString(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::end_cursor() const -{ - id const p = _v[@\\"end_cursor\\"]; - return RCTBridgingToString(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierImage JS::NativeCameraRollManager::PhotoIdentifierNode::image() const -{ - id const p = _v[@\\"image\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierImage(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::type() const -{ - id const p = _v[@\\"type\\"]; - return RCTBridgingToString(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::group_name() const -{ - id const p = _v[@\\"group_name\\"]; - return RCTBridgingToString(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierNode::timestamp() const -{ - id const p = _v[@\\"timestamp\\"]; - return RCTBridgingToDouble(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierNodeLocation JS::NativeCameraRollManager::PhotoIdentifierNode::location() const -{ - id const p = _v[@\\"location\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierNodeLocation(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::longitude() const -{ - id const p = _v[@\\"longitude\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::latitude() const -{ - id const p = _v[@\\"latitude\\"]; - return RCTBridgingToDouble(p); -} - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::altitude() const +inline folly::Optional JS::NativeExceptionsManager::StackFrame::column() const { - id const p = _v[@\\"altitude\\"]; + id const p = _v[@\\"column\\"]; return RCTBridgingToOptionalDouble(p); } - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::heading() const +inline NSString *JS::NativeExceptionsManager::StackFrame::file() const { - id const p = _v[@\\"heading\\"]; - return RCTBridgingToOptionalDouble(p); + id const p = _v[@\\"file\\"]; + return RCTBridgingToString(p); } - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::speed() const +inline folly::Optional JS::NativeExceptionsManager::StackFrame::lineNumber() const { - id const p = _v[@\\"speed\\"]; + id const p = _v[@\\"lineNumber\\"]; return RCTBridgingToOptionalDouble(p); } - - - -@protocol NativeCameraRollManagerSpec - -- (void) getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void) saveToCameraRoll:(NSString *)uri - type:(NSString *)type - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void) deletePhotos:(NSArray *)assets - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -@end - - - -namespace JS { - namespace NativeExceptionsManager { - struct StackFrame { - folly::Optional column() const; - NSString *file() const; - folly::Optional lineNumber() const; - NSString *methodName() const; - folly::Optional collapse() const; - - StackFrame(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeExceptionsManager_StackFrame) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json; -@end - - -namespace JS { - namespace NativeExceptionsManager { - struct ExceptionData { - NSString *message() const; - NSString *originalMessage() const; - NSString *name() const; - NSString *componentStack() const; - facebook::react::LazyVector stack() const; - double id_() const; - bool isFatal() const; - id _Nullable extraData() const; - - ExceptionData(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } +inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const +{ + id const p = _v[@\\"methodName\\"]; + return RCTBridgingToString(p); +} +inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const +{ + id const p = _v[@\\"collapse\\"]; + return RCTBridgingToOptionalBool(p); } - -@interface RCTCxxConvert (NativeExceptionsManager_ExceptionData) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json; -@end - inline NSString *JS::NativeExceptionsManager::ExceptionData::message() const { id const p = _v[@\\"message\\"]; return RCTBridgingToString(p); } - - inline NSString *JS::NativeExceptionsManager::ExceptionData::originalMessage() const { id const p = _v[@\\"originalMessage\\"]; return RCTBridgingToString(p); } - - inline NSString *JS::NativeExceptionsManager::ExceptionData::name() const { id const p = _v[@\\"name\\"]; return RCTBridgingToString(p); } - - inline NSString *JS::NativeExceptionsManager::ExceptionData::componentStack() const { id const p = _v[@\\"componentStack\\"]; return RCTBridgingToString(p); } - - inline facebook::react::LazyVector JS::NativeExceptionsManager::ExceptionData::stack() const { id const p = _v[@\\"stack\\"]; return RCTBridgingToVec(p, ^JS::NativeExceptionsManager::StackFrame(id itemValue_0) { return JS::NativeExceptionsManager::StackFrame(itemValue_0); }); } - - inline double JS::NativeExceptionsManager::ExceptionData::id_() const { - id const p = _v[@\\"id_\\"]; + id const p = _v[@\\"id\\"]; return RCTBridgingToDouble(p); } - - inline bool JS::NativeExceptionsManager::ExceptionData::isFatal() const { id const p = _v[@\\"isFatal\\"]; return RCTBridgingToBool(p); } - - inline id _Nullable JS::NativeExceptionsManager::ExceptionData::extraData() const { id const p = _v[@\\"extraData\\"]; return p; } - - -inline folly::Optional JS::NativeExceptionsManager::StackFrame::column() const -{ - id const p = _v[@\\"column\\"]; - return RCTBridgingToOptionalDouble(p); -} - - -inline NSString *JS::NativeExceptionsManager::StackFrame::file() const -{ - id const p = _v[@\\"file\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeExceptionsManager::StackFrame::lineNumber() const -{ - id const p = _v[@\\"lineNumber\\"]; - return RCTBridgingToOptionalDouble(p); -} - - -inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const -{ - id const p = _v[@\\"methodName\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const -{ - id const p = _v[@\\"collapse\\"]; - return RCTBridgingToOptionalBool(p); -} - - - -@protocol NativeExceptionsManagerSpec -- (void) reportFatalException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) reportSoftException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) reportException:(JS::NativeExceptionsManager::ExceptionData &)data; -- (void) updateExceptionMessage:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) dismissRedbox; -@end - - - -namespace JS { - namespace NativeImagePickerIOS { - struct SpecOpenCameraDialogConfig { - bool unmirrorFrontFacingCamera() const; - bool videoMode() const; - - SpecOpenCameraDialogConfig(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json; -@end - inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::unmirrorFrontFacingCamera() const { id const p = _v[@\\"unmirrorFrontFacingCamera\\"]; return RCTBridgingToBool(p); } - - inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::videoMode() const { id const p = _v[@\\"videoMode\\"]; return RCTBridgingToBool(p); } - - - -@protocol NativeImagePickerIOSSpec -- (void) openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config - successCallback:(RCTResponseSenderBlock)successCallback - cancelCallback:(RCTResponseSenderBlock)cancelCallback; -@end - - -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'CameraRollManager' - */ - class JSI_EXPORT NativeCameraRollManagerSpecJSI : public ObjCTurboModule { - public: - NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - /** - * ObjC++ class for module 'ExceptionsManager' - */ - class JSI_EXPORT NativeExceptionsManagerSpecJSI : public ObjCTurboModule { - public: - NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - /** - * ObjC++ class for module 'ImagePickerIOS' - */ - class JSI_EXPORT NativeImagePickerIOSSpecJSI : public ObjCTurboModule { - public: - NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook ", } `; exports[`GenerateModuleHObjCpp can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "SampleSpec.h" => " -/** + "SIMPLE_NATIVE_MODULES.h" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleHObjCpp.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif - -#import - #import - -#import - #import #import #import - #import #import #import - #import - - +#import +#import namespace JS { namespace NativeSampleTurboModule { @@ -1327,196 +828,119 @@ namespace JS { }; } } - -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto const1 = i.const1.get(); - d[@\\"const1\\"] = @(const1); -auto const2 = i.const2.get(); - d[@\\"const2\\"] = @(const2); -auto const3 = i.const3.get(); - d[@\\"const3\\"] = const3; - return d; -}) {} -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - - @protocol NativeSampleTurboModuleSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(BOOL)arg; +- (NSNumber *)getNumber:(double)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSNumber *)getRootTag:(double)arg; +- (NSDictionary *)getValue:(double)x + y:(NSString *)y + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; - (facebook::react::ModuleConstants)constantsToExport; - (facebook::react::ModuleConstants)getConstants; -- (void) voidFunc; -- (BOOL) getBool:(BOOL)arg; -- (NSNumber *) getNumber:(double)arg; -- (NSString *) getString:(NSString *)arg; -- (NSArray> *) getArray:(NSArray *)arg; -- (NSDictionary *) getObject:(NSDictionary *)arg; -- (NSNumber *) getRootTag:(double)arg; -- (NSDictionary *) getValue:(double)x - y:(NSString *)y - z:(NSDictionary *)z; -- (void) getValueWithCallback:(RCTResponseSenderBlock)callback; -- (void) getValueWithPromise:(BOOL)error - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -@end - +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'NativeSampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = @(const1); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = @(const2); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} ", } `; exports[`GenerateModuleHObjCpp can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "SampleSpec.h" => " -/** + "TWO_MODULES_DIFFERENT_FILES.h" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleHObjCpp.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ #ifndef __cplusplus #error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. #endif - -#import - #import - -#import - #import #import #import - #import #import #import - #import - - - - - -@protocol NativeSample2TurboModuleSpec - -- (void) voidFunc; -@end - - - +#import +#import @protocol NativeSampleTurboModuleSpec -- (void) voidFunc; -@end +- (void)voidFunc; +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'NativeSampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; - /** - * ObjC++ class for module 'Sample2TurboModule' - */ - class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; } // namespace react } // namespace facebook -", -} -`; - -exports[`GenerateModuleHObjCpp can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "SampleSpec.h" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleHObjCpp.js - */ - -#ifndef __cplusplus -#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. -#endif - -#import - -#import - -#import - -#import -#import -#import - -#import -#import -#import - -#import - - +@protocol NativeSampleTurboModule2Spec +- (void)voidFunc; -@protocol NativeSample2TurboModuleSpec -- (void) voidFunc; @end - - - - - -@protocol NativeSampleTurboModuleSpec -- (void) voidFunc; -@end - - namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ - class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - /** - * ObjC++ class for module 'Sample2TurboModule' - */ - class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { + * ObjC++ class for module 'NativeSampleTurboModule2' + */ + class JSI_EXPORT NativeSampleTurboModule2SpecJSI : public ObjCTurboModule { public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + NativeSampleTurboModule2SpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook + + ", } `; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap index 13eeb45cc922e6..5e314758e47c21 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap @@ -2,7 +2,8 @@ exports[`GenerateModuleJavaSpec can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -13,8 +14,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -31,15 +33,19 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo } @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract WritableMap difficult(ReadableMap A); @ReactMethod + @DoNotStrip public abstract void optionals(ReadableMap A); @ReactMethod - public abstract void optionalMethod(ReadableMap options, Callback callback, ReadableArray extras); + @DoNotStrip + public void optionalMethod(ReadableMap options, Callback callback, ReadableArray extras) {} @ReactMethod + @DoNotStrip public abstract void getArrays(ReadableMap options); } ", @@ -48,7 +54,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -59,8 +66,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -80,7 +88,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "NativeAliasTurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/AliasTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -91,8 +100,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -100,12 +110,13 @@ import com.facebook.react.bridge.ReactModuleWithSpec; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.turbomodule.core.interfaces.TurboModule; -public abstract class NativeAliasTurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeAliasTurboModuleSpec(ReactApplicationContext reactContext) { +public abstract class AliasTurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public AliasTurboModuleSpec(ReactApplicationContext reactContext) { super(reactContext); } @ReactMethod + @DoNotStrip public abstract void cropImage(ReadableMap cropData); } ", @@ -114,7 +125,8 @@ public abstract class NativeAliasTurboModuleSpec extends ReactContextBaseJavaMod exports[`GenerateModuleJavaSpec can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "NativeCameraRollManagerSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeCameraRollManagerSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -125,8 +137,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -142,16 +155,20 @@ public abstract class NativeCameraRollManagerSpec extends ReactContextBaseJavaMo } @ReactMethod + @DoNotStrip public abstract void getPhotos(ReadableMap params, Promise promise); @ReactMethod + @DoNotStrip public abstract void saveToCameraRoll(String uri, String type, Promise promise); @ReactMethod + @DoNotStrip public abstract void deletePhotos(ReadableArray assets, Promise promise); } ", - "NativeImagePickerIOSSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeExceptionsManagerSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -162,38 +179,9 @@ public abstract class NativeCameraRollManagerSpec extends ReactContextBaseJavaMo * @nolint */ -package com.facebook.fbreact.specs.beta; - -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeImagePickerIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeImagePickerIOSSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void openCameraDialog(ReadableMap config, Callback successCallback, Callback cancelCallback); -} -", - "NativeExceptionsManagerSpec.java" => "/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - * @generated by codegen project: GenerateModuleJavaSpec.js - * - * @nolint - */ - -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -208,19 +196,24 @@ public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaMo } @ReactMethod + @DoNotStrip public abstract void reportFatalException(String message, ReadableArray stack, double exceptionId); @ReactMethod + @DoNotStrip public abstract void reportSoftException(String message, ReadableArray stack, double exceptionId); @ReactMethod - public abstract void reportException(ReadableMap data); + @DoNotStrip + public void reportException(ReadableMap data) {} @ReactMethod + @DoNotStrip public abstract void updateExceptionMessage(String message, ReadableArray stack, double exceptionId); @ReactMethod - public abstract void dismissRedbox(); + @DoNotStrip + public void dismissRedbox() {} } ", } @@ -228,7 +221,8 @@ public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -239,8 +233,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; @@ -292,33 +287,43 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo } @ReactMethod + @DoNotStrip public abstract void voidFunc(); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract boolean getBool(boolean arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract double getNumber(double arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract String getString(String arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract WritableArray getArray(ReadableArray arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract WritableMap getObject(ReadableMap arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract double getRootTag(double arg); @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip public abstract WritableMap getValue(double x, String y, ReadableMap z); @ReactMethod + @DoNotStrip public abstract void getValueWithCallback(Callback callback); @ReactMethod + @DoNotStrip public abstract void getValueWithPromise(boolean error, Promise promise); } ", @@ -327,68 +332,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - * @generated by codegen project: GenerateModuleJavaSpec.js - * - * @nolint - */ - -package com.facebook.fbreact.specs.beta; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void voidFunc(); -} -", - "NativeSample2TurboModuleSpec.java" => "/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - * - * @generated by codegen project: GenerateModuleJavaSpec.js - * - * @nolint - */ - -package com.facebook.fbreact.specs.beta; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReactModuleWithSpec; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeSample2TurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSample2TurboModuleSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - public abstract void voidFunc(); -} -", -} -`; - -exports[`GenerateModuleJavaSpec can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "NativeSampleTurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -399,8 +344,9 @@ Map { * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -413,10 +359,12 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo } @ReactMethod + @DoNotStrip public abstract void voidFunc(); } ", - "NativeSample2TurboModuleSpec.java" => "/** + "java/com/facebook/fbreact/specs/NativeSampleTurboModule2Spec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -427,20 +375,22 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo * @nolint */ -package com.facebook.fbreact.specs.beta; +package com.facebook.fbreact.specs; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactModuleWithSpec; import com.facebook.react.turbomodule.core.interfaces.TurboModule; -public abstract class NativeSample2TurboModuleSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeSample2TurboModuleSpec(ReactApplicationContext reactContext) { +public abstract class NativeSampleTurboModule2Spec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public NativeSampleTurboModule2Spec(ReactApplicationContext reactContext) { super(reactContext); } @ReactMethod + @DoNotStrip public abstract void voidFunc(); } ", diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap index 3baa888f467312..328f1a34779a55 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap @@ -2,7 +2,7 @@ exports[`GenerateModuleJniCpp can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/COMPLEX_OBJECTS-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -12,12 +12,11 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"COMPLEX_OBJECTS.h\\" namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"difficult\\", \\"(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;\\", args, count); } @@ -42,6 +41,13 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays}; } +std::shared_ptr COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + return nullptr; +} + } // namespace react } // namespace facebook ", @@ -50,7 +56,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo exports[`GenerateModuleJniCpp can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/EMPTY_NATIVE_MODULES-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -60,7 +66,7 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"EMPTY_NATIVE_MODULES.h\\" namespace facebook { namespace react { @@ -72,6 +78,13 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo } +std::shared_ptr EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + return nullptr; +} + } // namespace react } // namespace facebook ", @@ -80,7 +93,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo exports[`GenerateModuleJniCpp can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/NATIVE_MODULES_WITH_TYPE_ALIASES-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -90,21 +103,27 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"NATIVE_MODULES_WITH_TYPE_ALIASES.h\\" namespace facebook { namespace react { -static facebook::jsi::Value __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { +static facebook::jsi::Value __hostFunction_AliasTurboModuleSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"cropImage\\", \\"(Lcom/facebook/react/bridge/ReadableMap;)V\\", args, count); } -NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) +AliasTurboModuleSpecJSI::AliasTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { + methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleSpecJSI_cropImage}; +} - methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage}; +std::shared_ptr NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"AliasTurboModule\\") { + return std::make_shared(params); + } + return nullptr; } } // namespace react @@ -115,7 +134,7 @@ NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const JavaTurboModu exports[`GenerateModuleJniCpp can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/REAL_MODULE_EXAMPLE-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -125,7 +144,7 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"REAL_MODULE_EXAMPLE.h\\" namespace facebook { namespace react { @@ -146,21 +165,10 @@ static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_delete NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; } - -static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"openCameraDialog\\", \\"(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V\\", args, count); -} - -NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - methodMap_[\\"openCameraDialog\\"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; -} - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"reportFatalException\\", \\"(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V\\", args, count); } @@ -190,6 +198,16 @@ NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const JavaTurboMo methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; } +std::shared_ptr REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"CameraRollManager\\") { + return std::make_shared(params); + } + if (moduleName == \\"ExceptionsManager\\") { + return std::make_shared(params); + } + return nullptr; +} + } // namespace react } // namespace facebook ", @@ -198,7 +216,7 @@ NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const JavaTurboMo exports[`GenerateModuleJniCpp can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/SIMPLE_NATIVE_MODULES-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -208,12 +226,11 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"SIMPLE_NATIVE_MODULES.h\\" namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getConstants\\", \\"()Ljava/util/Map;\\", args, count); } @@ -273,6 +290,13 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; } +std::shared_ptr SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + return nullptr; +} + } // namespace react } // namespace facebook ", @@ -281,7 +305,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo exports[`GenerateModuleJniCpp can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "SampleSpec-generated.cpp" => " + "jni/TWO_MODULES_DIFFERENT_FILES-generated.cpp" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -291,12 +315,11 @@ Map { * @generated by codegen project: GenerateModuleJniCpp.js */ -#include \\"SampleSpec.h\\" +#include \\"TWO_MODULES_DIFFERENT_FILES.h\\" namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); } @@ -307,56 +330,23 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo } -static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); -} - -NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; -} - -} // namespace react -} // namespace facebook -", -} -`; - -exports[`GenerateModuleJniCpp can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "SampleSpec-generated.cpp" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleJniCpp.js - */ - -#include \\"SampleSpec.h\\" - -namespace facebook { -namespace react { - - -static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { +static facebook::jsi::Value __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); } -NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) +NativeSampleTurboModule2SpecJSI::NativeSampleTurboModule2SpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; -} - -static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc}; } -NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) - : JavaTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; +std::shared_ptr TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + if (moduleName == \\"SampleTurboModule2\\") { + return std::make_shared(params); + } + return nullptr; } } // namespace react diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index 6308dceddc0b5f..821ffc8303e736 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -2,7 +2,7 @@ exports[`GenerateModuleJniH can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "SampleSpec.h" => " + "jni/COMPLEX_OBJECTS.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -12,16 +12,17 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { /** - * JNI C++ class for module 'SampleTurboModule' + * JNI C++ class for module 'NativeSampleTurboModule' */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { public: @@ -29,15 +30,45 @@ public: }; +std::shared_ptr COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + } // namespace react } // namespace facebook +", + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_complex_objects + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/complex_objects/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/complex_objects + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; exports[`GenerateModuleJniH can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "SampleSpec.h" => " + "jni/EMPTY_NATIVE_MODULES.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -47,16 +78,17 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { /** - * JNI C++ class for module 'SampleTurboModule' + * JNI C++ class for module 'NativeSampleTurboModule' */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { public: @@ -64,15 +96,45 @@ public: }; +std::shared_ptr EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + } // namespace react } // namespace facebook +", + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_empty_native_modules + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/empty_native_modules/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/empty_native_modules + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; exports[`GenerateModuleJniH can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "SampleSpec.h" => " + "jni/NATIVE_MODULES_WITH_TYPE_ALIASES.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -82,10 +144,11 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { @@ -93,21 +156,51 @@ namespace react { /** * JNI C++ class for module 'AliasTurboModule' */ -class JSI_EXPORT NativeAliasTurboModuleSpecJSI : public JavaTurboModule { +class JSI_EXPORT AliasTurboModuleSpecJSI : public JavaTurboModule { public: - NativeAliasTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); + AliasTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); }; +std::shared_ptr NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + } // namespace react } // namespace facebook +", + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_native_modules_with_type_aliases + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/native_modules_with_type_aliases/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/native_modules_with_type_aliases + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; exports[`GenerateModuleJniH can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "SampleSpec.h" => " + "jni/REAL_MODULE_EXAMPLE.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -117,16 +210,17 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { /** - * JNI C++ class for module 'CameraRollManager' + * JNI C++ class for module 'NativeCameraRollManager' */ class JSI_EXPORT NativeCameraRollManagerSpecJSI : public JavaTurboModule { public: @@ -134,31 +228,53 @@ public: }; /** - * JNI C++ class for module 'ExceptionsManager' + * JNI C++ class for module 'NativeExceptionsManager' */ class JSI_EXPORT NativeExceptionsManagerSpecJSI : public JavaTurboModule { public: NativeExceptionsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); }; -/** - * JNI C++ class for module 'ImagePickerIOS' - */ -class JSI_EXPORT NativeImagePickerIOSSpecJSI : public JavaTurboModule { -public: - NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); -}; +std::shared_ptr REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); } // namespace react } // namespace facebook +", + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_real_module_example + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/real_module_example/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/real_module_example + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; exports[`GenerateModuleJniH can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "SampleSpec.h" => " + "jni/SIMPLE_NATIVE_MODULES.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -168,16 +284,17 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { /** - * JNI C++ class for module 'SampleTurboModule' + * JNI C++ class for module 'NativeSampleTurboModule' */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { public: @@ -185,15 +302,45 @@ public: }; +std::shared_ptr SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + } // namespace react } // namespace facebook +", + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := react_codegen_simple_native_modules + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/simple_native_modules/*.cpp) + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/simple_native_modules + +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; exports[`GenerateModuleJniH can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "SampleSpec.h" => " + "jni/TWO_MODULES_DIFFERENT_FILES.h" => " /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -203,16 +350,17 @@ Map { * @generated by codegen project: GenerateModuleJniH.js */ -#import -#import -#import -#import +#pragma once + +#include +#include +#include namespace facebook { namespace react { /** - * JNI C++ class for module 'SampleTurboModule' + * JNI C++ class for module 'NativeSampleTurboModule' */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { public: @@ -220,59 +368,46 @@ public: }; /** - * JNI C++ class for module 'Sample2TurboModule' + * JNI C++ class for module 'NativeSampleTurboModule2' */ -class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public JavaTurboModule { +class JSI_EXPORT NativeSampleTurboModule2SpecJSI : public JavaTurboModule { public: - NativeSample2TurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); + NativeSampleTurboModule2SpecJSI(const JavaTurboModule::InitParams ¶ms); }; +std::shared_ptr TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + } // namespace react } // namespace facebook ", -} -`; + "jni/Android.mk" => "# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. -exports[`GenerateModuleJniH can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "SampleSpec.h" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleJniH.js - */ +LOCAL_PATH := $(call my-dir) -#import -#import -#import -#import +include $(CLEAR_VARS) -namespace facebook { -namespace react { +LOCAL_MODULE := react_codegen_two_modules_different_files -/** - * JNI C++ class for module 'SampleTurboModule' - */ -class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { -public: - NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); -}; +LOCAL_C_INCLUDES := $(LOCAL_PATH) -/** - * JNI C++ class for module 'Sample2TurboModule' - */ -class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public JavaTurboModule { -public: - NativeSample2TurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); -}; +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/two_modules_different_files/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/two_modules_different_files -} // namespace react -} // namespace facebook +LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core libreact_render_components_view libreact_render_core libreact_render_graphics + +LOCAL_STATIC_LIBRARIES := libjsi + +LOCAL_CFLAGS := \\\\ + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_SHARED_LIBRARY) ", } `; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index 192e19235d1cf1..3053a5fee6acc6 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -2,99 +2,90 @@ exports[`GenerateModuleMm can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "COMPLEX_OBJECTS-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import - +#import \\"COMPLEX_OBJECTS.h\\" -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultReturnType:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - - @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json { return facebook::react::managedPointer(json); } @end - - +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json +{ + return facebook::react::managedPointer(json); +} +@end @implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json { return facebook::react::managedPointer(json); } @end - - -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - - -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - namespace facebook { namespace react { - + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionals(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"optionals\\", @selector(optionals:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"optionals\\", @selector(optionals:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"optionalMethod\\", @selector(optionalMethod:callback:extras:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"optionalMethod\\", @selector(optionalMethod:callback:extras:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"getArrays\\", @selector(getArrays:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getArrays\\", @selector(getArrays:), args, count); } NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; - methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_optionals}; - methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod}; - methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays}; - setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); - setMethodArgConversionSelector(@\\"optionals\\", 0, @\\"JS_NativeSampleTurboModule_SpecOptionalsA:\\"); - setMethodArgConversionSelector(@\\"getArrays\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetArraysOptions:\\"); + + methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; + setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); + + methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_optionals}; + setMethodArgConversionSelector(@\\"optionals\\", 0, @\\"JS_NativeSampleTurboModule_SpecOptionalsA:\\"); + + methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod}; + + + methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays}; + setMethodArgConversionSelector(@\\"getArrays\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetArraysOptions:\\"); } } // namespace react } // namespace facebook @@ -104,27 +95,29 @@ namespace facebook { exports[`GenerateModuleMm can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "EMPTY_NATIVE_MODULES-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import +#import \\"EMPTY_NATIVE_MODULES.h\\" namespace facebook { namespace react { - + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - + } } // namespace react } // namespace facebook @@ -134,65 +127,57 @@ namespace facebook { exports[`GenerateModuleMm can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "NATIVE_MODULES_WITH_TYPE_ALIASES-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import - +#import \\"NATIVE_MODULES_WITH_TYPE_ALIASES.h\\" -@implementation RCTCxxConvert (NativeAliasTurboModule_Options) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_Options:(id)json +@implementation RCTCxxConvert (AliasTurboModule_OptionsOffset) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsOffset:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - - -@implementation RCTCxxConvert (NativeAliasTurboModule_OptionsOffset) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsOffset:(id)json +@implementation RCTCxxConvert (AliasTurboModule_OptionsSize) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsSize:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - - -@implementation RCTCxxConvert (NativeAliasTurboModule_OptionsSize) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsSize:(id)json +@implementation RCTCxxConvert (AliasTurboModule_OptionsDisplaySize) ++ (RCTManagedPointer *)JS_AliasTurboModule_OptionsDisplaySize:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - - -@implementation RCTCxxConvert (NativeAliasTurboModule_OptionsDisplaySize) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsDisplaySize:(id)json +@implementation RCTCxxConvert (AliasTurboModule_Options) ++ (RCTManagedPointer *)JS_AliasTurboModule_Options:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end - namespace facebook { namespace react { - - - static facebook::jsi::Value __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"cropImage\\", @selector(cropImage:), args, count); + + static facebook::jsi::Value __hostFunction_AliasTurboModuleSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"cropImage\\", @selector(cropImage:), args, count); } - NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + AliasTurboModuleSpecJSI::AliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - - methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage}; - setMethodArgConversionSelector(@\\"cropImage\\", 0, @\\"JS_NativeAliasTurboModule_Options:\\"); + + methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleSpecJSI_cropImage}; + setMethodArgConversionSelector(@\\"cropImage\\", 0, @\\"JS_AliasTurboModule_Options:\\"); } } // namespace react } // namespace facebook @@ -202,43 +187,20 @@ namespace facebook { exports[`GenerateModuleMm can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "REAL_MODULE_EXAMPLE-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - +#import \\"REAL_MODULE_EXAMPLE.h\\" @implementation RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) + (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json @@ -246,127 +208,108 @@ Map { return facebook::react::managedPointer(json); } @end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getPhotos\\", @selector(getPhotos:resolve:reject:), args, count); + } + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"saveToCameraRoll\\", @selector(saveToCameraRoll:type:resolve:reject:), args, count); + } -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"deletePhotos\\", @selector(deletePhotos:resolve:reject:), args, count); + } + NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; + setMethodArgConversionSelector(@\\"getPhotos\\", 0, @\\"JS_NativeCameraRollManager_GetPhotosParams:\\"); + + methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; + + + methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; + + } + } // namespace react +} // namespace facebook @implementation RCTCxxConvert (NativeExceptionsManager_StackFrame) + (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json { return facebook::react::managedPointer(json); } @end - - @implementation RCTCxxConvert (NativeExceptionsManager_ExceptionData) + (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json { return facebook::react::managedPointer(json); } @end - namespace facebook { namespace react { - - - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"getPhotos\\", @selector(getPhotos:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"saveToCameraRoll\\", @selector(saveToCameraRoll:type:resolve:reject:), args, count); - } - - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"deletePhotos\\", @selector(deletePhotos:resolve:reject:), args, count); - } - - NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; - methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; - methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; - setMethodArgConversionSelector(@\\"getPhotos\\", 0, @\\"JS_NativeCameraRollManager_GetPhotosParams:\\"); - } - - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"openCameraDialog\\", @selector(openCameraDialog:successCallback:cancelCallback:), args, count); - } - - NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"openCameraDialog\\"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; - setMethodArgConversionSelector(@\\"openCameraDialog\\", 0, @\\"JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:\\"); - } - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportFatalException\\", @selector(reportFatalException:stack:exceptionId:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportFatalException\\", @selector(reportFatalException:stack:exceptionId:), args, count); } static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportSoftException\\", @selector(reportSoftException:stack:exceptionId:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportSoftException\\", @selector(reportSoftException:stack:exceptionId:), args, count); } static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportException\\", @selector(reportException:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportException\\", @selector(reportException:), args, count); } static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"updateExceptionMessage\\", @selector(updateExceptionMessage:stack:exceptionId:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"updateExceptionMessage\\", @selector(updateExceptionMessage:stack:exceptionId:), args, count); } static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"dismissRedbox\\", @selector(dismissRedbox), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"dismissRedbox\\", @selector(dismissRedbox), args, count); } NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"reportFatalException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; - methodMap_[\\"reportSoftException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; - methodMap_[\\"reportException\\"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; - methodMap_[\\"updateExceptionMessage\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; - methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; - setMethodArgConversionSelector(@\\"reportException\\", 0, @\\"JS_NativeExceptionsManager_ExceptionData:\\"); + + methodMap_[\\"reportFatalException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; + + + methodMap_[\\"reportSoftException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; + + + methodMap_[\\"reportException\\"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; + setMethodArgConversionSelector(@\\"reportException\\", 0, @\\"JS_NativeExceptionsManager_ExceptionData:\\"); + + methodMap_[\\"updateExceptionMessage\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; + + + methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; + + } + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) ++ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"openCameraDialog\\", @selector(openCameraDialog:successCallback:cancelCallback:), args, count); + } + + NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"openCameraDialog\\"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; + setMethodArgConversionSelector(@\\"openCameraDialog\\", 0, @\\"JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:\\"); } } // namespace react } // namespace facebook @@ -376,91 +319,104 @@ namespace facebook { exports[`GenerateModuleMm can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "SIMPLE_NATIVE_MODULES-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import +#import \\"SIMPLE_NATIVE_MODULES.h\\" namespace facebook { namespace react { - - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); - } - + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); } static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); } NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; - methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; - methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; - methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; - methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; - methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; - methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; - methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; - methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; - methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + } } // namespace react } // namespace facebook @@ -470,89 +426,50 @@ namespace facebook { exports[`GenerateModuleMm can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "SampleSpec-generated.mm" => " -/** + "TWO_MODULES_DIFFERENT_FILES-generated.mm" => "/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. */ -#include -#import - +#import \\"TWO_MODULES_DIFFERENT_FILES.h\\" namespace facebook { namespace react { - + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; - } - - - static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); - } - - NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + } } // namespace react } // namespace facebook -", -} -`; - -exports[`GenerateModuleMm can generate fixture TWO_MODULES_SAME_FILE 1`] = ` -Map { - "SampleSpec-generated.mm" => " -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by codegen project: GenerateModuleMm.js - */ - -#include -#import - - namespace facebook { namespace react { - - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); - } - - NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; - } - - static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } - NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + NativeSampleTurboModule2SpecJSI::NativeSampleTurboModule2SpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc}; + } } // namespace react } // namespace facebook diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap deleted file mode 100644 index 75bb7bfe5dbde1..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap +++ /dev/null @@ -1,284 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GenerateStructs can generate fixture SIMPLE_CONSTANTS 1`] = ` -" - -namespace JS { - namespace NativeSampleTurboModule { - struct ConstantsDG { - - struct Builder { - struct Input { - RCTRequired h; - RCTRequired i; - RCTRequired j; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsDG */ - Builder(ConstantsDG i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsDG fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsDG(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::ConstantsDG::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto h = i.h.get(); - d[@\\"h\\"] = @(h); -auto i = i.i.get(); - d[@\\"i\\"] = @(i); -auto j = i.j.get(); - d[@\\"j\\"] = j; - return d; -}) {} -inline JS::NativeSampleTurboModule::ConstantsDG::Builder::Builder(ConstantsDG i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - -namespace JS { - namespace NativeSampleTurboModule { - struct ConstantsD { - - struct Builder { - struct Input { - RCTRequired e; - RCTRequired f; - RCTRequired g; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsD */ - Builder(ConstantsD i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsD fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsD(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::ConstantsD::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto e = i.e.get(); - d[@\\"e\\"] = @(e); -auto f = i.f.get(); - d[@\\"f\\"] = @(f); -auto g = i.g.get(); - d[@\\"g\\"] = g.buildUnsafeRawValue(); - return d; -}) {} -inline JS::NativeSampleTurboModule::ConstantsD::Builder::Builder(ConstantsD i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - -namespace JS { - namespace NativeSampleTurboModule { - struct Constants { - - struct Builder { - struct Input { - RCTRequired a; - RCTRequired b; - RCTRequired c; - RCTRequired d; - RCTRequired k; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto a = i.a.get(); - d[@\\"a\\"] = @(a); -auto b = i.b.get(); - d[@\\"b\\"] = @(b); -auto c = i.c.get(); - d[@\\"c\\"] = c; -auto d = i.d.get(); - d[@\\"d\\"] = d.buildUnsafeRawValue(); -auto k = i.k.get(); - d[@\\"k\\"] = @(k); - return d; -}) {} -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -" -`; - -exports[`GenerateStructs can generate fixture SIMPLE_STRUCT 1`] = ` -" - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnTypeDG { - bool h() const; - double i() const; - NSString *j() const; - - SpecSampleFuncReturnTypeDG(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnTypeDG) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnTypeDG:(id)json; -@end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnTypeD { - bool e() const; - double f() const; - JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG g() const; - - SpecSampleFuncReturnTypeD(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnTypeD) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnTypeD:(id)json; -@end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnType { - bool a() const; - double b() const; - NSString *c() const; - JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD d() const; - double k() const; - - SpecSampleFuncReturnType(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnType:(id)json; -@end - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnType::a() const -{ - id const p = _v[@\\"a\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnType::b() const -{ - id const p = _v[@\\"b\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecSampleFuncReturnType::c() const -{ - id const p = _v[@\\"c\\"]; - return RCTBridgingToString(p); -} - - -inline JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD JS::NativeSampleTurboModule::SpecSampleFuncReturnType::d() const -{ - id const p = _v[@\\"d\\"]; - return JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnType::k() const -{ - id const p = _v[@\\"k\\"]; - return RCTBridgingToDouble(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::e() const -{ - id const p = _v[@\\"e\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::f() const -{ - id const p = _v[@\\"f\\"]; - return RCTBridgingToDouble(p); -} - - -inline JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::g() const -{ - id const p = _v[@\\"g\\"]; - return JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::h() const -{ - id const p = _v[@\\"h\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::i() const -{ - id const p = _v[@\\"i\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::j() const -{ - id const p = _v[@\\"j\\"]; - return RCTBridgingToString(p); -} - -" -`; diff --git a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap index 5ae118d770dd63..48836ae868944b 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/components/__tests__/__snapshots__/component-parser-test.js.snap @@ -35,7979 +35,9388 @@ exports[`RN Codegen Flow Parser Fails with error message PROPS_CONFLICT_WITH_SPR exports[`RN Codegen Flow Parser Fails with error message PROPS_SPREAD_CONFLICTS_WITH_PROPS 1`] = `"A prop was already defined with the name isEnabled"`; exports[`RN Codegen Flow Parser can generate fixture ALL_PROP_TYPES_NO_EVENTS 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "props": Array [ - Object { - "name": "boolean_required", - "optional": false, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": true, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": true, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "boolean_null_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "boolean_null_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "string_required", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "string_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": "", - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "string_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": "", - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "string_null_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "string_null_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "stringish_required", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "stringish_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": "", - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "stringish_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": "", - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "stringish_null_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "stringish_null_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "double_required", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "DoubleTypeAnnotation", - }, - }, - Object { - "name": "double_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": 1.1, - "type": "DoubleTypeAnnotation", - }, - }, - Object { - "name": "double_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": 1.1, - "type": "DoubleTypeAnnotation", - }, - }, - Object { - "name": "float_required", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "FloatTypeAnnotation", - }, - }, - Object { - "name": "float_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": 1.1, - "type": "FloatTypeAnnotation", - }, - }, - Object { - "name": "float_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": 1.1, - "type": "FloatTypeAnnotation", - }, - }, - Object { - "name": "float_null_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "FloatTypeAnnotation", - }, - }, - Object { - "name": "float_null_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "FloatTypeAnnotation", - }, - }, - Object { - "name": "int32_required", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "int32_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": 1, - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "int32_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": 1, - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "enum_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": "small", - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - }, - Object { - "name": "enum_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": "small", - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - }, - Object { - "name": "int_enum_optional_key", - "optional": true, - "typeAnnotation": Object { - "default": 0, - "options": Array [ - Object { - "value": 0, - }, - Object { - "value": 1, - }, - ], - "type": "Int32EnumTypeAnnotation", - }, - }, - Object { - "name": "object_optional_key", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_optional_both", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_optional_value", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "image_required", - "optional": false, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "image_optional_value", - "optional": true, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "image_optional_both", - "optional": true, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "color_required", - "optional": false, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "color_optional_key", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "color_optional_value", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "color_optional_both", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "color_array_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "color_array_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "color_array_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "color_array_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "processed_color_required", - "optional": false, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_key", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_value", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_both", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "point_required", - "optional": false, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "point_optional_key", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "point_optional_value", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "point_optional_both", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "insets_required", - "optional": false, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_key", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_value", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_both", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, + 'events': [], + 'props': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + }, + { + 'name': 'boolean_null_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': null + } + }, + { + 'name': 'boolean_null_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': null + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + }, + { + 'name': 'string_null_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'string_null_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'stringish_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'stringish_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + }, + { + 'name': 'stringish_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + }, + { + 'name': 'stringish_null_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'stringish_null_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 1.1 + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 1.1 + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 1.1 + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 1.1 + } + }, + { + 'name': 'float_null_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': null + } + }, + { + 'name': 'float_null_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': null + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 1 + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 1 + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'int_enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32EnumTypeAnnotation', + 'default': 0, + 'options': [ + 0, + 1 + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'image_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + }, + { + 'name': 'image_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + }, + { + 'name': 'image_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + }, + { + 'name': 'color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'color_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'color_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'color_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'color_array_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'color_array_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'color_array_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'color_array_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'processed_color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'processed_color_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'processed_color_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'processed_color_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + }, + { + 'name': 'point_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + }, + { + 'name': 'point_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + }, + { + 'name': 'point_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + }, + { + 'name': 'point_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + }, + { + 'name': 'insets_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + }, + { + 'name': 'insets_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + }, + { + 'name': 'insets_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + }, + { + 'name': 'insets_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture ARRAY_PROP_TYPES_NO_EVENTS 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "props": Array [ - Object { - "name": "array_boolean_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "BooleanTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_boolean_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "BooleanTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_boolean_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "BooleanTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_boolean_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "BooleanTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_string_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_string_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_string_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_string_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_double_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "DoubleTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_double_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "DoubleTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_double_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "DoubleTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_double_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "DoubleTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_float_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "FloatTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_float_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "FloatTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_float_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "FloatTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_float_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "FloatTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_int32_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "Int32TypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_int32_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "Int32TypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_int32_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "Int32TypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_int32_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "type": "Int32TypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_enum_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "default": "small", - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_enum_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "default": "small", - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_image_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_image_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_image_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_image_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_color_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_color_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_color_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_color_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_point_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_point_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_point_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_point_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_insets_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_insets_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_insets_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_insets_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_object_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_object_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_object_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_object_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_object_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "array_object_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_object_optional_key", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "array_object_optional_key", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_object_optional_value", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "array_object_optional_value", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_object_optional_both", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "array_object_optional_both", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_of_object_required", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_of_object_required_in_file", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - Object { - "name": "array_of_array_of_object_required_with_spread", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, + 'events': [], + 'props': [ + { + 'name': 'array_boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'array_boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'array_boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'array_boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'BooleanTypeAnnotation' + } + } + }, + { + 'name': 'array_string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'array_string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'array_string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'array_string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + }, + { + 'name': 'array_double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'array_double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'array_double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'array_double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'DoubleTypeAnnotation' + } + } + }, + { + 'name': 'array_float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'array_float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'array_float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'array_float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'FloatTypeAnnotation' + } + } + }, + { + 'name': 'array_int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'array_int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'array_int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'array_int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'Int32TypeAnnotation' + } + } + }, + { + 'name': 'array_enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'array_enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + } + }, + { + 'name': 'array_image_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + }, + { + 'name': 'array_image_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + }, + { + 'name': 'array_image_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + }, + { + 'name': 'array_image_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + }, + { + 'name': 'array_color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'array_color_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'array_color_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'array_color_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + }, + { + 'name': 'array_point_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + }, + { + 'name': 'array_point_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + }, + { + 'name': 'array_point_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + }, + { + 'name': 'array_point_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + }, + { + 'name': 'array_insets_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + }, + { + 'name': 'array_insets_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + }, + { + 'name': 'array_insets_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + }, + { + 'name': 'array_insets_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + }, + { + 'name': 'array_object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + }, + { + 'name': 'array_object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + }, + { + 'name': 'array_object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + }, + { + 'name': 'array_object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + }, + { + 'name': 'array_of_array_object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'array_object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + ] + } + } + }, + { + 'name': 'array_of_array_object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'array_object_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + ] + } + } + }, + { + 'name': 'array_of_array_object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'array_object_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + ] + } + } + }, + { + 'name': 'array_of_array_object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'array_object_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + ] + } + } + }, + { + 'name': 'array_of_array_of_object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + }, + { + 'name': 'array_of_array_of_object_required_in_file', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + }, + { + 'name': 'array_of_array_of_object_required_with_spread', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture COMMANDS_AND_EVENTS_TYPES_EXPORTED 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [ - Object { - "name": "scrollTo", - "optional": false, - "typeAnnotation": Object { - "params": Array [ - Object { - "name": "y", - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "animated", - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "FunctionTypeAnnotation", - }, - }, - ], - "events": Array [ - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineWithPaperName", - "optional": false, - "paperTopLevelNameDeprecated": "paperBubblingEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineWithPaperName", - "optional": false, - "paperTopLevelNameDeprecated": "paperDirectEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onBubblingEventDefinedInline', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineWithPaperName', + 'optional': false, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInline', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': false, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + } ], - "props": Array [], - }, - }, - }, - }, -} + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'animated', + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ], + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture COMMANDS_DEFINED_WITH_ALL_TYPES 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [ - Object { - "name": "handleRootTag", - "optional": false, - "typeAnnotation": Object { - "params": Array [ - Object { - "name": "rootTag", - "typeAnnotation": Object { - "name": "RootTag", - "type": "ReservedFunctionValueTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [ + { + 'name': 'handleRootTag', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'rootTag', + 'typeAnnotation': { + 'type': 'ReservedTypeAnnotation', + 'name': 'RootTag' + } + } ], - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "hotspotUpdate", - "optional": false, - "typeAnnotation": Object { - "params": Array [ - Object { - "name": "x", - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "y", - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + }, + { + 'name': 'hotspotUpdate', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'x', + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } }, + { + 'name': 'y', + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } ], - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "scrollTo", - "optional": false, - "typeAnnotation": Object { - "params": Array [ - Object { - "name": "x", - "typeAnnotation": Object { - "type": "FloatTypeAnnotation", - }, + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + }, + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'x', + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } }, - Object { - "name": "y", - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, + { + 'name': 'y', + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } }, - Object { - "name": "z", - "typeAnnotation": Object { - "type": "DoubleTypeAnnotation", - }, - }, - Object { - "name": "animated", - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, + { + 'name': 'z', + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } }, + { + 'name': 'animated', + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } ], - "type": "FunctionTypeAnnotation", - }, - }, - ], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, - ], - "props": Array [], - }, - }, - }, - }, -} + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture COMMANDS_WITH_EXTERNAL_TYPES 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [ - Object { - "name": "scrollTo", - "optional": false, - "typeAnnotation": Object { - "params": Array [ - Object { - "name": "y", - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, - }, - Object { - "name": "animated", - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } + ], + 'events': [], + 'props': [], + 'commands': [ + { + 'name': 'scrollTo', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'params': [ + { + 'name': 'y', + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } }, + { + 'name': 'animated', + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } ], - "type": "FunctionTypeAnnotation", - }, - }, - ], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, - ], - "props": Array [], - }, - }, - }, - }, -} + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + } + } + } + ] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_AS_NULL_INLINE 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [ - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNullOptionalKey", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNullOptionalValue", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNullOptionalBoth", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNullWithPaperName", - "optional": true, - "paperTopLevelNameDeprecated": "paperDirectEventDefinedInlineNullWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNullOptionalKey", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNullOptionalValue", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNullOptionalBoth", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNullWithPaperName", - "optional": true, - "paperTopLevelNameDeprecated": "paperBubblingEventDefinedInlineNullWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalKey', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNullWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineNullWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } ], - "props": Array [], - }, - }, - }, - }, -} + 'props': [], + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture EVENTS_DEFINED_INLINE_WITH_ALL_TYPES 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [ - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineOptionalKey", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineOptionalValue", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineOptionalBoth", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineWithPaperName", - "optional": true, - "paperTopLevelNameDeprecated": "paperDirectEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineOptionalKey", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineOptionalValue", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineOptionalBoth", - "optional": true, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineWithPaperName", - "optional": true, - "paperTopLevelNameDeprecated": "paperBubblingEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onDirectEventDefinedInline', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineOptionalKey', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineOptionalValue', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInline', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalKey', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalValue', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineOptionalBoth', + 'optional': true, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineWithPaperName', + 'optional': true, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + } ], - "props": Array [], - }, - }, - }, - }, -} + 'props': [], + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture NO_PROPS_EVENTS_ONLY_DEPRECATED_VIEW_CONFIG_NAME_OPTION 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "deprecatedViewConfigName": "DeprecateModuleName", - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'deprecatedViewConfigName': 'DeprecateModuleName', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "props": Array [], - }, - }, - }, - }, -} + 'events': [], + 'props': [], + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture OBJECT_PROP_TYPES_NO_EVENTS 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "props": Array [ - Object { - "name": "boolean_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "boolean_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "string_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "string_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": "", - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "double_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "DoubleTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "double_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": 0, - "type": "DoubleTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "float_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "FloatTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "float_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": 0, - "type": "FloatTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "int_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "default": 0, - "type": "Int32TypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "int_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "default": 0, - "type": "Int32TypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "enum_optional", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "elementType": Object { - "default": "small", - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "image_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "image_optional_key", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "image_optional_value", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "image_optional_both", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ImageSourcePrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "color_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "color_optional_key", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "color_optional_value", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "color_optional_both", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "processed_color_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_key", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_value", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "processed_color_optional_both", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "ColorPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "point_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "point_optional_key", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "point_optional_value", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "point_optional_both", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "PointPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "insets_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_key", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_value", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "insets_optional_both", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": true, - "typeAnnotation": Object { - "name": "EdgeInsetsPrimitive", - "type": "ReservedPropTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_required", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "nestedProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_optional_key", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "nestedProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_optional_value", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "nestedProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "object_optional_both", - "optional": true, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "prop", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "nestedProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, + 'events': [], + 'props': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'boolean_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + } + ] + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'string_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': '' + } + } + ] + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'double_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'float_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'int_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation', + 'default': 0 + } + } + ] + } + }, + { + 'name': 'enum_optional', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringEnumTypeAnnotation', + 'default': 'small', + 'options': [ + 'small', + 'large' + ] + } + } + } + ] + } + }, + { + 'name': 'image_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'image_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ImageSourcePrimitive' + } + } + ] + } + }, + { + 'name': 'color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'processed_color_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'ColorPrimitive' + } + } + ] + } + }, + { + 'name': 'point_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'point_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'point_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'point_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'PointPrimitive' + } + } + ] + } + }, + { + 'name': 'insets_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + ] + } + }, + { + 'name': 'insets_optional_key', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + ] + } + }, + { + 'name': 'insets_optional_value', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + ] + } + }, + { + 'name': 'insets_optional_both', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': true, + 'typeAnnotation': { + 'type': 'ReservedPropTypeAnnotation', + 'name': 'EdgeInsetsPrimitive' + } + } + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'prop', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'nestedProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + ] + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [ - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } ], - "interfaceOnly": true, - "paperComponentName": "RCTModule", - "props": Array [ - Object { - "name": "boolean_default_true_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": true, - "type": "BooleanTypeAnnotation", - }, - }, + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture ONE_OF_EACH_PROP_EVENT_DEFAULT_AND_OPTIONS_NO_CAST 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [ - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineNull", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'interfaceOnly': true, + 'excludedPlatforms': [ + 'android' ], - "excludedPlatforms": Array [ - "android", + 'paperComponentName': 'RCTModule', + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onDirectEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineNull', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [] + } + } + } ], - "interfaceOnly": true, - "paperComponentName": "RCTModule", - "props": Array [ - Object { - "name": "boolean_default_true_optional_both", - "optional": true, - "typeAnnotation": Object { - "default": true, - "type": "BooleanTypeAnnotation", - }, - }, + 'props': [ + { + 'name': 'boolean_default_true_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': true + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture PROPS_ALIASED_LOCALLY 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "props": Array [ - Object { - "name": "otherStringProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "isEnabled", - "optional": false, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "label", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "localType", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "otherStringProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, + 'events': [], + 'props': [ + { + 'name': 'otherStringProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'isEnabled', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'localType', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'otherStringProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } }, - Object { - "name": "isEnabled", - "optional": false, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "label", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, + { + 'name': 'isEnabled', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "localArr", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "otherStringProp", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "isEnabled", - "optional": false, - "typeAnnotation": Object { - "default": false, - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "label", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + }, + { + 'name': 'localArr', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'otherStringProp', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'isEnabled', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation', + 'default': false + } + }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + } + ] + } + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture PROPS_AND_EVENTS_TYPES_EXPORTED 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [ - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "bubble", - "name": "onBubblingEventDefinedInlineWithPaperName", - "optional": false, - "paperTopLevelNameDeprecated": "paperBubblingEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInline", - "optional": false, - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, - Object { - "bubblingType": "direct", - "name": "onDirectEventDefinedInlineWithPaperName", - "optional": false, - "paperTopLevelNameDeprecated": "paperDirectEventDefinedInlineWithPaperName", - "typeAnnotation": Object { - "argument": Object { - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_key", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_value", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "boolean_optional_both", - "optional": true, - "type": "BooleanTypeAnnotation", - }, - Object { - "name": "string_required", - "optional": false, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_value", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "string_optional_both", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_required", - "optional": false, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_key", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "double_optional_both", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_required", - "optional": false, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_key", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "float_optional_both", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_key", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_value", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "enum_required", - "optional": false, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_key", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_value", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "enum_optional_both", - "optional": true, - "options": Array [ - Object { - "name": "small", - }, - Object { - "name": "large", - }, - ], - "type": "StringEnumTypeAnnotation", - }, - Object { - "name": "object_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_required_nested_2_layers", - "optional": false, - "properties": Array [ - Object { - "name": "object_optional_nested_1_layer", - "optional": true, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "Int32TypeAnnotation", - }, - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - Object { - "name": "double_optional_value", - "optional": true, - "type": "DoubleTypeAnnotation", - }, - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_required", - "optional": false, - "properties": Array [ - Object { - "name": "boolean_required", - "optional": false, - "type": "BooleanTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_key", - "optional": true, - "properties": Array [ - Object { - "name": "string_optional_key", - "optional": true, - "type": "StringTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_value", - "optional": true, - "properties": Array [ - Object { - "name": "float_optional_value", - "optional": true, - "type": "FloatTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - Object { - "name": "object_readonly_optional_both", - "optional": true, - "properties": Array [ - Object { - "name": "int32_optional_both", - "optional": true, - "type": "Int32TypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "EventTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [ + { + 'type': 'ReactNativeBuiltInType', + 'knownTypeName': 'ReactNativeCoreViewProps' + } ], - "extendsProps": Array [ - Object { - "knownTypeName": "ReactNativeCoreViewProps", - "type": "ReactNativeBuiltInType", - }, + 'events': [ + { + 'name': 'onBubblingEventDefinedInline', + 'optional': false, + 'bubblingType': 'bubble', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onBubblingEventDefinedInlineWithPaperName', + 'optional': false, + 'bubblingType': 'bubble', + 'paperTopLevelNameDeprecated': 'paperBubblingEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInline', + 'optional': false, + 'bubblingType': 'direct', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + }, + { + 'name': 'onDirectEventDefinedInlineWithPaperName', + 'optional': false, + 'bubblingType': 'direct', + 'paperTopLevelNameDeprecated': 'paperDirectEventDefinedInlineWithPaperName', + 'typeAnnotation': { + 'type': 'EventTypeAnnotation', + 'argument': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'boolean_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'string_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'string_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'double_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'float_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'enum_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'enum_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringEnumTypeAnnotation', + 'options': [ + 'small', + 'large' + ] + } + }, + { + 'name': 'object_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_required_nested_2_layers', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'object_optional_nested_1_layer', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + }, + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'double_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'DoubleTypeAnnotation' + } + }, + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + }, + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'object_readonly_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'boolean_required', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'string_optional_key', + 'optional': true, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'float_optional_value', + 'optional': true, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'object_readonly_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'int32_optional_both', + 'optional': true, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + } + ] + } + } + } ], - "props": Array [], - }, - }, - }, - }, -} + 'props': [], + 'commands': [] + } + } + } + } +}" `; exports[`RN Codegen Flow Parser can generate fixture PROPS_AS_EXTERNAL_TYPES 1`] = ` -Object { - "modules": Object { - "Module": Object { - "components": Object { - "Module": Object { - "commands": Array [], - "events": Array [], - "extendsProps": Array [], - "props": Array [ - Object { - "name": "disable", - "optional": false, - "typeAnnotation": Object { - "default": null, - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "array", - "optional": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, +"{ + 'modules': { + 'Module': { + 'type': 'Component', + 'components': { + 'Module': { + 'extendsProps': [], + 'events': [], + 'props': [ + { + 'name': 'disable', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation', + 'default': null + } + }, + { + 'name': 'array', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } ], - }, - }, - }, - }, -} + 'commands': [] + } + } + } + } +}" `; diff --git a/packages/react-native-codegen/src/parsers/flow/components/__tests__/component-parser-test.js b/packages/react-native-codegen/src/parsers/flow/components/__tests__/component-parser-test.js index 0f5a94a00cffbc..9c93fe7f7c85ac 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/__tests__/component-parser-test.js +++ b/packages/react-native-codegen/src/parsers/flow/components/__tests__/component-parser-test.js @@ -23,7 +23,12 @@ describe('RN Codegen Flow Parser', () => { .sort() .forEach(fixtureName => { it(`can generate fixture ${fixtureName}`, () => { - expect(FlowParser.parseFile(fixtureName)).toMatchSnapshot(); + const schema = FlowParser.parseFile(fixtureName); + const serializedSchema = JSON.stringify(schema, null, 2).replace( + /"/g, + "'", + ); + expect(serializedSchema).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/parsers/flow/components/commands.js b/packages/react-native-codegen/src/parsers/flow/components/commands.js index 769039be7a074d..48103dc595f680 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/commands.js +++ b/packages/react-native-codegen/src/parsers/flow/components/commands.js @@ -10,14 +10,17 @@ 'use strict'; -import type {CommandTypeShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type { + NamedShape, + CommandTypeAnnotation, +} from '../../../CodegenSchema.js'; +import type {TypeDeclarationMap} from '../utils.js'; const {getValueFromTypes} = require('../utils.js'); type EventTypeAST = Object; -function buildCommandSchema(property, types: TypeMap) { +function buildCommandSchema(property, types: TypeDeclarationMap) { const name = property.key.name; const optional = property.optional; const value = getValueFromTypes(property.value, types); @@ -49,7 +52,7 @@ function buildCommandSchema(property, types: TypeMap) { switch (type) { case 'RootTag': returnType = { - type: 'ReservedFunctionValueTypeAnnotation', + type: 'ReservedTypeAnnotation', name: 'RootTag', }; break; @@ -92,14 +95,17 @@ function buildCommandSchema(property, types: TypeMap) { typeAnnotation: { type: 'FunctionTypeAnnotation', params, + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, }, }; } function getCommands( commandTypeAST: $ReadOnlyArray, - types: TypeMap, -): $ReadOnlyArray { + types: TypeDeclarationMap, +): $ReadOnlyArray> { return commandTypeAST .filter(property => property.type === 'ObjectTypeProperty') .map(property => buildCommandSchema(property, types)) diff --git a/packages/react-native-codegen/src/parsers/flow/components/events.js b/packages/react-native-codegen/src/parsers/flow/components/events.js index 81295411a08c06..61962cf790e98b 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/events.js +++ b/packages/react-native-codegen/src/parsers/flow/components/events.js @@ -12,10 +12,15 @@ import type { EventTypeShape, - EventObjectPropertyType, + NamedShape, + EventTypeAnnotation, } from '../../../CodegenSchema.js'; -function getPropertyType(name, optional, typeAnnotation) { +function getPropertyType( + name, + optional, + typeAnnotation, +): NamedShape { const type = typeAnnotation.type === 'GenericTypeAnnotation' ? typeAnnotation.id.name @@ -24,33 +29,43 @@ function getPropertyType(name, optional, typeAnnotation) { switch (type) { case 'BooleanTypeAnnotation': return { - type: 'BooleanTypeAnnotation', name, optional, + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, }; case 'StringTypeAnnotation': return { - type: 'StringTypeAnnotation', name, optional, + typeAnnotation: { + type: 'StringTypeAnnotation', + }, }; case 'Int32': return { - type: 'Int32TypeAnnotation', name, optional, + typeAnnotation: { + type: 'Int32TypeAnnotation', + }, }; case 'Double': return { - type: 'DoubleTypeAnnotation', name, optional, + typeAnnotation: { + type: 'DoubleTypeAnnotation', + }, }; case 'Float': return { - type: 'FloatTypeAnnotation', name, optional, + typeAnnotation: { + type: 'FloatTypeAnnotation', + }, }; case '$ReadOnly': return getPropertyType( @@ -60,17 +75,21 @@ function getPropertyType(name, optional, typeAnnotation) { ); case 'ObjectTypeAnnotation': return { - type: 'ObjectTypeAnnotation', name, optional, - properties: typeAnnotation.properties.map(buildPropertiesForEvent), + typeAnnotation: { + type: 'ObjectTypeAnnotation', + properties: typeAnnotation.properties.map(buildPropertiesForEvent), + }, }; case 'UnionTypeAnnotation': return { - type: 'StringEnumTypeAnnotation', name, optional, - options: typeAnnotation.types.map(option => ({name: option.value})), + typeAnnotation: { + type: 'StringEnumTypeAnnotation', + options: typeAnnotation.types.map(option => option.value), + }, }; default: (type: empty); @@ -132,7 +151,7 @@ function findEventArgumentsAndType( } } -function buildPropertiesForEvent(property): EventObjectPropertyType { +function buildPropertiesForEvent(property): NamedShape { const name = property.key.name; const optional = property.value.type === 'NullableTypeAnnotation' || property.optional; diff --git a/packages/react-native-codegen/src/parsers/flow/components/extends.js b/packages/react-native-codegen/src/parsers/flow/components/extends.js index 77081974a30a69..7d5e899b80828b 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/extends.js +++ b/packages/react-native-codegen/src/parsers/flow/components/extends.js @@ -11,9 +11,9 @@ 'use strict'; import type {ExtendsPropsShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type {TypeDeclarationMap} from '../utils.js'; -function extendsForProp(prop: PropsAST, types: TypeMap) { +function extendsForProp(prop: PropsAST, types: TypeDeclarationMap) { if (!prop.argument) { console.log('null', prop); } @@ -38,7 +38,7 @@ function extendsForProp(prop: PropsAST, types: TypeMap) { function removeKnownExtends( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return typeDefinition.filter( prop => @@ -52,7 +52,7 @@ type PropsAST = Object; function getExtendsProps( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return typeDefinition .filter(prop => prop.type === 'ObjectTypeSpreadProperty') diff --git a/packages/react-native-codegen/src/parsers/flow/components/index.js b/packages/react-native-codegen/src/parsers/flow/components/index.js index eb8867401d5372..8c68c98d650d33 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/index.js +++ b/packages/react-native-codegen/src/parsers/flow/components/index.js @@ -16,6 +16,7 @@ const {getEvents} = require('./events'); const {getProps, getPropProperties} = require('./props'); const {getCommandOptions, getOptions} = require('./options'); const {getExtendsProps, removeKnownExtends} = require('./extends'); +const {getTypes} = require('../utils'); function findComponentConfig(ast) { const foundConfigs = []; @@ -167,7 +168,7 @@ function getCommandProperties(commandTypeName, types, commandOptions) { } // $FlowFixMe there's no flowtype for AST -function processComponent(ast, types): ComponentSchemaBuilderConfig { +function buildComponentSchema(ast): ComponentSchemaBuilderConfig { const { componentName, propsTypeName, @@ -176,6 +177,8 @@ function processComponent(ast, types): ComponentSchemaBuilderConfig { optionsExpression, } = findComponentConfig(ast); + const types = getTypes(ast); + const propProperties = getPropProperties(propsTypeName, types); const commandOptions = getCommandOptions(commandOptionsExpression); @@ -205,5 +208,5 @@ function processComponent(ast, types): ComponentSchemaBuilderConfig { } module.exports = { - processComponent, + buildComponentSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/components/options.js b/packages/react-native-codegen/src/parsers/flow/components/options.js index 8044575db15913..607ac526aabce7 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/options.js +++ b/packages/react-native-codegen/src/parsers/flow/components/options.js @@ -15,9 +15,9 @@ import type {OptionsShape} from '../../../CodegenSchema.js'; // $FlowFixMe there's no flowtype for ASTs type OptionsAST = Object; -export type CommandOptions = $ReadOnly<{| +export type CommandOptions = $ReadOnly<{ supportedCommands: $ReadOnlyArray, -|}>; +}>; function getCommandOptions( commandOptionsExpression: OptionsAST, diff --git a/packages/react-native-codegen/src/parsers/flow/components/props.js b/packages/react-native-codegen/src/parsers/flow/components/props.js index 9b549ac2337acd..208885505f76ef 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/props.js +++ b/packages/react-native-codegen/src/parsers/flow/components/props.js @@ -12,10 +12,13 @@ const {getValueFromTypes} = require('../utils.js'); -import type {PropTypeShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type {NamedShape, PropTypeAnnotation} from '../../../CodegenSchema.js'; +import type {TypeDeclarationMap} from '../utils.js'; -function getPropProperties(propsTypeName: string, types: TypeMap): $FlowFixMe { +function getPropProperties( + propsTypeName: string, + types: TypeDeclarationMap, +): $FlowFixMe { const typeAlias = types[propsTypeName]; try { return typeAlias.right.typeParameters.params[0].properties; @@ -150,7 +153,7 @@ function getTypeAnnotationForArray(name, typeAnnotation, defaultValue, types) { return { type: 'StringEnumTypeAnnotation', default: (defaultValue: string), - options: typeAnnotation.types.map(option => ({name: option.value})), + options: typeAnnotation.types.map(option => option.value), }; } else if (unionType === 'NumberLiteralTypeAnnotation') { throw new Error( @@ -298,13 +301,13 @@ function getTypeAnnotation( return { type: 'StringEnumTypeAnnotation', default: (defaultValue: string), - options: typeAnnotation.types.map(option => ({name: option.value})), + options: typeAnnotation.types.map(option => option.value), }; } else if (unionType === 'NumberLiteralTypeAnnotation') { return { type: 'Int32EnumTypeAnnotation', default: (defaultValue: number), - options: typeAnnotation.types.map(option => ({value: option.value})), + options: typeAnnotation.types.map(option => option.value), }; } else { throw new Error( @@ -321,7 +324,10 @@ function getTypeAnnotation( } } -function buildPropSchema(property, types: TypeMap): ?PropTypeShape { +function buildPropSchema( + property, + types: TypeDeclarationMap, +): ?NamedShape { const name = property.key.name; const value = getValueFromTypes(property.value, types); @@ -426,7 +432,7 @@ function verifyPropNotAlreadyDefined( function flattenProperties( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ) { return typeDefinition .map(property => { @@ -456,8 +462,8 @@ function flattenProperties( function getProps( typeDefinition: $ReadOnlyArray, - types: TypeMap, -): $ReadOnlyArray { + types: TypeDeclarationMap, +): $ReadOnlyArray> { return flattenProperties(typeDefinition, types) .map(property => buildPropSchema(property, types)) .filter(Boolean); diff --git a/packages/react-native-codegen/src/parsers/flow/components/schema.js b/packages/react-native-codegen/src/parsers/flow/components/schema.js index f55e77f162753a..21ce46d6856ea0 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/schema.js +++ b/packages/react-native-codegen/src/parsers/flow/components/schema.js @@ -12,24 +12,25 @@ import type { EventTypeShape, - PropTypeShape, - CommandTypeShape, + NamedShape, + CommandTypeAnnotation, + PropTypeAnnotation, ExtendsPropsShape, SchemaType, OptionsShape, } from '../../../CodegenSchema.js'; -export type ComponentSchemaBuilderConfig = $ReadOnly<{| +export type ComponentSchemaBuilderConfig = $ReadOnly<{ filename: string, componentName: string, extendsProps: $ReadOnlyArray, events: $ReadOnlyArray, - props: $ReadOnlyArray, - commands: $ReadOnlyArray, + props: $ReadOnlyArray>, + commands: $ReadOnlyArray>, options?: ?OptionsShape, -|}>; +}>; -function buildComponentSchema({ +function wrapComponentSchema({ filename, componentName, extendsProps, @@ -41,6 +42,7 @@ function buildComponentSchema({ return { modules: { [filename]: { + type: 'Component', components: { [componentName]: { ...(options || {}), @@ -56,5 +58,5 @@ function buildComponentSchema({ } module.exports = { - buildComponentSchema, + wrapComponentSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/errors.js b/packages/react-native-codegen/src/parsers/flow/errors.js new file mode 100644 index 00000000000000..b480f321f592a4 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/errors.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +class ParserError extends Error { + nodes: $ReadOnlyArray<$FlowFixMe>; + constructor( + hasteModuleName: string, + astNodeOrNodes: $FlowFixMe, + message: string, + ) { + super(`Module ${hasteModuleName}: ${message}`); + + this.nodes = Array.isArray(astNodeOrNodes) + ? astNodeOrNodes + : [astNodeOrNodes]; + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = { + ParserError, +}; diff --git a/packages/react-native-codegen/src/parsers/flow/index.js b/packages/react-native-codegen/src/parsers/flow/index.js index 4de02b0094393d..23c9a930fdaeea 100644 --- a/packages/react-native-codegen/src/parsers/flow/index.js +++ b/packages/react-native-codegen/src/parsers/flow/index.js @@ -15,64 +15,43 @@ import type {SchemaType} from '../../CodegenSchema.js'; const flowParser = require('flow-parser'); const fs = require('fs'); const path = require('path'); -const {buildModuleSchema} = require('./modules/schema'); -const {buildComponentSchema} = require('./components/schema'); -const {processComponent} = require('./components'); -const {processModule} = require('./modules'); - -function getTypes(ast) { - return ast.body.reduce((types, node) => { - if (node.type === 'ExportNamedDeclaration') { - if (node.declaration && node.declaration.type !== 'VariableDeclaration') { - types[node.declaration.id.name] = node.declaration; - } - } else if ( - node.type === 'TypeAlias' || - node.type === 'InterfaceDeclaration' - ) { - types[node.id.name] = node; - } - return types; - }, {}); -} - -function getConfigType(ast, types): 'module' | 'component' { - const defaultExports = ast.body.filter( - node => node.type === 'ExportDefaultDeclaration', - ); - +const {buildComponentSchema} = require('./components'); +const {wrapComponentSchema} = require('./components/schema'); +const {buildModuleSchema} = require('./modules'); +const {wrapModuleSchema} = require('./modules/schema'); +const { + createParserErrorCapturer, + visit, + isModuleRegistryCall, +} = require('./utils'); +const invariant = require('invariant'); + +function getConfigType( + // TODO(T71778680): Flow-type this node. + ast: $FlowFixMe, +): 'module' | 'component' | 'none' { let isComponent = false; + let isModule = false; + + visit(ast, { + CallExpression(node) { + if ( + node.callee.type === 'Identifier' && + node.callee.name === 'codegenNativeComponent' + ) { + isComponent = true; + } - if (defaultExports.length > 0) { - let declaration = defaultExports[0].declaration; - // codegenNativeComponent can be nested inside a cast - // expression so we need to go one level deeper - if (declaration.type === 'TypeCastExpression') { - declaration = declaration.expression; - } - - isComponent = - declaration && - declaration.callee && - declaration.callee.name === 'codegenNativeComponent'; - } - - const typesExtendingTurboModule = Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.extends && - type.extends[0] && - type.extends[0].id.name === 'TurboModule', - ); - - if (typesExtendingTurboModule.length > 1) { - throw new Error( - 'Found two types extending "TurboModule" is one file. Split them into separated files.', - ); - } - - const isModule = typesExtendingTurboModule.length === 1; + if (isModuleRegistryCall(node)) { + isModule = true; + } + }, + InterfaceExtends(node) { + if (node.id.name === 'TurboModule') { + isModule = true; + } + }, + }); if (isModule && isComponent) { throw new Error( @@ -85,45 +64,75 @@ function getConfigType(ast, types): 'module' | 'component' { } else if (isComponent) { return 'component'; } else { - throw new Error( - `Default export for module specified incorrectly. It should containts - either type extending "TurboModule" or "codegenNativeComponent".`, - ); + return 'none'; } } -function buildSchema(contents: string, filename: ?string): ?SchemaType { +function buildSchema(contents: string, filename: ?string): SchemaType { + // Early return for non-Spec JavaScript files + if ( + !contents.includes('codegenNativeComponent') && + !contents.includes('TurboModule') + ) { + return {modules: {}}; + } + const ast = flowParser.parse(contents); + const configType = getConfigType(ast); - const types = getTypes(ast); + switch (configType) { + case 'component': { + return wrapComponentSchema(buildComponentSchema(ast)); + } + case 'module': { + if (filename === undefined || filename === null) { + throw new Error('Filepath expected while parasing a module'); + } + const hasteModuleName = path.basename(filename).replace(/\.js$/, ''); + + const [parsingErrors, tryParse] = createParserErrorCapturer(); + const schema = tryParse(() => + buildModuleSchema(hasteModuleName, ast, tryParse), + ); + + if (parsingErrors.length > 0) { + /** + * TODO(T77968131): We have two options: + * - Throw the first error, but indicate there are more then one errors. + * - Display all errors, nicely formatted. + * + * For the time being, we're just throw the first error. + **/ + + throw parsingErrors[0]; + } - const configType = getConfigType(ast, types); + invariant( + schema != null, + 'When there are no parsing errors, the schema should not be null', + ); - if (configType === 'component') { - return buildComponentSchema(processComponent(ast, types)); - } else { - if (filename === undefined || filename === null) { - throw new Error('Filepath expected while parasing a module'); + return wrapModuleSchema(schema, hasteModuleName); } - const moduleName = path.basename(filename).slice(6, -3); - return buildModuleSchema(processModule(types), moduleName); + default: + return {modules: {}}; } } -function parseFile(filename: string): ?SchemaType { +function parseFile(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); return buildSchema(contents, filename); } -function parseModuleFixture(filename: string): ?SchemaType { +function parseModuleFixture(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); return buildSchema(contents, 'path/NativeSampleTurboModule.js'); } -function parseString(contents: string): ?SchemaType { - return buildSchema(contents); +function parseString(contents: string, filename: ?string): SchemaType { + return buildSchema(contents, filename); } module.exports = { diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js index a326be96accd23..e05e185232ca59 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js @@ -27,7 +27,7 @@ import type {TurboModule} from '../RCTExport'; import * as TurboModuleRegistry from '../TurboModuleRegistry'; export interface Spec extends TurboModule { - // mo methods + // no methods } export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); @@ -200,7 +200,7 @@ type Foo = {| export interface Spec extends TurboModule { // Exported methods. - foo1: (x: Foo) => void; + foo1: (x: Foo) => Foo; foo2: (x: Foo) => void; } @@ -257,6 +257,31 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; +const NATIVE_MODULE_WITH_UNSAFE_OBJECT = ` +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type {TurboModule} from '../RCTExport'; +import * as TurboModuleRegistry from '../TurboModuleRegistry'; +import type {UnsafeObject} from 'react-native/Libraries/Types/CodegenTypes'; + +export interface Spec extends TurboModule { + +getUnsafeObject: (o: UnsafeObject) => UnsafeObject, +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); + +`; + const NATIVE_MODULE_WITH_ROOT_TAG = ` /** * Copyright (c) Facebook, Inc. and its affiliates. @@ -367,6 +392,7 @@ export interface Spec extends TurboModule { export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; + const NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE = ` /** * Copyright (c) Facebook, Inc. and its affiliates. @@ -434,7 +460,7 @@ import type {TurboModule} from '../RCTExport'; import * as TurboModuleRegistry from '../TurboModuleRegistry'; export interface Spec extends TurboModule { - +getArray: (arg: Array>>>>) => Array>>; + +getArray: (arg: Array>>>>) => Array>>; } export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); @@ -496,6 +522,54 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; +const ANDROID_ONLY_NATIVE_MODULE = ` +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {TurboModule} from '../RCTExport'; +import * as TurboModuleRegistry from '../TurboModuleRegistry'; + +export interface Spec extends TurboModule { + // no methods +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModuleAndroid'); + +`; + +const IOS_ONLY_NATIVE_MODULE = ` +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import type {TurboModule} from '../RCTExport'; +import * as TurboModuleRegistry from '../TurboModuleRegistry'; + +export interface Spec extends TurboModule { + // no methods +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModuleIOS'); + +`; + module.exports = { NATIVE_MODULE_WITH_OBJECT_WITH_OBJECT_DEFINED_IN_FILE_AS_PROPERTY, NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE, @@ -506,6 +580,7 @@ module.exports = { NATIVE_MODULE_WITH_COMPLEX_OBJECTS, NATIVE_MODULE_WITH_COMPLEX_OBJECTS_WITH_NULLABLE_KEY, NATIVE_MODULE_WITH_SIMPLE_OBJECT, + NATIVE_MODULE_WITH_UNSAFE_OBJECT, NATIVE_MODULE_WITH_ROOT_TAG, NATIVE_MODULE_WITH_NULLABLE_PARAM, NATIVE_MODULE_WITH_BASIC_ARRAY, @@ -514,4 +589,6 @@ module.exports = { NATIVE_MODULE_WITH_BASIC_PARAM_TYPES, NATIVE_MODULE_WITH_CALLBACK, EMPTY_NATIVE_MODULE, + ANDROID_ONLY_NATIVE_MODULE, + IOS_ONLY_NATIVE_MODULE, }; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap new file mode 100644 index 00000000000000..b17885a171e66c --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -0,0 +1,1336 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT 1`] = `"Module NativeSampleTurboModule: Generic 'Array' must have type parameters."`; + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Module NativeSampleTurboModule: Generic 'Array' must have type parameters."`; + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Module NativeSampleTurboModule: Flow interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property 'sampleBool' refers to a 'BooleanTypeAnnotation'."`; + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Module NativeSampleTurboModule: Generic 'Promise' must have type parameters."`; + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_READ_ONLY_OBJECT_NO_TYPE_FOR_CONTENT 1`] = `"Module NativeSampleTurboModule: Generic '$ReadOnly' must have exactly one type parameter."`; + +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_UNNAMED_PARAMS 1`] = `"Module NativeSampleTurboModule: All function parameters must be named."`; + +exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_EXTENDING_TURBO_MODULE 1`] = `"Module NativeSampleTurboModule: Every NativeModule spec file must declare exactly one NativeModule Flow interface. This file declares 2: 'Spec', and 'Spec2'. Please remove the extraneous Flow interface declarations."`; + +exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `"Module NativeSampleTurboModule: No Flow interfaces extending TurboModule were detected in this NativeModule spec."`; + +exports[`RN Codegen Flow Parser can generate fixture ANDROID_ONLY_NATIVE_MODULE 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [] + }, + 'moduleNames': [ + 'SampleTurboModuleAndroid' + ], + 'excludedPlatforms': [ + 'iOS' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [] + }, + 'moduleNames': [ + 'SampleTurboModuleIOS' + ], + 'excludedPlatforms': [ + 'android' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ALIASES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': { + 'ObjectAlias': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'x', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + }, + { + 'name': 'y', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + }, + { + 'name': 'label', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'truthy', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + 'spec': { + 'properties': [ + { + 'name': 'getNumber', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getVoid', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + }, + 'params': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + } + }, + { + 'name': 'getStringFromAlias', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'StringTypeAnnotation' + }, + 'params': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'ObjectAlias' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_ALIAS 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_ARRAY 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + ] + } + }, + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PARAM_TYPES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'passBool', + 'optional': true, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'passNumber', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'passString', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'passStringish', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_CALLBACK 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getValueWithCallback', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'callback', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'value', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'arr', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + } + ] + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ARRAY 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'StringTypeAnnotation' + } + } + } + } + } + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getObject', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + } + } + ] + } + }, + { + 'name': 'getReadOnlyObject', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + } + } + ] + } + }, + { + 'name': 'getObject2', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'GenericObjectTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'a', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + } + } + ] + } + }, + { + 'name': 'getObjectInArray', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ArrayTypeAnnotation', + 'elementType': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + } + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'const1', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + } + ] + } + } + ] + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS_WITH_NULLABLE_KEY 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getConstants', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'isTesting', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'reactNativeVersion', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'major', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + }, + { + 'name': 'minor', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + }, + { + 'name': 'patch', + 'optional': true, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + }, + { + 'name': 'prerelease', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + } + ] + } + }, + { + 'name': 'forceTouchAvailable', + 'optional': false, + 'typeAnnotation': { + 'type': 'BooleanTypeAnnotation' + } + }, + { + 'name': 'osVersion', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'systemName', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + }, + { + 'name': 'interfaceIdiom', + 'optional': false, + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + ] + }, + 'params': [] + } + } + ] + }, + 'moduleNames': [ + 'PlatformConstants' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_FLOAT_AND_INT32 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getInt', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'Int32TypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'Int32TypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getFloat', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'FloatTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'FloatTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NESTED_ALIASES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': { + 'Bar': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'z', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + }, + 'Foo': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'bar1', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } + }, + { + 'name': 'bar2', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Bar' + } + } + ] + } + }, + 'spec': { + 'properties': [ + { + 'name': 'foo1', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + }, + 'params': [ + { + 'name': 'x', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + } + } + ] + } + }, + { + 'name': 'foo2', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'x', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'Foo' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE_PARAM 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'voidFunc', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'arg', + 'optional': false, + 'typeAnnotation': { + 'type': 'NullableTypeAnnotation', + 'typeAnnotation': { + 'type': 'StringTypeAnnotation' + } + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OBJECT_WITH_OBJECT_DEFINED_IN_FILE_AS_PROPERTY 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': { + 'DisplayMetricsAndroid': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'width', + 'optional': false, + 'typeAnnotation': { + 'type': 'NumberTypeAnnotation' + } + } + ] + } + }, + 'spec': { + 'properties': [ + { + 'name': 'getConstants', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'Dimensions', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'windowPhysicalPixels', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'DisplayMetricsAndroid' + } + } + ] + } + } + ] + }, + 'params': [] + } + }, + { + 'name': 'getConstants2', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'Dimensions', + 'optional': false, + 'typeAnnotation': { + 'type': 'ObjectTypeAnnotation', + 'properties': [ + { + 'name': 'windowPhysicalPixels', + 'optional': false, + 'typeAnnotation': { + 'type': 'TypeAliasTypeAnnotation', + 'name': 'DisplayMetricsAndroid' + } + } + ] + } + } + ] + }, + 'params': [] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getValueWithPromise', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'PromiseTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'getValueWithPromiseDefinedSomewhereElse', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'PromiseTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'getValueWithPromiseObjDefinedSomewhereElse', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'PromiseTypeAnnotation' + }, + 'params': [] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ROOT_TAG 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getRootTag', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'ReservedTypeAnnotation', + 'name': 'RootTag' + }, + 'params': [ + { + 'name': 'rootTag', + 'optional': false, + 'typeAnnotation': { + 'type': 'ReservedTypeAnnotation', + 'name': 'RootTag' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_OBJECT 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getObject', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'GenericObjectTypeAnnotation' + }, + 'params': [ + { + 'name': 'o', + 'optional': false, + 'typeAnnotation': { + 'type': 'GenericObjectTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; + +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_OBJECT 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliases': {}, + 'spec': { + 'properties': [ + { + 'name': 'getUnsafeObject', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'GenericObjectTypeAnnotation' + }, + 'params': [ + { + 'name': 'o', + 'optional': false, + 'typeAnnotation': { + 'type': 'GenericObjectTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleNames': [ + 'SampleTurboModule' + ] + } + } +}" +`; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap deleted file mode 100644 index 0aeb307d1b2201..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap +++ /dev/null @@ -1,1242 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT 1`] = `"Unsupported return type for getString: expected to find annotation for type of array contents"`; - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Unsupported type for getString, param: \\"arg\\": expected to find annotation for type of array contents"`; - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Only methods are supported as module properties. Found BooleanTypeAnnotation in sampleBool"`; - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Unsupported return promise type for getBool: expected to find annotation for type of promise content"`; - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_READ_ONLY_OBJECT_NO_TYPE_FOR_CONTENT 1`] = `"Unsupported param for method \\"getString\\", param \\"arg\\". No type specified for $ReadOnly"`; - -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_UNNAMED_PARAMS 1`] = `"Unsupported type for getBool. Please provide a name for every parameter."`; - -exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_EXTENDING_TURBO_MODULE 1`] = `"Found two types extending \\"TurboModule\\" is one file. Split them into separated files."`; - -exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = ` -"Default export for module specified incorrectly. It should containts - either type extending \\"TurboModule\\" or \\"codegenNativeComponent\\"." -`; - -exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ALIASES 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object { - "ObjectAlias": Object { - "properties": Array [ - Object { - "name": "x", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - Object { - "name": "y", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - Object { - "name": "label", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "truthy", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - "properties": Array [ - Object { - "name": "getNumber", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getVoid", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "a", - "nullable": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "NumberTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "a", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getStringFromAlias", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "a", - "nullable": false, - "typeAnnotation": Object { - "name": "ObjectAlias", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "StringTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_ALIAS 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "elementType": undefined, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": undefined, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_ARRAY 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PARAM_TYPES 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "passBool", - "typeAnnotation": Object { - "optional": true, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "passNumber", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "passString", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "passStringish", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_CALLBACK 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getValueWithCallback", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "callback", - "nullable": false, - "typeAnnotation": Object { - "type": "FunctionTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ARRAY 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "elementType": Object { - "elementType": Object { - "elementType": Object { - "elementType": Object { - "elementType": Object { - "type": "AnyTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": Object { - "elementType": Object { - "elementType": Object { - "type": "StringTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "type": "ArrayTypeAnnotation", - }, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getObject", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getReadOnlyObject", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getObject2", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "a", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "GenericObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getObjectInArray", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "elementType": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "const1", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "nullable": false, - "type": "ArrayTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_OBJECTS_WITH_NULLABLE_KEY 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getConstants", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "isTesting", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "reactNativeVersion", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "major", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - Object { - "name": "minor", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - Object { - "name": "patch", - "optional": true, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - Object { - "name": "prerelease", - "optional": true, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - Object { - "name": "forceTouchAvailable", - "optional": false, - "typeAnnotation": Object { - "type": "BooleanTypeAnnotation", - }, - }, - Object { - "name": "osVersion", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "systemName", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - Object { - "name": "interfaceIdiom", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_FLOAT_AND_INT32 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getInt", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "Int32TypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "Int32TypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getFloat", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": false, - "typeAnnotation": Object { - "type": "FloatTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "FloatTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NESTED_ALIASES 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object { - "Bar": Object { - "properties": Array [ - Object { - "name": "z", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "Foo": Object { - "properties": Array [ - Object { - "name": "bar1", - "optional": false, - "typeAnnotation": Object { - "name": "Bar", - "type": "TypeAliasTypeAnnotation", - }, - }, - Object { - "name": "bar2", - "optional": false, - "typeAnnotation": Object { - "name": "Bar", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - "properties": Array [ - Object { - "name": "foo1", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "x", - "nullable": false, - "typeAnnotation": Object { - "name": "Foo", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "foo2", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "x", - "nullable": false, - "typeAnnotation": Object { - "name": "Foo", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE_PARAM 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "voidFunc", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "arg", - "nullable": true, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "VoidTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OBJECT_WITH_OBJECT_DEFINED_IN_FILE_AS_PROPERTY 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object { - "DisplayMetricsAndroid": Object { - "properties": Array [ - Object { - "name": "width", - "optional": false, - "typeAnnotation": Object { - "type": "NumberTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - "properties": Array [ - Object { - "name": "getConstants", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "Dimensions", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "windowPhysicalPixels", - "optional": false, - "typeAnnotation": Object { - "name": "DisplayMetricsAndroid", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getConstants2", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "properties": Array [ - Object { - "name": "Dimensions", - "optional": false, - "typeAnnotation": Object { - "properties": Array [ - Object { - "name": "windowPhysicalPixels", - "optional": false, - "typeAnnotation": Object { - "name": "DisplayMetricsAndroid", - "type": "TypeAliasTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object { - "SomeObj": Object { - "properties": Array [ - Object { - "name": "a", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, - "properties": Array [ - Object { - "name": "getValueWithPromise", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "GenericPromiseTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getValueWithPromiseDefinedSomewhereElse", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "GenericPromiseTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - Object { - "name": "getValueWithPromiseObjDefinedSomewhereElse", - "typeAnnotation": Object { - "optional": false, - "params": Array [], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "GenericPromiseTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ROOT_TAG 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getRootTag", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "rootTag", - "nullable": false, - "typeAnnotation": Object { - "name": "RootTag", - "type": "ReservedFunctionValueTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "name": "RootTag", - "nullable": false, - "type": "ReservedFunctionValueTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; - -exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_OBJECT 1`] = ` -Object { - "modules": Object { - "NativeSampleTurboModule": Object { - "nativeModules": Object { - "SampleTurboModule": Object { - "aliases": Object {}, - "properties": Array [ - Object { - "name": "getObject", - "typeAnnotation": Object { - "optional": false, - "params": Array [ - Object { - "name": "o", - "nullable": false, - "typeAnnotation": Object { - "type": "GenericObjectTypeAnnotation", - }, - }, - ], - "returnTypeAnnotation": Object { - "nullable": false, - "type": "GenericObjectTypeAnnotation", - }, - "type": "FunctionTypeAnnotation", - }, - }, - ], - }, - }, - }, - }, -} -`; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js new file mode 100644 index 00000000000000..ef3354df45f3e2 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js @@ -0,0 +1,1271 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type { + NativeModuleReturnTypeAnnotation, + NativeModuleBaseTypeAnnotation, + NativeModuleSchema, + NativeModuleParamTypeAnnotation, +} from '../../../../CodegenSchema'; + +const {parseString} = require('../../index.js'); +const {unwrapNullable} = require('../utils'); +const { + UnsupportedFlowGenericParserError, + UnsupportedFlowTypeAnnotationParserError, + UnnamedFunctionParamParserError, + IncorrectlyParameterizedFlowGenericParserError, +} = require('../errors'); +const invariant = require('invariant'); + +type PrimitiveTypeAnnotationType = + | 'StringTypeAnnotation' + | 'NumberTypeAnnotation' + | 'Int32TypeAnnotation' + | 'DoubleTypeAnnotation' + | 'FloatTypeAnnotation' + | 'BooleanTypeAnnotation'; + +const PRIMITIVES: $ReadOnlyArray<[string, PrimitiveTypeAnnotationType]> = [ + ['string', 'StringTypeAnnotation'], + ['number', 'NumberTypeAnnotation'], + ['Int32', 'Int32TypeAnnotation'], + ['Double', 'DoubleTypeAnnotation'], + ['Float', 'FloatTypeAnnotation'], + ['boolean', 'BooleanTypeAnnotation'], +]; + +const RESERVED_FUNCTION_VALUE_TYPE_NAME: $ReadOnlyArray<'RootTag'> = [ + 'RootTag', +]; + +const MODULE_NAME = 'NativeFoo'; + +const TYPE_ALIAS_DECLARATIONS = ` +type Animal = { + name: string, +}; + +type AnimalPointer = Animal; +`; + +function expectAnimalTypeAliasToExist(module: NativeModuleSchema) { + const animalAlias = module.aliases.Animal; + + expect(animalAlias).not.toBe(null); + invariant(animalAlias != null, ''); + expect(animalAlias.type).toBe('ObjectTypeAnnotation'); + expect(animalAlias.properties.length).toBe(1); + expect(animalAlias.properties[0].name).toBe('name'); + expect(animalAlias.properties[0].optional).toBe(false); + + const [typeAnnotation, nullable] = unwrapNullable( + animalAlias.properties[0].typeAnnotation, + ); + + expect(typeAnnotation.type).toBe('StringTypeAnnotation'); + expect(nullable).toBe(false); +} + +describe('Flow Module Parser', () => { + describe('Parameter Parsing', () => { + it("should fail parsing when a method has an parameter of type 'any'", () => { + const parser = () => + parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(arg: any): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(parser).toThrow(UnsupportedFlowTypeAnnotationParserError); + }); + + it('should fail parsing when a function param type is unamed', () => { + const parser = () => + parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(boolean): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(parser).toThrow(UnnamedFunctionParamParserError); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable, optional}) => { + const PARAM_TYPE_DESCRIPTION = + nullable && optional + ? 'a nullable and optional' + : nullable + ? 'a nullable' + : optional + ? 'an optional' + : 'a required'; + + function annotateArg(paramName: string, paramType: string) { + if (nullable && optional) { + return `${paramName}?: ?${paramType}`; + } + if (nullable) { + return `${paramName}: ?${paramType}`; + } + if (optional) { + return `${paramName}?: ${paramType}`; + } + return `${paramName}: ${paramType}`; + } + + function parseParamType( + paramName: string, + paramType: string, + ): [NativeModuleParamTypeAnnotation, NativeModuleSchema] { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + ${TYPE_ALIAS_DECLARATIONS} + + export interface Spec extends TurboModule { + +useArg(${annotateArg(paramName, paramType)}): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.spec.properties[0]).not.toBe(null); + const param = unwrapNullable( + module.spec.properties[0].typeAnnotation, + )[0].params[0]; + expect(param).not.toBe(null); + expect(param.name).toBe(paramName); + expect(param.optional).toBe(optional); + const [ + paramTypeAnnotation, + isParamTypeAnnotationNullable, + ] = unwrapNullable(param.typeAnnotation); + expect(isParamTypeAnnotationNullable).toBe(nullable); + + return [paramTypeAnnotation, module]; + } + + describe( + (nullable && optional + ? 'Nullable and Optional' + : nullable + ? 'Nullable' + : optional + ? 'Optional' + : 'Required') + ' Parameter', + () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Function'`, () => { + expect(() => parseParamType('arg', 'Function')).toThrow( + UnsupportedFlowGenericParserError, + ); + }); + + describe('Primitive types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} primitive parameter of type '${FLOW_TYPE}'`, () => { + const [paramTypeAnnotation] = parseParamType('arg', FLOW_TYPE); + expect(paramTypeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Object'`, () => { + const [paramTypeAnnotation] = parseParamType('arg', 'Object'); + expect(paramTypeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of reserved type '${FLOW_TYPE}'`, () => { + const [paramTypeAnnotation] = parseParamType('arg', FLOW_TYPE); + + expect(paramTypeAnnotation.type).toBe('ReservedTypeAnnotation'); + invariant( + paramTypeAnnotation.type === 'ReservedTypeAnnotation', + 'Param must be a Reserved type', + ); + + expect(paramTypeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Array Types', () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array'`, () => { + expect(() => parseParamType('arg', 'Array')).toThrow( + IncorrectlyParameterizedFlowGenericParserError, + ); + }); + + function parseParamArrayElementType( + paramName: string, + paramType: string, + ): [NativeModuleBaseTypeAnnotation, NativeModuleSchema] { + const [paramTypeAnnotation, module] = parseParamType( + paramName, + `Array<${paramType}>`, + ); + + expect(paramTypeAnnotation.type).toBe('ArrayTypeAnnotation'); + invariant(paramTypeAnnotation.type === 'ArrayTypeAnnotation', ''); + + expect(paramTypeAnnotation.elementType).not.toBe(null); + invariant(paramTypeAnnotation.elementType != null, ''); + const [ + elementType, + isElementTypeNullable, + ] = unwrapNullable( + paramTypeAnnotation.elementType, + ); + expect(isElementTypeNullable).toBe(false); + return [elementType, module]; + } + + // TODO: Do we support nullable element types? + + describe('Primitive Element Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Element Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + FLOW_TYPE, + ); + expect(elementType.type).toBe('ReservedTypeAnnotation'); + invariant(elementType.type === 'ReservedTypeAnnotation', ''); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array'`, () => { + const [elementType] = parseParamArrayElementType('arg', 'Object'); + expect(elementType.type).toBe('GenericObjectTypeAnnotation'); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some array of an alias`, () => { + const [elementType, module] = parseParamArrayElementType( + 'arg', + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant(elementType.type === 'TypeAliasTypeAnnotation', ''); + + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<{foo: ?string}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + '{foo: ?string}', + ); + expect(elementType).not.toBe(null); + + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + invariant(properties != null, ''); + + expect(properties).not.toBe(null); + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + + const [typeAnnotation, isPropertyNullable] = unwrapNullable( + properties[0].typeAnnotation, + ); + + expect(typeAnnotation.type).toBe('StringTypeAnnotation'); + expect(isPropertyNullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias`, () => { + const [paramTypeAnnotation, module] = parseParamType( + 'arg', + 'Animal', + ); + expect(paramTypeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + paramTypeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(paramTypeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias that points to another type alias`, () => { + const [paramTypeAnnotation, module] = parseParamType( + 'arg', + 'AnimalPointer', + ); + expect(paramTypeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + paramTypeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(paramTypeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias that points to another nullable type alias`, () => { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + type Animal = ?{ + name: string, + }; + + type AnimalPointer = Animal; + + export interface Spec extends TurboModule { + +useArg(${annotateArg('arg', 'AnimalPointer')}): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.spec.properties[0]).not.toBe(null); + const param = unwrapNullable( + module.spec.properties[0].typeAnnotation, + )[0].params[0]; + expect(param.name).toBe('arg'); + expect(param.optional).toBe(optional); + + // The TypeAliasAnnotation is called Animal, and is nullable + const [ + paramTypeAnnotation, + isParamTypeAnnotationNullable, + ] = unwrapNullable(param.typeAnnotation); + expect(paramTypeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + paramTypeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(paramTypeAnnotation.name).toBe('Animal'); + expect(isParamTypeAnnotationNullable).toBe(true); + + // The Animal type alias RHS is valid, and non-null + expectAnimalTypeAliasToExist(module); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable: isPropNullable, optional: isPropOptional}) => { + const PROP_TYPE_DESCRIPTION = + isPropNullable && isPropOptional + ? 'a nullable and optional' + : isPropNullable + ? 'a nullable' + : isPropOptional + ? 'an optional' + : 'a required'; + + function annotateProp(propName: string, propType: string) { + if (isPropNullable && isPropOptional) { + return `${propName}?: ?${propType}`; + } + if (isPropNullable) { + return `${propName}: ?${propType}`; + } + if (isPropOptional) { + return `${propName}?: ${propType}`; + } + return `${propName}: ${propType}`; + } + + function parseParamTypeObjectLiteralProp( + propName: string, + propType: string, + ): [ + $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: NativeModuleBaseTypeAnnotation, + }>, + NativeModuleSchema, + ] { + const [paramTypeAnnotation, module] = parseParamType( + 'arg', + `{${annotateProp(propName, propType)}}`, + ); + + expect(paramTypeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + paramTypeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = paramTypeAnnotation; + + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties.length).toBe(1); + expect(properties[0].name).toBe(propName); + expect(properties[0].optional).toBe(isPropOptional); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation).not.toBe(null); + expect(isPropertyTypeAnnotationNullable).toBe(isPropNullable); + + return [ + { + ...properties[0], + typeAnnotation: propertyTypeAnnotation, + }, + module, + ]; + } + + describe( + (isPropNullable && isPropOptional + ? 'Nullable and Optional' + : isPropNullable + ? 'Nullable' + : isPropOptional + ? 'Optional' + : 'Required') + ' Property', + () => { + describe('Props with Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of primitive type '${FLOW_TYPE}'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + FLOW_TYPE, + ); + expect(prop.typeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Object'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + 'Object', + ); + expect(prop.typeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Props with Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of reserved type '${FLOW_TYPE}'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + FLOW_TYPE, + ); + expect(prop.typeAnnotation.type).toBe( + 'ReservedTypeAnnotation', + ); + invariant( + prop.typeAnnotation.type === 'ReservedTypeAnnotation', + '', + ); + + expect(prop.typeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Props with Array Types', () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array`, () => { + expect(() => + parseParamTypeObjectLiteralProp('prop', 'Array'), + ).toThrow(IncorrectlyParameterizedFlowGenericParserError); + }); + + function parseArrayElementType( + propName: string, + arrayElementType: string, + ): [NativeModuleBaseTypeAnnotation, NativeModuleSchema] { + const [property, module] = parseParamTypeObjectLiteralProp( + 'propName', + `Array<${arrayElementType}>`, + ); + expect(property.typeAnnotation.type).toBe( + 'ArrayTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const { + elementType: nullableElementType, + } = property.typeAnnotation; + expect(nullableElementType).not.toBe(null); + invariant(nullableElementType != null, ''); + + const [ + elementType, + isElementTypeNullable, + ] = unwrapNullable( + nullableElementType, + ); + + expect(isElementTypeNullable).toBe(false); + + return [elementType, module]; + } + + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + + expect(elementType.type).toBe('ReservedTypeAnnotation'); + invariant( + elementType.type === 'ReservedTypeAnnotation', + '', + ); + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + 'Object', + ); + expect(elementType.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type of some array of an alias`, () => { + const [elementType, module] = parseArrayElementType( + 'prop', + 'Animal', + ); + + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant( + elementType.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of 'Array<{foo: ?string}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + '{foo: ?string}', + ); + + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(isPropertyTypeAnnotationNullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type '{foo: ?string}'`, () => { + const [property] = parseParamTypeObjectLiteralProp( + 'prop', + '{foo: ?string}', + ); + + expect(property.typeAnnotation.type).toBe( + 'ObjectTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = property.typeAnnotation; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(isPropertyTypeAnnotationNullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of some type alias`, () => { + const [property, module] = parseParamTypeObjectLiteralProp( + 'prop', + 'Animal', + ); + + expect(property.typeAnnotation.type).toBe( + 'TypeAliasTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + }, + ); + }); + }, + ); + }); + }); + + describe('Return Parsing', () => { + it('should parse methods that have a return type of void', () => { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.spec.properties[0]).not.toBe(null); + + const [ + functionTypeAnnotation, + isFunctionTypeAnnotationNullable, + ] = unwrapNullable(module.spec.properties[0].typeAnnotation); + expect(isFunctionTypeAnnotationNullable).toBe(false); + + const [ + returnTypeAnnotation, + isReturnTypeAnnotationNullable, + ] = unwrapNullable(functionTypeAnnotation.returnTypeAnnotation); + expect(returnTypeAnnotation.type).toBe('VoidTypeAnnotation'); + expect(isReturnTypeAnnotationNullable).toBe(false); + }); + + [true, false].forEach(IS_RETURN_TYPE_NULLABLE => { + const RETURN_TYPE_DESCRIPTION = IS_RETURN_TYPE_NULLABLE + ? 'a nullable' + : 'a non-nullable'; + const annotateRet = retType => + IS_RETURN_TYPE_NULLABLE ? `?${retType}` : retType; + + function parseReturnType( + flowType: string, + ): [NativeModuleReturnTypeAnnotation, NativeModuleSchema] { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + ${TYPE_ALIAS_DECLARATIONS} + + export interface Spec extends TurboModule { + +useArg(): ${annotateRet(flowType)}; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.spec.properties[0]).not.toBe(null); + const [ + functionTypeAnnotation, + isFunctionTypeAnnotationNullable, + ] = unwrapNullable(module.spec.properties[0].typeAnnotation); + expect(isFunctionTypeAnnotationNullable).toBe(false); + + const [ + returnTypeAnnotation, + isReturnTypeAnnotationNullable, + ] = unwrapNullable(functionTypeAnnotation.returnTypeAnnotation); + expect(isReturnTypeAnnotationNullable).toBe(IS_RETURN_TYPE_NULLABLE); + + return [returnTypeAnnotation, module]; + } + + describe( + IS_RETURN_TYPE_NULLABLE ? 'Nullable Returns' : 'Non-Nullable Returns', + () => { + ['Promise', 'Promise<{}>', 'Promise<*>'].forEach( + promiseFlowType => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type '${promiseFlowType}'`, () => { + const [returnTypeAnnotation] = parseReturnType(promiseFlowType); + expect(returnTypeAnnotation.type).toBe('PromiseTypeAnnotation'); + }); + }, + ); + + describe('Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} primitive return of type '${FLOW_TYPE}'`, () => { + const [returnTypeAnnotation] = parseReturnType(FLOW_TYPE); + expect(returnTypeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} reserved return of type '${FLOW_TYPE}'`, () => { + const [returnTypeAnnotation] = parseReturnType(FLOW_TYPE); + expect(returnTypeAnnotation.type).toBe( + 'ReservedTypeAnnotation', + ); + invariant( + returnTypeAnnotation.type === 'ReservedTypeAnnotation', + '', + ); + expect(returnTypeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Array Types', () => { + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array'`, () => { + expect(() => parseReturnType('Array')).toThrow( + IncorrectlyParameterizedFlowGenericParserError, + ); + }); + + function parseArrayElementReturnType( + flowType: string, + ): [NativeModuleBaseTypeAnnotation, NativeModuleSchema] { + const [returnTypeAnnotation, module] = parseReturnType( + 'Array' + (flowType != null ? `<${flowType}>` : ''), + ); + expect(returnTypeAnnotation.type).toBe('ArrayTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const arrayTypeAnnotation = returnTypeAnnotation; + + const {elementType} = arrayTypeAnnotation; + expect(elementType).not.toBe(null); + invariant(elementType != null, ''); + + const [ + elementTypeAnnotation, + isElementTypeAnnotation, + ] = unwrapNullable(elementType); + expect(isElementTypeAnnotation).toBe(false); + + return [elementTypeAnnotation, module]; + } + + // TODO: Do we support nullable element types? + + describe('Primitive Element Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType, module] = parseArrayElementReturnType( + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Element Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementReturnType(FLOW_TYPE); + expect(elementType.type).toBe('ReservedTypeAnnotation'); + invariant(elementType.type === 'ReservedTypeAnnotation', ''); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array'`, () => { + const [elementType] = parseArrayElementReturnType('Object'); + expect(elementType.type).toBe('GenericObjectTypeAnnotation'); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of some array of an alias`, () => { + const [elementType, module] = parseArrayElementReturnType( + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant(elementType.type === 'TypeAliasTypeAnnotation', ''); + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<{foo: ?string}>'`, () => { + const [elementType] = parseArrayElementReturnType( + '{foo: ?string}', + ); + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation.type).toBe('StringTypeAnnotation'); + expect(isPropertyTypeAnnotationNullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of some type alias`, () => { + const [returnTypeAnnotation, module] = parseReturnType('Animal'); + expect(returnTypeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(returnTypeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Function'`, () => { + expect(() => parseReturnType('Function')).toThrow( + UnsupportedFlowGenericParserError, + ); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Object'`, () => { + const [returnTypeAnnotation] = parseReturnType('Object'); + expect(returnTypeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Object Literals Types', () => { + // TODO: Inexact vs exact object literals? + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an empty object literal`, () => { + const [returnTypeAnnotation] = parseReturnType('{}'); + expect(returnTypeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + // Validate properties of object literal + expect(returnTypeAnnotation.properties).not.toBe(null); + expect(returnTypeAnnotation.properties?.length).toBe(0); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable, optional}) => { + const PROP_TYPE_DESCRIPTION = + nullable && optional + ? 'a nullable and optional' + : nullable + ? 'a nullable' + : optional + ? 'an optional' + : 'a required'; + + function annotateProp(propName, propType) { + if (nullable && optional) { + return `${propName}?: ?${propType}`; + } + if (nullable) { + return `${propName}: ?${propType}`; + } + if (optional) { + return `${propName}?: ${propType}`; + } + return `${propName}: ${propType}`; + } + + function parseObjectLiteralReturnTypeProp( + propName: string, + propType: string, + ): [ + $ReadOnly<{ + name: string, + optional: boolean, + typeAnnotation: NativeModuleBaseTypeAnnotation, + }>, + NativeModuleSchema, + ] { + const [returnTypeAnnotation, module] = parseReturnType( + `{${annotateProp(propName, propType)}}`, + ); + expect(returnTypeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const properties = returnTypeAnnotation.properties; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties.length).toBe(1); + + // Validate property + const property = properties[0]; + expect(property.name).toBe(propName); + expect(property.optional).toBe(optional); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(property.typeAnnotation); + + expect(propertyTypeAnnotation).not.toBe(null); + expect(isPropertyTypeAnnotationNullable).toBe(nullable); + return [ + { + ...property, + typeAnnotation: propertyTypeAnnotation, + }, + module, + ]; + } + + describe( + (nullable && optional + ? 'Nullable and Optional' + : nullable + ? 'Nullable' + : optional + ? 'Optional' + : 'Required') + ' Property', + () => { + /** + * TODO: Fill out props in promise + */ + + describe('Props with Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of primitive type '${FLOW_TYPE}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + FLOW_TYPE, + ); + expect(property.typeAnnotation.type).toBe( + PARSED_TYPE_NAME, + ); + }); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Object'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + 'Object', + ); + + expect(property.typeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Props with Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of reserved type '${FLOW_TYPE}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + FLOW_TYPE, + ); + + expect(property.typeAnnotation.type).toBe( + 'ReservedTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === + 'ReservedTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Props with Array Types', () => { + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array`, () => { + expect(() => + parseObjectLiteralReturnTypeProp('prop', 'Array'), + ).toThrow(IncorrectlyParameterizedFlowGenericParserError); + }); + + function parseArrayElementType( + propName: string, + arrayElementType: string, + ): [NativeModuleBaseTypeAnnotation, NativeModuleSchema] { + const [ + property, + module, + ] = parseObjectLiteralReturnTypeProp( + propName, + `Array<${arrayElementType}>`, + ); + expect(property.name).toBe(propName); + expect(property.typeAnnotation.type).toBe( + 'ArrayTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const { + elementType: nullableElementType, + } = property.typeAnnotation; + expect(nullableElementType).not.toBe(null); + invariant(nullableElementType != null, ''); + + const [ + elementType, + isElementTypeNullable, + ] = unwrapNullable( + nullableElementType, + ); + expect(isElementTypeNullable).toBe(false); + + return [elementType, module]; + } + + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + expect(elementType.type).toBe('ReservedTypeAnnotation'); + invariant( + elementType.type === 'ReservedTypeAnnotation', + '', + ); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + 'Object', + ); + expect(elementType).not.toBe(null); + expect(elementType.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type of some array of an aliase`, () => { + const [elementType, module] = parseArrayElementType( + 'prop', + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant( + elementType.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<{foo: ?string}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + '{foo: ?string}', + ); + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant( + elementType.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = elementType; + invariant(properties != null, ''); + expect(properties).not.toBe(null); + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].optional).toBe(false); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(isPropertyTypeAnnotationNullable).toBe(true); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of '{foo: ?string}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + '{foo: ?string}', + ); + + expect(property.typeAnnotation.type).toBe( + 'ObjectTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = property.typeAnnotation; + + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].optional).toBe(false); + + const [ + propertyTypeAnnotation, + isPropertyTypeAnnotationNullable, + ] = unwrapNullable(properties[0].typeAnnotation); + + expect(propertyTypeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(isPropertyTypeAnnotationNullable).toBe(true); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of some type alias`, () => { + const [property, module] = parseObjectLiteralReturnTypeProp( + 'prop', + 'Animal', + ); + + expect(property.typeAnnotation.type).toBe( + 'TypeAliasTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === + 'TypeAliasTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + }, + ); + }); + }); + }, + ); + }); + }); +}); + +function parseModule(source) { + const schema = parseString(source, `${MODULE_NAME}.js`); + const module = schema.modules.NativeFoo; + invariant( + module.type === 'NativeModule', + "'nativeModules' in Spec NativeFoo shouldn't be null", + ); + return module; +} diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js similarity index 81% rename from packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js rename to packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js index 23114e86caa207..cd32e108ef379e 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js @@ -23,7 +23,13 @@ describe('RN Codegen Flow Parser', () => { .sort() .forEach(fixtureName => { it(`can generate fixture ${fixtureName}`, () => { - expect(FlowParser.parseModuleFixture(fixtureName)).toMatchSnapshot(); + const schema = FlowParser.parseModuleFixture(fixtureName); + const serializedSchema = JSON.stringify(schema, null, 2).replace( + /"/g, + "'", + ); + + expect(serializedSchema).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/parsers/flow/modules/aliases.js b/packages/react-native-codegen/src/parsers/flow/modules/aliases.js deleted file mode 100644 index 7c55e4d9ff61a6..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/aliases.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type {ObjectTypeAliasTypeShape} from '../../../CodegenSchema.js'; - -import type {TypeMap} from '../utils.js'; - -const {getObjectProperties} = require('./properties'); - -// $FlowFixMe there's no flowtype for ASTs -type MethodAST = Object; - -function getAliases( - typeDefinition: $ReadOnlyArray, - types: TypeMap, -): $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}> { - const aliases = {}; - typeDefinition.map(moduleAlias => { - const aliasName = Object.keys(moduleAlias)[0]; - const typeAnnotation = moduleAlias[Object.keys(moduleAlias)[0]]; - - switch (typeAnnotation.type) { - case 'ObjectTypeAnnotation': - aliases[aliasName] = { - type: 'ObjectTypeAnnotation', - ...(typeAnnotation.properties && { - properties: getObjectProperties( - aliasName, - {properties: typeAnnotation.properties}, - aliasName, - types, - ), - }), - }; - return; - case 'GenericTypeAnnotation': - if (typeAnnotation.id.name && typeAnnotation.id.name !== '') { - aliases[aliasName] = { - type: 'TypeAliasTypeAnnotation', - name: typeAnnotation.id.name, - }; - return; - } else { - throw new Error( - `Cannot use "${typeAnnotation.type}" type annotation for "${aliasName}": must specify a type alias name`, - ); - } - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error( - `Unknown prop type, found "${typeAnnotation.type}" in "${aliasName}"`, - ); - } - }); - return aliases; -} - -module.exports = { - getAliases, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/errors.js b/packages/react-native-codegen/src/parsers/flow/modules/errors.js new file mode 100644 index 00000000000000..370262cfcb7448 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/errors.js @@ -0,0 +1,335 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +const invariant = require('invariant'); +const {ParserError} = require('../errors'); + +class MisnamedModuleFlowInterfaceParserError extends ParserError { + constructor(hasteModuleName: string, id: $FlowFixMe) { + super( + hasteModuleName, + id, + `All Flow interfaces extending TurboModule must be called 'Spec'. Please rename Flow interface '${id.name}' to 'Spec'.`, + ); + } +} + +class ModuleFlowInterfaceNotFoundParserError extends ParserError { + constructor(hasteModuleName: string, ast: $FlowFixMe) { + super( + hasteModuleName, + ast, + 'No Flow interfaces extending TurboModule were detected in this NativeModule spec.', + ); + } +} + +class MoreThanOneModuleFlowInterfaceParserError extends ParserError { + constructor( + hasteModuleName: string, + flowModuleInterfaces: $ReadOnlyArray<$FlowFixMe>, + names: $ReadOnlyArray, + ) { + const finalName = names[names.length - 1]; + const allButLastName = names.slice(0, -1); + const quote = x => `'${x}'`; + + const nameStr = + allButLastName.map(quote).join(', ') + ', and ' + quote(finalName); + + super( + hasteModuleName, + flowModuleInterfaces, + `Every NativeModule spec file must declare exactly one NativeModule Flow interface. This file declares ${names.length}: ${nameStr}. Please remove the extraneous Flow interface declarations.`, + ); + } +} + +class UnsupportedModulePropertyParserError extends ParserError { + constructor( + hasteModuleName: string, + propertyValue: $FlowFixMe, + propertyName: string, + invalidPropertyValueType: string, + ) { + super( + hasteModuleName, + propertyValue, + `Flow interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property '${propertyName}' refers to a '${invalidPropertyValueType}'.`, + ); + } +} + +class UnsupportedFlowTypeAnnotationParserError extends ParserError { + +typeAnnotationType: string; + constructor(hasteModuleName: string, typeAnnotation: $FlowFixMe) { + super( + hasteModuleName, + typeAnnotation, + `Flow type annotation '${typeAnnotation.type}' is unsupported in NativeModule specs.`, + ); + + this.typeAnnotationType = typeAnnotation.type; + } +} + +class UnsupportedFlowGenericParserError extends ParserError { + +genericName: string; + constructor(hasteModuleName: string, genericTypeAnnotation: $FlowFixMe) { + const genericName = genericTypeAnnotation.id.name; + super( + hasteModuleName, + genericTypeAnnotation, + `Unrecognized generic type '${genericName}' in NativeModule spec.`, + ); + + this.genericName = genericName; + } +} + +class IncorrectlyParameterizedFlowGenericParserError extends ParserError { + +genericName: string; + +numTypeParameters: number; + + constructor(hasteModuleName: string, genericTypeAnnotation: $FlowFixMe) { + if (genericTypeAnnotation.typeParameters == null) { + super( + hasteModuleName, + genericTypeAnnotation, + `Generic '${genericTypeAnnotation.id.name}' must have type parameters.`, + ); + return; + } + + if ( + genericTypeAnnotation.typeParameters.type === + 'TypeParameterInstantiation' && + genericTypeAnnotation.typeParameters.params.length !== 1 + ) { + super( + hasteModuleName, + genericTypeAnnotation.typeParameters, + `Generic '${genericTypeAnnotation.id.name}' must have exactly one type parameter.`, + ); + return; + } + + invariant( + false, + "Couldn't create IncorrectlyParameterizedFlowGenericParserError", + ); + } +} + +/** + * Array parsing errors + */ + +class UnsupportedArrayElementTypeAnnotationParserError extends ParserError { + constructor( + hasteModuleName: string, + arrayElementTypeAST: $FlowFixMe, + arrayType: 'Array' | '$ReadOnlyArray', + invalidArrayElementType: string, + ) { + super( + hasteModuleName, + arrayElementTypeAST, + `${arrayType} element types cannot be '${invalidArrayElementType}'.`, + ); + } +} + +/** + * Object parsing errors + */ + +class UnsupportedObjectPropertyTypeAnnotationParserError extends ParserError { + constructor( + hasteModuleName: string, + propertyAST: $FlowFixMe, + invalidPropertyType: string, + ) { + let message = `'ObjectTypeAnnotation' cannot contain '${invalidPropertyType}'.`; + + if (invalidPropertyType === 'ObjectTypeSpreadProperty') { + message = "Object spread isn't supported in 'ObjectTypeAnnotation's."; + } + + super(hasteModuleName, propertyAST, message); + } +} + +class UnsupportedObjectPropertyValueTypeAnnotationParserError extends ParserError { + constructor( + hasteModuleName: string, + propertyValueAST: $FlowFixMe, + propertyName: string, + invalidPropertyValueType: string, + ) { + super( + hasteModuleName, + propertyValueAST, + `Object property '${propertyName}' cannot have type '${invalidPropertyValueType}'.`, + ); + } +} + +/** + * Function parsing errors + */ + +class UnnamedFunctionParamParserError extends ParserError { + constructor(functionParam: $FlowFixMe, hasteModuleName: string) { + super( + hasteModuleName, + functionParam, + 'All function parameters must be named.', + ); + } +} + +class UnsupportedFunctionParamTypeAnnotationParserError extends ParserError { + constructor( + hasteModuleName: string, + flowParamTypeAnnotation: $FlowFixMe, + paramName: string, + invalidParamType: string, + ) { + super( + hasteModuleName, + flowParamTypeAnnotation, + `Function parameter '${paramName}' cannot have type '${invalidParamType}'.`, + ); + } +} + +class UnsupportedFunctionReturnTypeAnnotationParserError extends ParserError { + constructor( + hasteModuleName: string, + flowReturnTypeAnnotation: $FlowFixMe, + invalidReturnType: string, + ) { + super( + hasteModuleName, + flowReturnTypeAnnotation, + `Function return cannot have type '${invalidReturnType}'.`, + ); + } +} + +class UnusedModuleFlowInterfaceParserError extends ParserError { + constructor(hasteModuleName: string, flowInterface: $FlowFixMe) { + super( + hasteModuleName, + flowInterface, + "Unused NativeModule spec. Please load the NativeModule by calling TurboModuleRegistry.get('').", + ); + } +} + +class MoreThanOneModuleRegistryCallsParserError extends ParserError { + constructor( + hasteModuleName: string, + flowCallExpressions: $FlowFixMe, + numCalls: number, + ) { + super( + hasteModuleName, + flowCallExpressions, + `Every NativeModule spec file must contain exactly one NativeModule load. This file contains ${numCalls}. Please simplify this spec file, splitting it as necessary, to remove the extraneous loads.`, + ); + } +} + +class UntypedModuleRegistryCallParserError extends ParserError { + constructor( + hasteModuleName: string, + flowCallExpression: $FlowFixMe, + methodName: string, + moduleName: string, + ) { + super( + hasteModuleName, + flowCallExpression, + `Please type this NativeModule load: TurboModuleRegistry.${methodName}('${moduleName}').`, + ); + } +} + +class IncorrectModuleRegistryCallTypeParameterParserError extends ParserError { + constructor( + hasteModuleName: string, + flowTypeArguments: $FlowFixMe, + methodName: string, + moduleName: string, + ) { + super( + hasteModuleName, + flowTypeArguments, + `Please change these type arguments to reflect TurboModuleRegistry.${methodName}('${moduleName}').`, + ); + } +} + +class IncorrectModuleRegistryCallArityParserError extends ParserError { + constructor( + hasteModuleName: string, + flowCallExpression: $FlowFixMe, + methodName: string, + incorrectArity: number, + ) { + super( + hasteModuleName, + flowCallExpression, + `Please call TurboModuleRegistry.${methodName}() with exactly one argument. Detected ${incorrectArity}.`, + ); + } +} + +class IncorrectModuleRegistryCallArgumentTypeParserError extends ParserError { + constructor( + hasteModuleName: string, + flowArgument: $FlowFixMe, + methodName: string, + type: string, + ) { + const a = /[aeiouy]/.test(type.toLowerCase()) ? 'an' : 'a'; + super( + hasteModuleName, + flowArgument, + `Please call TurboModuleRegistry.${methodName}() with a string literal. Detected ${a} '${type}'`, + ); + } +} + +module.exports = { + IncorrectlyParameterizedFlowGenericParserError, + MisnamedModuleFlowInterfaceParserError, + ModuleFlowInterfaceNotFoundParserError, + MoreThanOneModuleFlowInterfaceParserError, + UnnamedFunctionParamParserError, + UnsupportedArrayElementTypeAnnotationParserError, + UnsupportedFlowGenericParserError, + UnsupportedFlowTypeAnnotationParserError, + UnsupportedFunctionParamTypeAnnotationParserError, + UnsupportedFunctionReturnTypeAnnotationParserError, + UnsupportedModulePropertyParserError, + UnsupportedObjectPropertyTypeAnnotationParserError, + UnsupportedObjectPropertyValueTypeAnnotationParserError, + UnusedModuleFlowInterfaceParserError, + MoreThanOneModuleRegistryCallsParserError, + UntypedModuleRegistryCallParserError, + IncorrectModuleRegistryCallTypeParameterParserError, + IncorrectModuleRegistryCallArityParserError, + IncorrectModuleRegistryCallArgumentTypeParserError, +}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/index.js b/packages/react-native-codegen/src/parsers/flow/modules/index.js index c09c66acf47c51..1d8b7b55f87c30 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/index.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/index.js @@ -10,67 +10,708 @@ 'use strict'; -import type {NativeModuleSchemaBuilderConfig} from './schema.js'; -const {getAliases} = require('./aliases'); -const {getMethods} = require('./methods'); +import type { + NamedShape, + NativeModuleAliasMap, + NativeModuleArrayTypeAnnotation, + NativeModuleBaseTypeAnnotation, + NativeModuleFunctionTypeAnnotation, + NativeModuleParamTypeAnnotation, + NativeModulePropertyShape, + NativeModuleSchema, + Nullable, +} from '../../../CodegenSchema.js'; -function getModuleProperties(types, interfaceName) { - if (types[interfaceName] && types[interfaceName].body) { - return types[interfaceName].body.properties; +import type {TypeDeclarationMap} from '../utils.js'; +import type {ParserErrorCapturer} from '../utils'; +import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js'; + +const { + resolveTypeAnnotation, + getTypes, + visit, + isModuleRegistryCall, +} = require('../utils.js'); +const {unwrapNullable, wrapNullable} = require('./utils'); +const { + IncorrectlyParameterizedFlowGenericParserError, + MisnamedModuleFlowInterfaceParserError, + ModuleFlowInterfaceNotFoundParserError, + MoreThanOneModuleFlowInterfaceParserError, + UnnamedFunctionParamParserError, + UnsupportedArrayElementTypeAnnotationParserError, + UnsupportedFlowGenericParserError, + UnsupportedFlowTypeAnnotationParserError, + UnsupportedFunctionParamTypeAnnotationParserError, + UnsupportedFunctionReturnTypeAnnotationParserError, + UnsupportedModulePropertyParserError, + UnsupportedObjectPropertyTypeAnnotationParserError, + UnsupportedObjectPropertyValueTypeAnnotationParserError, + UnusedModuleFlowInterfaceParserError, + MoreThanOneModuleRegistryCallsParserError, + UntypedModuleRegistryCallParserError, + IncorrectModuleRegistryCallTypeParameterParserError, + IncorrectModuleRegistryCallArityParserError, + IncorrectModuleRegistryCallArgumentTypeParserError, +} = require('./errors.js'); + +const invariant = require('invariant'); + +function nullGuard(fn: () => T): ?T { + return fn(); +} + +function translateTypeAnnotation( + hasteModuleName: string, + /** + * TODO(T71778680): Flow-type this node. + */ + flowTypeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, + tryParse: ParserErrorCapturer, +): Nullable { + const { + nullable, + typeAnnotation, + typeAliasResolutionStatus, + } = resolveTypeAnnotation(flowTypeAnnotation, types); + + switch (typeAnnotation.type) { + case 'GenericTypeAnnotation': { + switch (typeAnnotation.id.name) { + case 'RootTag': { + return wrapNullable(nullable, { + type: 'ReservedTypeAnnotation', + name: 'RootTag', + }); + } + case 'Promise': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + hasteModuleName, + typeAnnotation, + ); + + return wrapNullable(nullable, { + type: 'PromiseTypeAnnotation', + }); + } + case 'Array': + case '$ReadOnlyArray': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + hasteModuleName, + typeAnnotation, + ); + + try { + /** + * TODO(T72031674): Migrate all our NativeModule specs to not use + * invalid Array ElementTypes. Then, make the elementType a required + * parameter. + */ + const [elementType, isElementTypeNullable] = unwrapNullable( + translateTypeAnnotation( + hasteModuleName, + typeAnnotation.typeParameters.params[0], + types, + aliasMap, + /** + * TODO(T72031674): Ensure that all ParsingErrors that are thrown + * while parsing the array element don't get captured and collected. + * Why? If we detect any parsing error while parsing the element, + * we should default it to null down the line, here. This is + * the correct behaviour until we migrate all our NativeModule specs + * to be parseable. + */ + nullGuard, + ), + ); + + if (elementType.type === 'VoidTypeAnnotation') { + throw new UnsupportedArrayElementTypeAnnotationParserError( + hasteModuleName, + typeAnnotation.typeParameters.params[0], + typeAnnotation.type, + 'void', + ); + } + + if (elementType.type === 'PromiseTypeAnnotation') { + throw new UnsupportedArrayElementTypeAnnotationParserError( + hasteModuleName, + typeAnnotation.typeParameters.params[0], + typeAnnotation.type, + 'Promise', + ); + } + + if (elementType.type === 'FunctionTypeAnnotation') { + throw new UnsupportedArrayElementTypeAnnotationParserError( + hasteModuleName, + typeAnnotation.typeParameters.params[0], + typeAnnotation.type, + 'FunctionTypeAnnotation', + ); + } + + const finalTypeAnnotation: NativeModuleArrayTypeAnnotation< + Nullable, + > = { + type: 'ArrayTypeAnnotation', + elementType: wrapNullable(isElementTypeNullable, elementType), + }; + + return wrapNullable(nullable, finalTypeAnnotation); + } catch (ex) { + return wrapNullable(nullable, { + type: 'ArrayTypeAnnotation', + }); + } + } + case '$ReadOnly': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + hasteModuleName, + typeAnnotation, + ); + + return translateTypeAnnotation( + hasteModuleName, + typeAnnotation.typeParameters.params[0], + types, + aliasMap, + tryParse, + ); + } + case 'Stringish': { + return wrapNullable(nullable, { + type: 'StringTypeAnnotation', + }); + } + case 'Int32': { + return wrapNullable(nullable, { + type: 'Int32TypeAnnotation', + }); + } + case 'Double': { + return wrapNullable(nullable, { + type: 'DoubleTypeAnnotation', + }); + } + case 'Float': { + return wrapNullable(nullable, { + type: 'FloatTypeAnnotation', + }); + } + case 'UnsafeObject': + case 'Object': { + return wrapNullable(nullable, { + type: 'GenericObjectTypeAnnotation', + }); + } + default: { + throw new UnsupportedFlowGenericParserError( + hasteModuleName, + typeAnnotation, + ); + } + } + } + case 'ObjectTypeAnnotation': { + const objectTypeAnnotation = { + type: 'ObjectTypeAnnotation', + properties: (typeAnnotation.properties: Array<$FlowFixMe>) + .map>>( + property => { + return tryParse(() => { + if (property.type !== 'ObjectTypeProperty') { + throw new UnsupportedObjectPropertyTypeAnnotationParserError( + hasteModuleName, + property, + property.type, + ); + } + + const {optional, key} = property; + + const [ + propertyTypeAnnotation, + isPropertyNullable, + ] = unwrapNullable( + translateTypeAnnotation( + hasteModuleName, + property.value, + types, + aliasMap, + tryParse, + ), + ); + + if (propertyTypeAnnotation.type === 'FunctionTypeAnnotation') { + throw new UnsupportedObjectPropertyValueTypeAnnotationParserError( + hasteModuleName, + property.value, + property.key, + propertyTypeAnnotation.type, + ); + } + + if (propertyTypeAnnotation.type === 'VoidTypeAnnotation') { + throw new UnsupportedObjectPropertyValueTypeAnnotationParserError( + hasteModuleName, + property.value, + property.key, + 'void', + ); + } + + if (propertyTypeAnnotation.type === 'PromiseTypeAnnotation') { + throw new UnsupportedObjectPropertyValueTypeAnnotationParserError( + hasteModuleName, + property.value, + property.key, + 'Promise', + ); + } + + return { + name: key.name, + optional, + typeAnnotation: wrapNullable( + isPropertyNullable, + propertyTypeAnnotation, + ), + }; + }); + }, + ) + .filter(Boolean), + }; + + if (!typeAliasResolutionStatus.successful) { + return wrapNullable(nullable, objectTypeAnnotation); + } + + /** + * All aliases RHS are required. + */ + aliasMap[typeAliasResolutionStatus.aliasName] = objectTypeAnnotation; + + /** + * Nullability of type aliases is transitive. + * + * Consider this case: + * + * type Animal = ?{ + * name: string, + * }; + * + * type B = Animal + * + * export interface Spec extends TurboModule { + * +greet: (animal: B) => void; + * } + * + * In this case, we follow B to Animal, and then Animal to ?{name: string}. + * + * We: + * 1. Replace `+greet: (animal: B) => void;` with `+greet: (animal: ?Animal) => void;`, + * 2. Pretend that Animal = {name: string}. + * + * Why do we do this? + * 1. In ObjC, we need to generate a struct called Animal, not B. + * 2. This design is simpler than managing nullability within both the type alias usage, and the type alias RHS. + * 3. What does it mean for a C++ struct, which is what this type alias RHS will generate, to be nullable? ¯\_(ツ)_/¯ + * Nullability is a concept that only makes sense when talking about instances (i.e: usages) of the C++ structs. + * Hence, it's better to manage nullability within the actual TypeAliasTypeAnnotation nodes, and not the + * associated ObjectTypeAnnotations. + */ + return wrapNullable(nullable, { + type: 'TypeAliasTypeAnnotation', + name: typeAliasResolutionStatus.aliasName, + }); + } + case 'BooleanTypeAnnotation': { + return wrapNullable(nullable, { + type: 'BooleanTypeAnnotation', + }); + } + case 'NumberTypeAnnotation': { + return wrapNullable(nullable, { + type: 'NumberTypeAnnotation', + }); + } + case 'VoidTypeAnnotation': { + return wrapNullable(nullable, { + type: 'VoidTypeAnnotation', + }); + } + case 'StringTypeAnnotation': { + return wrapNullable(nullable, { + type: 'StringTypeAnnotation', + }); + } + case 'FunctionTypeAnnotation': { + return wrapNullable( + nullable, + translateFunctionTypeAnnotation( + hasteModuleName, + typeAnnotation, + types, + aliasMap, + tryParse, + ), + ); + } + default: { + throw new UnsupportedFlowTypeAnnotationParserError( + hasteModuleName, + typeAnnotation, + ); + } + } +} + +function assertGenericTypeAnnotationHasExactlyOneTypeParameter( + moduleName: string, + /** + * TODO(T71778680): This is a GenericTypeAnnotation. Flow type this node + */ + typeAnnotation: $FlowFixMe, +) { + if (typeAnnotation.typeParameters == null) { + throw new IncorrectlyParameterizedFlowGenericParserError( + moduleName, + typeAnnotation, + ); } - throw new Error( - `Interface properties for "${interfaceName}" has been specified incorrectly.`, + + invariant( + typeAnnotation.typeParameters.type === 'TypeParameterInstantiation', + "assertGenericTypeAnnotationHasExactlyOneTypeParameter: Type parameters must be an AST node of type 'TypeParameterInstantiation'", ); + + if (typeAnnotation.typeParameters.params.length !== 1) { + throw new IncorrectlyParameterizedFlowGenericParserError( + moduleName, + typeAnnotation, + ); + } } -function findInterfaceName(types) { - return Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.extends && - type.extends[0] && - type.extends[0].id.name === 'TurboModule', - )[0].id.name; +function translateFunctionTypeAnnotation( + hasteModuleName: string, + // TODO(T71778680): This is a FunctionTypeAnnotation. Type this. + flowFunctionTypeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, + tryParse: ParserErrorCapturer, +): NativeModuleFunctionTypeAnnotation { + type Param = NamedShape>; + const params: Array = []; + + for (const flowParam of (flowFunctionTypeAnnotation.params: $ReadOnlyArray<$FlowFixMe>)) { + const parsedParam = tryParse(() => { + if (flowParam.name == null) { + throw new UnnamedFunctionParamParserError(flowParam, hasteModuleName); + } + + const paramName = flowParam.name.name; + const [ + paramTypeAnnotation, + isParamTypeAnnotationNullable, + ] = unwrapNullable( + translateTypeAnnotation( + hasteModuleName, + flowParam.typeAnnotation, + types, + aliasMap, + tryParse, + ), + ); + + if (paramTypeAnnotation.type === 'VoidTypeAnnotation') { + throw new UnsupportedFunctionParamTypeAnnotationParserError( + hasteModuleName, + flowParam.typeAnnotation, + paramName, + 'void', + ); + } + + if (paramTypeAnnotation.type === 'PromiseTypeAnnotation') { + throw new UnsupportedFunctionParamTypeAnnotationParserError( + hasteModuleName, + flowParam.typeAnnotation, + paramName, + 'Promise', + ); + } + + return { + name: flowParam.name.name, + optional: flowParam.optional, + typeAnnotation: wrapNullable( + isParamTypeAnnotationNullable, + paramTypeAnnotation, + ), + }; + }); + + if (parsedParam != null) { + params.push(parsedParam); + } + } + + const [returnTypeAnnotation, isReturnTypeAnnotationNullable] = unwrapNullable( + translateTypeAnnotation( + hasteModuleName, + flowFunctionTypeAnnotation.returnType, + types, + aliasMap, + tryParse, + ), + ); + + if (returnTypeAnnotation.type === 'FunctionTypeAnnotation') { + throw new UnsupportedFunctionReturnTypeAnnotationParserError( + hasteModuleName, + flowFunctionTypeAnnotation.returnType, + 'FunctionTypeAnnotation', + ); + } + + return { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: wrapNullable( + isReturnTypeAnnotationNullable, + returnTypeAnnotation, + ), + params, + }; } -function findAliasNames(types) { - return Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.type && - type.type === 'TypeAlias' && - type.right && - type.right.type === 'ObjectTypeAnnotation', - ) - .map(type => type.id.name); +function buildPropertySchema( + hasteModuleName: string, + // TODO(T71778680): This is an ObjectTypeProperty containing either: + // - a FunctionTypeAnnotation or GenericTypeAnnotation + // - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation + // Flow type this node + property: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, + tryParse: ParserErrorCapturer, +): NativeModulePropertyShape { + let nullable = false; + let {key, value} = property; + + const methodName: string = key.name; + + ({nullable, typeAnnotation: value} = resolveTypeAnnotation(value, types)); + + if (value.type !== 'FunctionTypeAnnotation') { + throw new UnsupportedModulePropertyParserError( + hasteModuleName, + property.value, + property.key.name, + value.type, + ); + } + + return { + name: methodName, + optional: property.optional, + typeAnnotation: wrapNullable( + nullable, + translateFunctionTypeAnnotation( + hasteModuleName, + value, + types, + aliasMap, + tryParse, + ), + ), + }; } -function getModuleAliases(types, aliasNames) { - return aliasNames.map(aliasName => { - if (types[aliasName] && types[aliasName].right) { - return {[aliasName]: types[aliasName].right}; - } - throw new Error( - `Interface properties for "${aliasName}" has been specified incorrectly.`, +function isModuleInterface(node) { + return ( + node.type === 'InterfaceDeclaration' && + node.extends.length === 1 && + node.extends[0].type === 'InterfaceExtends' && + node.extends[0].id.name === 'TurboModule' + ); +} + +function buildModuleSchema( + hasteModuleName: string, + /** + * TODO(T71778680): Flow-type this node. + */ + ast: $FlowFixMe, + tryParse: ParserErrorCapturer, +): NativeModuleSchema { + const types = getTypes(ast); + const moduleSpecs = (Object.values(types): $ReadOnlyArray<$FlowFixMe>).filter( + isModuleInterface, + ); + + if (moduleSpecs.length === 0) { + throw new ModuleFlowInterfaceNotFoundParserError(hasteModuleName, ast); + } + + if (moduleSpecs.length > 1) { + throw new MoreThanOneModuleFlowInterfaceParserError( + hasteModuleName, + moduleSpecs, + moduleSpecs.map(node => node.id.name), + ); + } + + const [moduleSpec] = moduleSpecs; + + if (moduleSpec.id.name !== 'Spec') { + throw new MisnamedModuleFlowInterfaceParserError( + hasteModuleName, + moduleSpec.id, ); + } + + // Parse Module Names + const moduleName = tryParse((): string => { + const callExpressions = []; + visit(ast, { + CallExpression(node) { + if (isModuleRegistryCall(node)) { + callExpressions.push(node); + } + }, + }); + + if (callExpressions.length === 0) { + throw new UnusedModuleFlowInterfaceParserError( + hasteModuleName, + moduleSpec, + ); + } + + if (callExpressions.length > 1) { + throw new MoreThanOneModuleRegistryCallsParserError( + hasteModuleName, + callExpressions, + callExpressions.length, + ); + } + + const [callExpression] = callExpressions; + const {typeArguments} = callExpression; + const methodName = callExpression.callee.property.name; + + if (callExpression.arguments.length !== 1) { + throw new IncorrectModuleRegistryCallArityParserError( + hasteModuleName, + callExpression, + methodName, + callExpression.arguments.length, + ); + } + + if (callExpression.arguments[0].type !== 'Literal') { + const {type} = callExpression.arguments[0]; + throw new IncorrectModuleRegistryCallArgumentTypeParserError( + hasteModuleName, + callExpression.arguments[0], + methodName, + type, + ); + } + + const $moduleName = callExpression.arguments[0].value; + + if (typeArguments == null) { + throw new UntypedModuleRegistryCallParserError( + hasteModuleName, + callExpression, + methodName, + $moduleName, + ); + } + + if ( + typeArguments.type !== 'TypeParameterInstantiation' || + typeArguments.params.length !== 1 || + typeArguments.params[0].type !== 'GenericTypeAnnotation' || + typeArguments.params[0].id.name !== 'Spec' + ) { + throw new IncorrectModuleRegistryCallTypeParameterParserError( + hasteModuleName, + typeArguments, + methodName, + $moduleName, + ); + } + + return $moduleName; }); -} -// $FlowFixMe there's no flowtype for AST -function processModule(types): NativeModuleSchemaBuilderConfig { - const interfaceName = findInterfaceName(types); - const moduleProperties = getModuleProperties(types, interfaceName); - const properties = getMethods(moduleProperties, types); + const moduleNames = moduleName == null ? [] : [moduleName]; - const aliasNames = findAliasNames(types); - const moduleAliases = getModuleAliases(types, aliasNames); - const aliases = getAliases(moduleAliases, types); + // Some module names use platform suffix to indicate platform-exclusive modules. + // Eventually this should be made explicit in the Flow type itself. + // Also check the hasteModuleName for platform suffix. + // Note: this shape is consistent with ComponentSchema. + const excludedPlatforms = []; + const namesToValidate = [...moduleNames, hasteModuleName]; + namesToValidate.forEach(name => { + if (name.endsWith('Android')) { + excludedPlatforms.push('iOS'); + } else if (name.endsWith('IOS')) { + excludedPlatforms.push('android'); + } + }); - return {aliases, properties}; + return (moduleSpec.body.properties: $ReadOnlyArray<$FlowFixMe>) + .filter(property => property.type === 'ObjectTypeProperty') + .map(property => { + const aliasMap: {...NativeModuleAliasMap} = {}; + + return tryParse(() => ({ + aliasMap: aliasMap, + propertyShape: buildPropertySchema( + hasteModuleName, + property, + types, + aliasMap, + tryParse, + ), + })); + }) + .filter(Boolean) + .reduce( + (moduleSchema: NativeModuleSchema, {aliasMap, propertyShape}) => { + return { + type: 'NativeModule', + aliases: {...moduleSchema.aliases, ...aliasMap}, + spec: { + properties: [...moduleSchema.spec.properties, propertyShape], + }, + moduleNames: moduleSchema.moduleNames, + excludedPlatforms: moduleSchema.excludedPlatforms, + }; + }, + { + type: 'NativeModule', + aliases: {}, + spec: {properties: []}, + moduleNames: moduleNames, + excludedPlatforms: + excludedPlatforms.length !== 0 ? [...excludedPlatforms] : undefined, + }, + ); } module.exports = { - processModule, + buildModuleSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/methods.js b/packages/react-native-codegen/src/parsers/flow/modules/methods.js deleted file mode 100644 index c63fc903692d56..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/methods.js +++ /dev/null @@ -1,352 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type { - NativeModuleMethodTypeShape, - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, -} from '../../../CodegenSchema.js'; - -import type {ASTNode, TypeMap} from '../utils.js'; -const {getValueFromTypes} = require('../utils.js'); -const { - getElementTypeForArrayOrObject, - getObjectProperties, -} = require('./properties'); - -// $FlowFixMe there's no flowtype for ASTs -type MethodAST = Object; - -function getTypeAnnotationForParam( - name: string, - paramAnnotation: ASTNode, - types: TypeMap, -): FunctionTypeAnnotationParam { - let param = paramAnnotation; - if (param.name === null) { - throw new Error( - `Unsupported type for ${name}. Please provide a name for every parameter.`, - ); - } - let paramName = param.name.name; - let nullable = false; - if (param.typeAnnotation.type === 'NullableTypeAnnotation') { - nullable = true; - param = paramAnnotation.typeAnnotation; - } - - const typeAnnotation = getValueFromTypes(param.typeAnnotation, types); - const type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }; - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }, - }; - } else { - throw new Error( - `Unsupported type for ${name}, param: "${paramName}": expected to find annotation for type of array contents`, - ); - } - case 'ObjectTypeAnnotation': - if (param.typeAnnotation.type === 'GenericTypeAnnotation') { - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'TypeAliasTypeAnnotation', - name: param.typeAnnotation.id.name, - }, - }; - } - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation, - paramName, - types, - ), - }, - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }, - }; - } else { - throw new Error( - `Unsupported param for method "${name}", param "${paramName}". No type specified for $ReadOnly`, - ); - } - case 'FunctionTypeAnnotation': - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - }, - }; - case 'NumberTypeAnnotation': - case 'BooleanTypeAnnotation': - return { - nullable, - name: paramName, - typeAnnotation: { - type, - }, - }; - - case 'StringTypeAnnotation': - case 'Stringish': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }; - case 'Int32': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'Int32TypeAnnotation', - }, - }; - case 'Float': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'FloatTypeAnnotation', - }, - }; - default: - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }; - } -} - -function getReturnTypeAnnotation( - methodName: string, - returnType, - types: TypeMap, -): FunctionTypeAnnotationReturn { - let typeAnnotation = getValueFromTypes(returnType, types); - let nullable = false; - if (typeAnnotation.type === 'NullableTypeAnnotation') { - nullable = true; - typeAnnotation = typeAnnotation.typeAnnotation; - } - let type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - nullable, - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }; - case 'Promise': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'GenericPromiseTypeAnnotation', - nullable, - }; - } else { - throw new Error( - `Unsupported return promise type for ${methodName}: expected to find annotation for type of promise content`, - ); - } - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - methodName, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported return type for ${methodName}: expected to find annotation for type of array contents`, - ); - } - case 'ObjectTypeAnnotation': - return { - nullable, - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - methodName, - typeAnnotation, - 'returning value', - types, - ), - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - methodName, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported return type for method "${methodName}", No type specified for $ReadOnly`, - ); - } - case 'BooleanTypeAnnotation': - case 'NumberTypeAnnotation': - case 'VoidTypeAnnotation': - return { - nullable, - type, - }; - case 'StringTypeAnnotation': - case 'Stringish': - return { - nullable, - type: 'StringTypeAnnotation', - }; - - case 'Int32': - return { - nullable, - type: 'Int32TypeAnnotation', - }; - case 'Float': - return { - nullable, - type: 'FloatTypeAnnotation', - }; - default: - return { - type: 'GenericObjectTypeAnnotation', - nullable, - }; - } -} - -function buildMethodSchema( - property: MethodAST, - types: TypeMap, -): NativeModuleMethodTypeShape { - const name: string = property.key.name; - const value = getValueFromTypes(property.value, types); - if (value.type !== 'FunctionTypeAnnotation') { - throw new Error( - `Only methods are supported as module properties. Found ${value.type} in ${property.key.name}`, - ); - } - const params = value.params.map(param => - getTypeAnnotationForParam(name, param, types), - ); - - const returnTypeAnnotation = getReturnTypeAnnotation( - name, - getValueFromTypes(value.returnType, types), - types, - ); - return { - name, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation, - params, - optional: property.optional, - }, - }; -} - -function getMethods( - typeDefinition: $ReadOnlyArray, - types: TypeMap, -): $ReadOnlyArray { - return typeDefinition - .filter(property => property.type === 'ObjectTypeProperty') - .map(property => buildMethodSchema(property, types)) - .filter(Boolean); -} - -module.exports = { - getMethods, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/properties.js b/packages/react-native-codegen/src/parsers/flow/modules/properties.js deleted file mode 100644 index f1e8c51e7fe443..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/properties.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type { - FunctionTypeAnnotationParamTypeAnnotation, - ObjectParamTypeAnnotation, - TypeAliasTypeAnnotation, -} from '../../../CodegenSchema.js'; - -import type {ASTNode, TypeMap} from '../utils.js'; -const {getValueFromTypes} = require('../utils.js'); - -function getObjectProperties( - name: string, - objectParam: ASTNode, - paramName: string, - types: TypeMap, -): $ReadOnlyArray { - return objectParam.properties.map(objectTypeProperty => { - let optional = objectTypeProperty.optional; - let value = objectTypeProperty.value; - if (value.type === 'NullableTypeAnnotation') { - if ( - objectTypeProperty.value.typeAnnotation.type !== 'StringTypeAnnotation' - ) { - optional = true; - } - value = objectTypeProperty.value.typeAnnotation; - } - return { - optional, - name: objectTypeProperty.key.name, - typeAnnotation: getElementTypeForArrayOrObject( - name, - value, - paramName, - types, - ), - }; - }); -} - -function getElementTypeForArrayOrObject( - name: string, - arrayParam: ASTNode, - paramName: string, - types: TypeMap, -): - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation - | typeof undefined { - const typeAnnotation = getValueFromTypes(arrayParam, types); - const type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }; - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - name, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported type for "${name}", param: "${paramName}": expected to find annotation for type of nested array contents`, - ); - } - case 'ObjectTypeAnnotation': - if (arrayParam.id) { - return { - type: 'TypeAliasTypeAnnotation', - name: arrayParam.id.name, - }; - } - return { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties(name, typeAnnotation, paramName, types), - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }; - } else { - throw new Error( - `Unsupported param for method "${name}", param "${paramName}". No type specified for $ReadOnly`, - ); - } - case 'AnyTypeAnnotation': - return { - type, - }; - case 'NumberTypeAnnotation': - case 'BooleanTypeAnnotation': - return { - type, - }; - case 'StringTypeAnnotation': - case 'Stringish': - return { - type: 'StringTypeAnnotation', - }; - case 'Int32': - return { - type: 'Int32TypeAnnotation', - }; - case 'Float': - return { - type: 'FloatTypeAnnotation', - }; - case 'TupleTypeAnnotation': - case 'UnionTypeAnnotation': - return undefined; - default: - // TODO T67565166: Generic objects are not type safe and should be disallowed in the schema. - return { - type: 'GenericObjectTypeAnnotation', - }; - } -} - -module.exports = { - getElementTypeForArrayOrObject, - getObjectProperties, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/schema.js b/packages/react-native-codegen/src/parsers/flow/modules/schema.js index c1e4c80cfd5fed..da3da6a4947649 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/schema.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/schema.js @@ -10,35 +10,19 @@ 'use strict'; -import type { - SchemaType, - ObjectTypeAliasTypeShape, - NativeModuleMethodTypeShape, -} from '../../../CodegenSchema.js'; +import type {SchemaType, NativeModuleSchema} from '../../../CodegenSchema.js'; -export type NativeModuleSchemaBuilderConfig = $ReadOnly<{| - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, - properties: $ReadOnlyArray, -|}>; - -function buildModuleSchema( - {aliases, properties}: NativeModuleSchemaBuilderConfig, - moduleName: string, +function wrapModuleSchema( + nativeModuleSchema: NativeModuleSchema, + hasteModuleName: string, ): SchemaType { return { modules: { - [`Native${moduleName}`]: { - nativeModules: { - [moduleName]: { - aliases, - properties, - }, - }, - }, + [hasteModuleName]: nativeModuleSchema, }, }; } module.exports = { - buildModuleSchema, + wrapModuleSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/utils.js b/packages/react-native-codegen/src/parsers/flow/modules/utils.js new file mode 100644 index 00000000000000..8b8aa0b0648d3e --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/utils.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +'use strict'; + +import type { + NativeModuleTypeAnnotation, + Nullable, +} from '../../../CodegenSchema.js'; + +function unwrapNullable<+T: NativeModuleTypeAnnotation>( + x: Nullable, +): [T, boolean] { + if (x.type === 'NullableTypeAnnotation') { + return [x.typeAnnotation, true]; + } + + return [x, false]; +} + +function wrapNullable<+T: NativeModuleTypeAnnotation>( + nullable: boolean, + typeAnnotation: T, +): Nullable { + if (!nullable) { + return typeAnnotation; + } + + return { + type: 'NullableTypeAnnotation', + typeAnnotation, + }; +} + +module.exports = { + unwrapNullable, + wrapNullable, +}; diff --git a/packages/react-native-codegen/src/parsers/flow/utils.js b/packages/react-native-codegen/src/parsers/flow/utils.js index 663b6b90bb941a..8f8727a2850d3c 100644 --- a/packages/react-native-codegen/src/parsers/flow/utils.js +++ b/packages/react-native-codegen/src/parsers/flow/utils.js @@ -10,19 +10,201 @@ 'use strict'; -// $FlowFixMe there's no flowtype for ASTs -export type TypeMap = $ReadOnly<{|[name: string]: Object|}>; +const {ParserError} = require('./errors'); + +/** + * This FlowFixMe is supposed to refer to an InterfaceDeclaration or TypeAlias + * declaration type. Unfortunately, we don't have those types, because flow-parser + * generates them, and flow-parser is not type-safe. In the future, we should find + * a way to get these types from our flow parser library. + * + * TODO(T71778680): Flow type AST Nodes + */ +export type TypeDeclarationMap = {[declarationName: string]: $FlowFixMe}; + +function getTypes(ast: $FlowFixMe): TypeDeclarationMap { + return ast.body.reduce((types, node) => { + if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') { + if ( + node.declaration.type === 'TypeAlias' || + node.declaration.type === 'InterfaceDeclaration' + ) { + types[node.declaration.id.name] = node.declaration; + } + } else if ( + node.type === 'TypeAlias' || + node.type === 'InterfaceDeclaration' + ) { + types[node.id.name] = node; + } + return types; + }, {}); +} // $FlowFixMe there's no flowtype for ASTs export type ASTNode = Object; -function getValueFromTypes(value: ASTNode, types: TypeMap): ASTNode { +const invariant = require('invariant'); + +type TypeAliasResolutionStatus = + | $ReadOnly<{ + successful: true, + aliasName: string, + }> + | $ReadOnly<{ + successful: false, + }>; + +function resolveTypeAnnotation( + // TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, +): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeAliasResolutionStatus: TypeAliasResolutionStatus, +} { + invariant( + typeAnnotation != null, + 'resolveTypeAnnotation(): typeAnnotation cannot be null', + ); + + let node = typeAnnotation; + let nullable = false; + let typeAliasResolutionStatus: TypeAliasResolutionStatus = { + successful: false, + }; + + for (;;) { + if (node.type === 'NullableTypeAnnotation') { + nullable = true; + node = node.typeAnnotation; + } else if (node.type === 'GenericTypeAnnotation') { + typeAliasResolutionStatus = { + successful: true, + aliasName: node.id.name, + }; + const resolvedTypeAnnotation = types[node.id.name]; + if (resolvedTypeAnnotation == null) { + break; + } + + invariant( + resolvedTypeAnnotation.type === 'TypeAlias', + `GenericTypeAnnotation '${node.id.name}' must resolve to a TypeAlias. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`, + ); + + node = resolvedTypeAnnotation.right; + } else { + break; + } + } + + return { + nullable: nullable, + typeAnnotation: node, + typeAliasResolutionStatus, + }; +} + +function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode { if (value.type === 'GenericTypeAnnotation' && types[value.id.name]) { return getValueFromTypes(types[value.id.name].right, types); } return value; } +export type ParserErrorCapturer = (fn: () => T) => ?T; + +function createParserErrorCapturer(): [ + Array, + ParserErrorCapturer, +] { + const errors = []; + function guard(fn: () => T): ?T { + try { + return fn(); + } catch (error) { + if (!(error instanceof ParserError)) { + throw error; + } + errors.push(error); + + return null; + } + } + + return [errors, guard]; +} + +// TODO(T71778680): Flow-type ASTNodes. +function visit( + astNode: $FlowFixMe, + visitor: { + [type: string]: (node: $FlowFixMe) => void, + }, +) { + const queue = [astNode]; + while (queue.length !== 0) { + let item = queue.shift(); + + if (!(typeof item === 'object' && item != null)) { + continue; + } + + if ( + typeof item.type === 'string' && + typeof visitor[item.type] === 'function' + ) { + // Don't visit any children + visitor[item.type](item); + } else if (Array.isArray(item)) { + queue.push(...item); + } else { + queue.push(...Object.values(item)); + } + } +} + +// TODO(T71778680): Flow-type ASTNodes. +function isModuleRegistryCall(node: $FlowFixMe): boolean { + if (node.type !== 'CallExpression') { + return false; + } + + const callExpression = node; + + if (callExpression.callee.type !== 'MemberExpression') { + return false; + } + + const memberExpression = callExpression.callee; + if ( + !( + memberExpression.object.type === 'Identifier' && + memberExpression.object.name === 'TurboModuleRegistry' + ) + ) { + return false; + } + + if ( + !( + memberExpression.property.type === 'Identifier' && + (memberExpression.property.name === 'get' || + memberExpression.property.name === 'getEnforcing') + ) + ) { + return false; + } + return true; +} + module.exports = { getValueFromTypes, + resolveTypeAnnotation, + createParserErrorCapturer, + getTypes, + visit, + isModuleRegistryCall, }; diff --git a/packages/rn-tester/Gemfile b/packages/rn-tester/Gemfile index b3234140e54d42..03d842220cfb0e 100644 --- a/packages/rn-tester/Gemfile +++ b/packages/rn-tester/Gemfile @@ -1,4 +1,4 @@ # Gemfile source 'https://rubygems.org' -gem 'cocoapods', '= 1.9.3' +gem 'cocoapods', '= 1.10.0' diff --git a/packages/rn-tester/NativeModuleExample/NativeScreenshotManager.js b/packages/rn-tester/NativeModuleExample/NativeScreenshotManager.js index 023a8e329560bf..862ffa5213f9c0 100644 --- a/packages/rn-tester/NativeModuleExample/NativeScreenshotManager.js +++ b/packages/rn-tester/NativeModuleExample/NativeScreenshotManager.js @@ -10,8 +10,8 @@ 'use strict'; -import type {TurboModule} from '../../../Libraries/TurboModule/RCTExport'; -import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModuleRegistry'; +import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => {||}; diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 9331c0b35c2b31..63b8dc52935978 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -1,33 +1,49 @@ require_relative '../../scripts/react_native_pods' source 'https://cdn.cocoapods.org/' -platform :ios, '10.0' +platform :ios, '11.0' -if ENV['USE_FRAMEWORKS'] == '1' +USE_FRAMEWORKS = ENV['USE_FRAMEWORKS'] == '1' + +if USE_FRAMEWORKS puts "Installing pods with use_frameworks!" use_frameworks! end +if ENV['USE_HERMES'] == '1' + puts "Using Hermes engine" +end + def pods() project 'RNTesterPods.xcodeproj' - # Enable TurboModule + fabric_enabled = false + + # To use fabric: set the environment variable `USE_FABRIC` to 1, like below + # $ USE_FABRIC=1 bundle exec pod install + # or + # $ export USE_FABRIC=1 + # $ bundle exec pod install + if ENV['USE_FABRIC'] == '1' + puts "Building RNTester with Fabric enabled." + fabric_enabled = true + end + prefix_path = "../.." - use_react_native!(path:prefix_path) + use_react_native!(path: prefix_path, fabric_enabled: fabric_enabled, hermes_enabled: ENV['USE_HERMES'] == '1') pod 'ReactCommon/turbomodule/samples', :path => "#{prefix_path}/ReactCommon" # Additional Pods which aren't included in the default Podfile pod 'React-RCTPushNotification', :path => "#{prefix_path}/Libraries/PushNotificationIOS" - pod 'Yoga',:path => "#{prefix_path}/ReactCommon/yoga", :modular_headers => true + pod 'Yoga', :path => "#{prefix_path}/ReactCommon/yoga", :modular_headers => true # Additional Pods which are classed as unstable - # - # To use fabric: add `fabric_enabled` option to the use_react_native method above, like below - # use_react_native!(path: "..", fabric_enabled: true) end target 'RNTester' do pods() - use_flipper! + if !USE_FRAMEWORKS + use_flipper! + end end target 'RNTesterUnitTests' do @@ -40,31 +56,8 @@ target 'RNTesterIntegrationTests' do pod 'React-RCTTest', :path => "./RCTTest" end -def frameworks_pre_install(installer) - static_frameworks = ['FlipperKit', 'Flipper', 'Flipper-Folly', - 'CocoaAsyncSocket', 'ComponentKit', 'Flipper-DoubleConversion', - 'Flipper-Glog', 'Flipper-PeerTalk', 'Flipper-RSocket', - 'CocoaLibEvent', 'OpenSSL-Universal', 'boost-for-react-native'] - - Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {} - installer.pod_targets.each do |pod| - if static_frameworks.include?(pod.name) - def pod.build_type - Pod::BuildType.static_library - end - end - end -end - -def codegen_pre_install(installer) - system("../../scripts/generate-native-modules-specs.sh") -end - -pre_install do |installer| - frameworks_pre_install(installer) if ENV['USE_FRAMEWORKS'] == '1' - codegen_pre_install(installer) if ENV['USE_CODEGEN'] == '1' -end - post_install do |installer| - flipper_post_install(installer) + if !USE_FRAMEWORKS + flipper_post_install(installer) + end end diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 1c441013b39483..3181e51504f2d0 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -11,56 +11,56 @@ PODS: - React-Core (= 1000.0.0) - React-jsi (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - - Flipper (0.41.5): + - Flipper (0.54.0): - Flipper-Folly (~> 2.2) - Flipper-RSocket (~> 1.1) - Flipper-DoubleConversion (1.1.7) - - Flipper-Folly (2.2.0): + - Flipper-Folly (2.3.0): - boost-for-react-native - CocoaLibEvent (~> 1.0) - Flipper-DoubleConversion - Flipper-Glog - - OpenSSL-Universal (= 1.0.2.19) + - OpenSSL-Universal (= 1.0.2.20) - Flipper-Glog (0.3.6) - Flipper-PeerTalk (0.0.4) - Flipper-RSocket (1.1.0): - Flipper-Folly (~> 2.2) - - FlipperKit (0.41.5): - - FlipperKit/Core (= 0.41.5) - - FlipperKit/Core (0.41.5): - - Flipper (~> 0.41.5) + - FlipperKit (0.54.0): + - FlipperKit/Core (= 0.54.0) + - FlipperKit/Core (0.54.0): + - Flipper (~> 0.54.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - - FlipperKit/CppBridge (0.41.5): - - Flipper (~> 0.41.5) - - FlipperKit/FBCxxFollyDynamicConvert (0.41.5): + - FlipperKit/CppBridge (0.54.0): + - Flipper (~> 0.54.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.54.0): - Flipper-Folly (~> 2.2) - - FlipperKit/FBDefines (0.41.5) - - FlipperKit/FKPortForwarding (0.41.5): + - FlipperKit/FBDefines (0.54.0) + - FlipperKit/FKPortForwarding (0.54.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.41.5) - - FlipperKit/FlipperKitLayoutPlugin (0.41.5): + - FlipperKit/FlipperKitHighlightOverlay (0.54.0) + - FlipperKit/FlipperKitLayoutPlugin (0.54.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.41.5) - - FlipperKit/FlipperKitNetworkPlugin (0.41.5): + - FlipperKit/FlipperKitLayoutTextSearchable (0.54.0) + - FlipperKit/FlipperKitNetworkPlugin (0.54.0): - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.41.5): + - FlipperKit/FlipperKitReactPlugin (0.54.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.41.5): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.54.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.41.5): + - FlipperKit/SKIOSNetworkPlugin (0.54.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - glog (0.3.5) - - OpenSSL-Universal (1.0.2.19): - - OpenSSL-Universal/Static (= 1.0.2.19) - - OpenSSL-Universal/Static (1.0.2.19) + - OpenSSL-Universal (1.0.2.20): + - OpenSSL-Universal/Static (= 1.0.2.20) + - OpenSSL-Universal/Static (1.0.2.20) - RCT-Folly (2020.01.13.00): - boost-for-react-native - DoubleConversion @@ -70,6 +70,10 @@ PODS: - boost-for-react-native - DoubleConversion - glog + - RCT-Folly/Fabric (2020.01.13.00): + - boost-for-react-native + - DoubleConversion + - glog - RCTRequired (1000.0.0) - RCTTypeSafety (1000.0.0): - FBLazyVector (= 1000.0.0) @@ -244,6 +248,289 @@ PODS: - React-jsinspector (= 1000.0.0) - React-perflogger (= 1000.0.0) - React-runtimeexecutor (= 1000.0.0) + - React-Fabric (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-Fabric/animations (= 1000.0.0) + - React-Fabric/attributedstring (= 1000.0.0) + - React-Fabric/better (= 1000.0.0) + - React-Fabric/componentregistry (= 1000.0.0) + - React-Fabric/components (= 1000.0.0) + - React-Fabric/config (= 1000.0.0) + - React-Fabric/core (= 1000.0.0) + - React-Fabric/debug (= 1000.0.0) + - React-Fabric/imagemanager (= 1000.0.0) + - React-Fabric/mounting (= 1000.0.0) + - React-Fabric/scheduler (= 1000.0.0) + - React-Fabric/templateprocessor (= 1000.0.0) + - React-Fabric/textlayoutmanager (= 1000.0.0) + - React-Fabric/uimanager (= 1000.0.0) + - React-Fabric/utils (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/animations (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/attributedstring (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/better (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/componentregistry (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-Fabric/components/activityindicator (= 1000.0.0) + - React-Fabric/components/image (= 1000.0.0) + - React-Fabric/components/inputaccessory (= 1000.0.0) + - React-Fabric/components/legacyviewmanagerinterop (= 1000.0.0) + - React-Fabric/components/modal (= 1000.0.0) + - React-Fabric/components/picker (= 1000.0.0) + - React-Fabric/components/rncore (= 1000.0.0) + - React-Fabric/components/root (= 1000.0.0) + - React-Fabric/components/safeareaview (= 1000.0.0) + - React-Fabric/components/scrollview (= 1000.0.0) + - React-Fabric/components/slider (= 1000.0.0) + - React-Fabric/components/text (= 1000.0.0) + - React-Fabric/components/textinput (= 1000.0.0) + - React-Fabric/components/unimplementedview (= 1000.0.0) + - React-Fabric/components/view (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/activityindicator (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/image (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/inputaccessory (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/legacyviewmanagerinterop (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/modal (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/picker (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/rncore (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/root (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/safeareaview (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/scrollview (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/slider (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/text (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/textinput (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/unimplementedview (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/view (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - Yoga + - React-Fabric/config (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/core (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/debug (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/imagemanager (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - React-RCTImage (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/mounting (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/scheduler (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/templateprocessor (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/textlayoutmanager (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-Fabric/uimanager + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/uimanager (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/utils (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-graphics (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) - React-jsi (1000.0.0): - boost-for-react-native (= 1.63.0) - DoubleConversion @@ -255,6 +542,11 @@ PODS: - DoubleConversion - glog - RCT-Folly (= 2020.01.13.00) + - React-jsi/Fabric (1000.0.0): + - boost-for-react-native (= 1.63.0) + - DoubleConversion + - glog + - RCT-Folly (= 2020.01.13.00) - React-jsiexecutor (1000.0.0): - DoubleConversion - glog @@ -281,6 +573,11 @@ PODS: - React-jsi (= 1000.0.0) - React-RCTNetwork (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTFabric (1000.0.0): + - RCT-Folly/Fabric (= 2020.01.13.00) + - React-Core (= 1000.0.0) + - React-Fabric (= 1000.0.0) + - React-RCTImage (= 1000.0.0) - React-RCTImage (1000.0.0): - FBReactNativeSpec (= 1000.0.0) - RCT-Folly (= 2020.01.13.00) @@ -357,27 +654,28 @@ DEPENDENCIES: - DoubleConversion (from `../../third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../../Libraries/FBLazyVector`) - FBReactNativeSpec (from `../../Libraries/FBReactNativeSpec`) - - Flipper (~> 0.41.1) + - Flipper (~> 0.54.0) - Flipper-DoubleConversion (= 1.1.7) - Flipper-Folly (~> 2.2) - Flipper-Glog (= 0.3.6) - Flipper-PeerTalk (~> 0.0.4) - Flipper-RSocket (~> 1.1) - - FlipperKit (~> 0.41.1) - - FlipperKit/Core (~> 0.41.1) - - FlipperKit/CppBridge (~> 0.41.1) - - FlipperKit/FBCxxFollyDynamicConvert (~> 0.41.1) - - FlipperKit/FBDefines (~> 0.41.1) - - FlipperKit/FKPortForwarding (~> 0.41.1) - - FlipperKit/FlipperKitHighlightOverlay (~> 0.41.1) - - FlipperKit/FlipperKitLayoutPlugin (~> 0.41.1) - - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.41.1) - - FlipperKit/FlipperKitNetworkPlugin (~> 0.41.1) - - FlipperKit/FlipperKitReactPlugin (~> 0.41.1) - - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.41.1) - - FlipperKit/SKIOSNetworkPlugin (~> 0.41.1) + - FlipperKit (~> 0.54.0) + - FlipperKit/Core (~> 0.54.0) + - FlipperKit/CppBridge (~> 0.54.0) + - FlipperKit/FBCxxFollyDynamicConvert (~> 0.54.0) + - FlipperKit/FBDefines (~> 0.54.0) + - FlipperKit/FKPortForwarding (~> 0.54.0) + - FlipperKit/FlipperKitHighlightOverlay (~> 0.54.0) + - FlipperKit/FlipperKitLayoutPlugin (~> 0.54.0) + - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.54.0) + - FlipperKit/FlipperKitNetworkPlugin (~> 0.54.0) + - FlipperKit/FlipperKitReactPlugin (~> 0.54.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.54.0) + - FlipperKit/SKIOSNetworkPlugin (~> 0.54.0) - glog (from `../../third-party-podspecs/glog.podspec`) - RCT-Folly (from `../../third-party-podspecs/RCT-Folly.podspec`) + - RCT-Folly/Fabric (from `../../third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../../Libraries/RCTRequired`) - RCTTypeSafety (from `../../Libraries/TypeSafety`) - React (from `../../`) @@ -387,13 +685,17 @@ DEPENDENCIES: - React-Core/RCTWebSocket (from `../../`) - React-CoreModules (from `../../React/CoreModules`) - React-cxxreact (from `../../ReactCommon/cxxreact`) + - React-Fabric (from `../../ReactCommon`) + - React-graphics (from `../../ReactCommon/react/renderer/graphics`) - React-jsi (from `../../ReactCommon/jsi`) + - React-jsi/Fabric (from `../../ReactCommon/jsi`) - React-jsiexecutor (from `../../ReactCommon/jsiexecutor`) - React-jsinspector (from `../../ReactCommon/jsinspector`) - React-perflogger (from `../../ReactCommon/reactperflogger`) - React-RCTActionSheet (from `../../Libraries/ActionSheetIOS`) - React-RCTAnimation (from `../../Libraries/NativeAnimation`) - React-RCTBlob (from `../../Libraries/Blob`) + - React-RCTFabric (from `../../React`) - React-RCTImage (from `../../Libraries/Image`) - React-RCTLinking (from `../../Libraries/LinkingIOS`) - React-RCTNetwork (from `../../Libraries/Network`) @@ -447,6 +749,10 @@ EXTERNAL SOURCES: :path: "../../React/CoreModules" React-cxxreact: :path: "../../ReactCommon/cxxreact" + React-Fabric: + :path: "../../ReactCommon" + React-graphics: + :path: "../../ReactCommon/react/renderer/graphics" React-jsi: :path: "../../ReactCommon/jsi" React-jsiexecutor: @@ -461,6 +767,8 @@ EXTERNAL SOURCES: :path: "../../Libraries/NativeAnimation" React-RCTBlob: :path: "../../Libraries/Blob" + React-RCTFabric: + :path: "../../React" React-RCTImage: :path: "../../Libraries/Image" React-RCTLinking: @@ -489,45 +797,48 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f DoubleConversion: cde416483dac037923206447da6e1454df403714 - FBLazyVector: 8ea0285646adaf7fa725c20ed737c49ee5ea680a - FBReactNativeSpec: 29b1b8a11346e71351f3a2ba126439810edee362 - Flipper: 33585e2d9810fe5528346be33bcf71b37bb7ae13 + FBLazyVector: 91e874a8823933a268c38765a88cbd5dba1fa024 + FBReactNativeSpec: 17a863c5e24969051850a3acab3a06069bb06e7f + Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 - Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3 + Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 - FlipperKit: bc68102cd4952a258a23c9c1b316c7bec1fecf83 + FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 - OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355 + OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd RCT-Folly: b39288cedafe50da43317ec7d91bcc8cc0abbf33 - RCTRequired: 34582e9b3ebe69f244e091f37218d318406d5c4a - RCTTypeSafety: 84db212a990ce622a28f1bcb1ac68c658e722373 - React: cafb3c2321f7df55ce90dbf29d513799a79e4418 - React-callinvoker: 0dada022d38b73e6e15b33e2a96476153f79bbf6 - React-Core: d377a770bb13aa5120a6ce553f75f0e1cbc1aafe - React-CoreModules: f38b671f8df4c1c744ed69f00264539a7c4024b4 - React-cxxreact: de6de17eac6bbaa4f9fad46b66e7f0c4aaaf863d - React-jsi: 652ad7cb7ff8c87e0e9fb11e9ebcbbc70cdfe865 - React-jsiexecutor: f20d2b5986dbe3d0e94ccbf2d8da24e0d9c42cc9 - React-jsinspector: 7fbf9b42b58b02943a0d89b0ba9fff0070f2de98 - React-perflogger: 1f668f3e4d1adef1fafb3b95e7d6cf922113fe31 - React-RCTActionSheet: 51c43beeb74ef41189e87fe9823e53ebf6210359 - React-RCTAnimation: 62f271148b71d0200773b4959e99a80f624182d4 - React-RCTBlob: b81d69c4dc7f7891a6a3ec969bba9b0a9801b062 - React-RCTImage: 37646ebc761e9f68781867e9e802afdadd18a3dc - React-RCTLinking: b5c261eb3befe7d5c62a4706ae904943e73f9c82 - React-RCTNetwork: 2f6c4ba283c9c2ea768fecc6c681d3ab9448b5f5 - React-RCTPushNotification: a4f86ef3d7c0cb3ee570108a62e39fcd296a5030 - React-RCTSettings: 5a76683d9cf7408b5f8c3306cda3eaf4db191fce - React-RCTTest: 090e9816044220c39462be109dab6d473d94b1c9 - React-RCTText: 6c01963d3e562109f5548262b09b1b2bc260dd60 - React-RCTVibration: 0997fcaf753c7ac0a341177db120eebc438484cf - React-runtimeexecutor: 60dd6204a13f68a1aa1118870edcc604a791df2b - ReactCommon: 1f231b4fbed866032aa084ca23973063bbb51927 - Yoga: f7fa200d8c49f97b54c9421079e781fb900b5cae + RCTRequired: d3d4ce60e1e2282864d7560340690a3c8c646de1 + RCTTypeSafety: 4da4f9f218727257c50fd3bf2683a06cdb4fede3 + React: 63b1f2a4e0e908c95416fd54e9dcca5d409e2a45 + React-callinvoker: e9524d75cf0b7ae108868f8d34c0b8d7dc08ec03 + React-Core: 2b2a8ac8bfb65779965456570a871f4cf5e5e03a + React-CoreModules: 87f011fa87190ffe979e443ce578ec93ec6ff4d4 + React-cxxreact: 14cce64344ab482615dfe82a2cbea6eb73be6481 + React-Fabric: 1744b2e94f5ed2ab247f3a55fd9762d55ed63f3b + React-graphics: 246b8e6cb4aad51271358767c965e47d692921ab + React-jsi: 08c6628096d2025d4085fbaec8fe14a3c9dc667c + React-jsiexecutor: 896c41b04121803e4ee61e4c9ed0900fdb420fea + React-jsinspector: 52fe8073736a97304c9bc61a5bbae8b66ca55701 + React-perflogger: e5c447a0435eb9cdd1e5cd692a48b5c5463406b0 + React-RCTActionSheet: 555656ac47e1b81d986a3822e22c374523e0ed17 + React-RCTAnimation: 639d6784188ee28b3cbb5c4915f18fb63b816a46 + React-RCTBlob: 5f82467e5d3bef65d05cdd900df6e12b0849744a + React-RCTFabric: 7a25f04616e0bcdcda4279a93b42e80ee69b46be + React-RCTImage: f3a98834281555ce1bbbe1af0306aaf40ac70fc7 + React-RCTLinking: 801d05ad5e6d1636e977f4dfeab21f87358a02a5 + React-RCTNetwork: 088b12d5836099ab1e1bd25fc6c8eb07689e7138 + React-RCTPushNotification: ce60993f816f917a6495227e16978b5fd550d73b + React-RCTSettings: 3ff97019291c40903d88ed062642a4fe07d2971d + React-RCTTest: 19f1b769a4bd35ca36bc48645fb218441fc8277d + React-RCTText: 51a41bf9d18a91b2437b833ed4246754baf830d0 + React-RCTVibration: c739e240076fd7dabd90d6242d6a949297565f72 + React-runtimeexecutor: d3e89935c7d4733ddf7da3dd8e0b2533adb7bca4 + ReactCommon: 293077fd73008093e681d96ae99e34e56d47160a + Yoga: 69c2b21737d8220f647e61141aec8c28f7249ef2 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: c38c19657f5aaa2d604f5f4c607f030b60452997 +PODFILE CHECKSUM: 799678aa4c11e7c6d8a431a3883e94b09b8dd0f1 -COCOAPODS: 1.9.3 +COCOAPODS: 1.10.0 diff --git a/packages/rn-tester/RCTTest/RCTSnapshotNativeComponent.js b/packages/rn-tester/RCTTest/RCTSnapshotNativeComponent.js index 9d8b9b949e2815..f9a30031b154dc 100644 --- a/packages/rn-tester/RCTTest/RCTSnapshotNativeComponent.js +++ b/packages/rn-tester/RCTTest/RCTSnapshotNativeComponent.js @@ -12,9 +12,9 @@ const {requireNativeComponent} = require('react-native'); -import type {HostComponent} from '../../../Libraries/Renderer/shims/ReactNativeTypes'; -import type {SyntheticEvent} from '../../../Libraries/Types/CoreEventTypes'; -import type {ViewProps} from '../../../Libraries/Components/View/ViewPropTypes'; +import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; +import type {SyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes'; +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; type SnapshotReadyEvent = SyntheticEvent< $ReadOnly<{testIdentifier: string, ...}>, diff --git a/packages/rn-tester/RCTTest/RCTTestModule.mm b/packages/rn-tester/RCTTest/RCTTestModule.mm index a0bfe8e1390f33..97db1f32a2b3f9 100644 --- a/packages/rn-tester/RCTTest/RCTTestModule.mm +++ b/packages/rn-tester/RCTTest/RCTTestModule.mm @@ -8,7 +8,7 @@ #import "RCTTestModule.h" #import -#import +#import #import #import #import @@ -79,6 +79,7 @@ @implementation RCTTestModule { } @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_MODULE() @@ -120,7 +121,7 @@ - (dispatch_queue_t)methodQueue { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [_bridge.eventDispatcher sendAppEventWithName:name body:body]; + [[_moduleRegistry moduleForName:"EventDispatcher"] sendAppEventWithName:name body:body]; #pragma clang diagnostic pop } diff --git a/packages/rn-tester/RCTTest/RCTTestRunner.m b/packages/rn-tester/RCTTest/RCTTestRunner.m index 161b80b874ea2a..daa047dfcd2aeb 100644 --- a/packages/rn-tester/RCTTest/RCTTestRunner.m +++ b/packages/rn-tester/RCTTest/RCTTestRunner.m @@ -20,8 +20,7 @@ static const NSTimeInterval kTestTimeoutSeconds = 120; -@implementation RCTTestRunner -{ +@implementation RCTTestRunner { FBSnapshotTestController *_testController; RCTBridgeModuleListProvider _moduleProvider; NSString *_appPath; @@ -62,7 +61,8 @@ - (instancetype)initWithApp:(NSString *)app if ((self = [super init])) { if (!referenceDirectory.length) { - referenceDirectory = [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:@"ReferenceImages"]; + referenceDirectory = + [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:@"ReferenceImages"]; } NSString *sanitizedAppName = [app stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; @@ -82,13 +82,13 @@ - (instancetype)initWithApp:(NSString *)app return self; } -RCT_NOT_IMPLEMENTED(- (instancetype)init) +RCT_NOT_IMPLEMENTED(-(instancetype)init) - (NSURL *)defaultScriptURL { if (getenv("CI_USE_PACKAGER") || _useBundler) { - NSString *bundlePrefix = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"RN_BUNDLE_PREFIX"]; - return [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@%@.bundle?platform=ios&dev=true", bundlePrefix, _appPath]]; + return [NSURL + URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.bundle?platform=ios&dev=true", _appPath]]; } else { return [[NSBundle bundleForClass:[RCTBridge class]] URLForResource:@"main" withExtension:@"jsbundle"]; } @@ -121,53 +121,63 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName [self runTest:test module:moduleName initialProps:nil configurationBlock:nil expectErrorBlock:nil]; } -- (void)runTest:(SEL)test module:(NSString *)moduleName - initialProps:(NSDictionary *)initialProps -configurationBlock:(void(^)(RCTRootView *rootView))configurationBlock +- (void)runTest:(SEL)test + module:(NSString *)moduleName + initialProps:(NSDictionary *)initialProps + configurationBlock:(void (^)(RCTRootView *rootView))configurationBlock { - [self runTest:test module:moduleName initialProps:initialProps configurationBlock:configurationBlock expectErrorBlock:nil]; + [self runTest:test + module:moduleName + initialProps:initialProps + configurationBlock:configurationBlock + expectErrorBlock:nil]; } -- (void)runTest:(SEL)test module:(NSString *)moduleName - initialProps:(NSDictionary *)initialProps -configurationBlock:(void(^)(RCTRootView *rootView))configurationBlock -expectErrorRegex:(NSString *)errorRegex +- (void)runTest:(SEL)test + module:(NSString *)moduleName + initialProps:(NSDictionary *)initialProps + configurationBlock:(void (^)(RCTRootView *rootView))configurationBlock + expectErrorRegex:(NSString *)errorRegex { - BOOL(^expectErrorBlock)(NSString *error) = ^BOOL(NSString *error){ + BOOL (^expectErrorBlock)(NSString *error) = ^BOOL(NSString *error) { return [error rangeOfString:errorRegex options:NSRegularExpressionSearch].location != NSNotFound; }; - [self runTest:test module:moduleName initialProps:initialProps configurationBlock:configurationBlock expectErrorBlock:expectErrorBlock]; + [self runTest:test + module:moduleName + initialProps:initialProps + configurationBlock:configurationBlock + expectErrorBlock:expectErrorBlock]; } -- (void)runTest:(SEL)test module:(NSString *)moduleName - initialProps:(NSDictionary *)initialProps -configurationBlock:(void(^)(RCTRootView *rootView))configurationBlock -expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock +- (void)runTest:(SEL)test + module:(NSString *)moduleName + initialProps:(NSDictionary *)initialProps + configurationBlock:(void (^)(RCTRootView *rootView))configurationBlock + expectErrorBlock:(BOOL (^)(NSString *error))expectErrorBlock { __weak RCTBridge *batchedBridge; NSNumber *rootTag; 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]; - } - }); + 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; if (_bridgeDelegate) { bridge = [[RCTBridge alloc] initWithDelegate:_bridgeDelegate launchOptions:nil]; } else { - bridge= [[RCTBridge alloc] initWithBundleURL:_scriptURL - moduleProvider:_moduleProvider - launchOptions:nil]; + bridge = [[RCTBridge alloc] initWithBundleURL:_scriptURL moduleProvider:_moduleProvider launchOptions:nil]; } [bridge.devSettings setIsDebuggingRemotely:_useJSDebugger]; batchedBridge = [bridge batchedBridge]; @@ -183,7 +193,9 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName @autoreleasepool { // The rootView needs to be deallocated after this @autoreleasepool block exits. - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName initialProperties:initialProps]; + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge + moduleName:moduleName + initialProperties:initialProps]; #if TARGET_OS_TV rootView.frame = CGRectMake(0, 0, 1920, 1080); // Standard screen size for tvOS #else @@ -210,20 +222,22 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName } // 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]; - } - }); + 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) { - return ![NSStringFromClass([subview class]) isEqualToString:@"_UILayoutGuide"]; - }]]; + NSArray *nonLayoutSubviews = [vc.view.subviews + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) { + return ![NSStringFromClass([subview class]) isEqualToString:@"_UILayoutGuide"]; + }]]; RCTAssert(nonLayoutSubviews.count == 0, @"There shouldn't be any other views: %@", nonLayoutSubviews); #endif @@ -232,7 +246,8 @@ - (void)runTest:(SEL)test module:(NSString *)moduleName RCTAssert(expectErrorBlock(errors[0]), @"Expected an error but the first one was missing or did not match."); } else { RCTAssert(errors == nil, @"RedBox errors: %@", errors); - RCTAssert(testModule.status != RCTTestStatusPending, @"Test didn't finish within %0.f seconds", kTestTimeoutSeconds); + RCTAssert( + testModule.status != RCTTestStatusPending, @"Test didn't finish within %0.f seconds", kTestTimeoutSeconds); RCTAssert(testModule.status == RCTTestStatusPassed, @"Test failed"); } diff --git a/packages/rn-tester/RCTTest/React-RCTTest.podspec b/packages/rn-tester/RCTTest/React-RCTTest.podspec index 44be5efdb95860..bdef4740b63a1d 100644 --- a/packages/rn-tester/RCTTest/React-RCTTest.podspec +++ b/packages/rn-tester/RCTTest/React-RCTTest.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :tvos => "10.0" } + s.platforms = { :ios => "11.0", :tvos => "11.0" } s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "**/*.{h,m,mm}" diff --git a/packages/rn-tester/README.md b/packages/rn-tester/README.md index 4c9733acf95377..98027009b6fd47 100644 --- a/packages/rn-tester/README.md +++ b/packages/rn-tester/README.md @@ -13,9 +13,9 @@ Before running the app, make sure you ran: ### Running on iOS Both macOS and Xcode are required. - +- `cd packages/rn-tester` - Install [Bundler](https://bundler.io/): `gem install bundler`. We use bundler to install the right version of [CocoaPods](https://cocoapods.org/) locally. -- Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install` +- Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install`. In order to use Hermes engine instead of JSC, run: `USE_HERMES=1 bundle exec pod install` instead. - Open the generated `RNTesterPods.xcworkspace`. This is not checked in, as it is generated by CocoaPods. Do not open `RNTesterPods.xcodeproj` directly. ### Running on Android diff --git a/packages/rn-tester/RNTester-tvOS/Info.plist b/packages/rn-tester/RNTester-tvOS/Info.plist index 1f05733996acbd..0afedbb816c675 100644 --- a/packages/rn-tester/RNTester-tvOS/Info.plist +++ b/packages/rn-tester/RNTester-tvOS/Info.plist @@ -31,7 +31,5 @@ UIUserInterfaceStyle Automatic - RN_BUNDLE_PREFIX - $(RN_BUNDLE_PREFIX) diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 4eb217c9704efa..012c26dd9e6cf6 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -7,20 +7,33 @@ #import "AppDelegate.h" +#ifndef RCT_USE_HERMES +#if __has_include() +#define RCT_USE_HERMES 1 +#else +#define RCT_USE_HERMES 0 +#endif +#endif + +#if RCT_USE_HERMES +#import +#else #import -#import +#endif + #import #import #import +#import +#import +#import +#import +#import +#import #import #import -#import #import -#import #import -#import -#import -#import #import #import @@ -30,14 +43,13 @@ #endif #ifdef RN_FABRIC_ENABLED +#import #import #import -#import #import #endif - #if DEBUG #ifdef FB_SONARKIT_ENABLED #import @@ -54,8 +66,7 @@ #import "RNTesterTurboModuleProvider.h" -@interface AppDelegate() { - +@interface AppDelegate () { #ifdef RN_FABRIC_ENABLED RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; std::shared_ptr _reactNativeConfig; @@ -72,14 +83,14 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith { RCTEnableTurboModule(YES); - _bridge = [[RCTBridge alloc] initWithDelegate:self - launchOptions:launchOptions]; + _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; // Appetizer.io params check NSDictionary *initProps = @{}; NSString *_routeUri = [[NSUserDefaults standardUserDefaults] stringForKey:@"route"]; if (_routeUri) { - initProps = @{@"exampleFromAppetizeParams": [NSString stringWithFormat:@"rntester://example/%@Example", _routeUri]}; + initProps = + @{@"exampleFromAppetizeParams" : [NSString stringWithFormat:@"rntester://example/%@Example", _routeUri]}; } #ifdef RN_FABRIC_ENABLED @@ -88,12 +99,13 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); - _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge - contextContainer:_contextContainer]; + _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer]; _bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; - UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge moduleName:@"RNTesterApp" initialProperties:initProps]; + UIView *rootView = [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:_bridge + moduleName:@"RNTesterApp" + initialProperties:initProps]; #else UIView *rootView = [[RCTRootView alloc] initWithBridge:_bridge moduleName:@"RNTesterApp" initialProperties:initProps]; #endif @@ -109,9 +121,7 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith - (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge { - NSString *bundlePrefix = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"RN_BUNDLE_PREFIX"]; - NSString *bundleRoot = [NSString stringWithFormat:@"%@packages/rn-tester/js/RNTesterApp.ios", bundlePrefix]; - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:bundleRoot + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"packages/rn-tester/js/RNTesterApp.ios" fallbackResource:nil]; } @@ -133,7 +143,7 @@ - (void)initializeFlipper:(UIApplication *)application - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url - options:(NSDictionary *)options + options:(NSDictionary *)options { return [RCTLinkingManager application:app openURL:url options:options]; } @@ -142,12 +152,10 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback { - [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] - onProgress:onProgress - onComplete:loadCallback]; + [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback]; } -# pragma mark - RCTCxxBridgeDelegate +#pragma mark - RCTCxxBridgeDelegate - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { @@ -165,20 +173,22 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge #endif __weak __typeof(self) weakSelf = self; +#if RCT_USE_HERMES + return std::make_unique( +#else return std::make_unique( - facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge](facebook::jsi::Runtime &runtime) { - if (!bridge) { - return; - } - __typeof(self) strongSelf = weakSelf; - if (strongSelf) { - facebook::react::RuntimeExecutor syncRuntimeExecutor = [&](std::function &&callback) { - callback(runtime); - }; - [strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; - } - }) - ); +#endif + facebook::react::RCTJSIExecutorRuntimeInstaller([weakSelf, bridge](facebook::jsi::Runtime &runtime) { + if (!bridge) { + return; + } + __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + facebook::react::RuntimeExecutor syncRuntimeExecutor = + [&](std::function &&callback) { callback(runtime); }; + [strongSelf->_turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; + } + })); } #pragma mark RCTTurboModuleManagerDelegate @@ -195,7 +205,8 @@ - (Class)getModuleClassFromName:(const char *)name } - (std::shared_ptr)getTurboModule:(const std::string &)name - initParams:(const facebook::react::ObjCTurboModule::InitParams &)params + initParams: + (const facebook::react::ObjCTurboModule::InitParams &)params { return facebook::react::RNTesterTurboModuleProvider(name, params); } @@ -203,13 +214,15 @@ - (Class)getModuleClassFromName:(const char *)name - (id)getModuleInstanceFromClass:(Class)moduleClass { if (moduleClass == RCTImageLoader.class) { - return [[moduleClass alloc] initWithRedirectDelegate:nil loadersProvider:^NSArray> *{ - return @[[RCTLocalAssetImageLoader new]]; - } decodersProvider:^NSArray> *{ - return @[[RCTGIFImageDecoder new]]; - }]; + return [[moduleClass alloc] initWithRedirectDelegate:nil + loadersProvider:^NSArray> * { + return @ [[RCTLocalAssetImageLoader new]]; + } + decodersProvider:^NSArray> * { + return @ [[RCTGIFImageDecoder new]]; + }]; } else if (moduleClass == RCTNetworking.class) { - return [[moduleClass alloc] initWithHandlersProvider:^NSArray> *{ + return [[moduleClass alloc] initWithHandlersProvider:^NSArray> * { return @[ [RCTHTTPRequestHandler new], [RCTDataRequestHandler new], @@ -221,24 +234,27 @@ - (Class)getModuleClassFromName:(const char *)name return [moduleClass new]; } -# pragma mark - Push Notifications +#pragma mark - Push Notifications #if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC // Required to register for notifications -- (void)application:(__unused UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings +- (void)application:(__unused UIApplication *)application + didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { [RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings]; } // Required for the remoteNotificationsRegistered event. -- (void)application:(__unused UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +- (void)application:(__unused UIApplication *)application + didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; } // Required for the remoteNotificationRegistrationError event. -- (void)application:(__unused UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +- (void)application:(__unused UIApplication *)application + didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error]; } @@ -250,7 +266,8 @@ - (void)application:(__unused UIApplication *)application didReceiveRemoteNotifi } // Required for the localNotificationReceived event. -- (void)application:(__unused UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification +- (void)application:(__unused UIApplication *)application + didReceiveLocalNotification:(UILocalNotification *)notification { [RCTPushNotificationManager didReceiveLocalNotification:notification]; } diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 3b0806d0b90814..13573d49b86602 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -60,7 +60,5 @@ NSPhotoLibraryUsageDescription You need to add NSPhotoLibraryUsageDescription key in Info.plist to enable photo library usage, otherwise it is going to *fail silently*! - RN_BUNDLE_PREFIX - $(RN_BUNDLE_PREFIX) diff --git a/packages/rn-tester/RNTesterIntegrationTests/RCTLoggingTests.m b/packages/rn-tester/RNTesterIntegrationTests/RCTLoggingTests.m index 3c04e32fe1bc7b..0346208ceb811b 100644 --- a/packages/rn-tester/RNTesterIntegrationTests/RCTLoggingTests.m +++ b/packages/rn-tester/RNTesterIntegrationTests/RCTLoggingTests.m @@ -15,8 +15,7 @@ @interface RCTLoggingTests : XCTestCase @end -@implementation RCTLoggingTests -{ +@implementation RCTLoggingTests { RCTBridge *_bridge; dispatch_semaphore_t _logSem; @@ -29,9 +28,9 @@ - (void)setUp { NSURL *scriptURL; if (getenv("CI_USE_PACKAGER")) { - NSString *bundlePrefix = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"RN_BUNDLE_PREFIX"]; NSString *app = @"IntegrationTests/IntegrationTestsApp"; - scriptURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@%@.bundle?platform=ios&dev=true", bundlePrefix, app]]; + scriptURL = + [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.bundle?platform=ios&dev=true", app]]; } else { scriptURL = [[NSBundle bundleForClass:[RCTBridge class]] URLForResource:@"main" withExtension:@"jsbundle"]; } @@ -59,18 +58,23 @@ - (void)testLogging { // First console log call will fire after 2.0 sec, to allow for any initial log messages // that might come in (seeing this in tvOS) - [_bridge enqueueJSCall:@"LoggingTestModule.logToConsoleAfterWait" args:@[@"Invoking console.log",@2000]]; + [_bridge enqueueJSCall:@"LoggingTestModule.logToConsoleAfterWait" args:@[ @"Invoking console.log", @2000 ]]; // Spin native layer for 1.9 sec [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.9]]; // Now set the log function to signal the semaphore - RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, __unused NSString *fileName, __unused NSNumber *lineNumber, NSString *message) { - if (source == RCTLogSourceJavaScript) { - self->_lastLogLevel = level; - self->_lastLogSource = source; - self->_lastLogMessage = message; - dispatch_semaphore_signal(self->_logSem); - } - }); + RCTSetLogFunction( + ^(RCTLogLevel level, + RCTLogSource source, + __unused NSString *fileName, + __unused NSNumber *lineNumber, + NSString *message) { + if (source == RCTLogSourceJavaScript) { + self->_lastLogLevel = level; + self->_lastLogSource = source; + self->_lastLogMessage = message; + dispatch_semaphore_signal(self->_logSem); + } + }); // Wait for console log to signal the semaphore dispatch_semaphore_wait(_logSem, DISPATCH_TIME_FOREVER); @@ -78,21 +82,21 @@ - (void)testLogging XCTAssertEqual(_lastLogSource, RCTLogSourceJavaScript); XCTAssertEqualObjects(_lastLogMessage, @"Invoking console.log"); - [_bridge enqueueJSCall:@"LoggingTestModule.warning" args:@[@"Generating warning"]]; + [_bridge enqueueJSCall:@"LoggingTestModule.warning" args:@[ @"Generating warning" ]]; dispatch_semaphore_wait(_logSem, DISPATCH_TIME_FOREVER); XCTAssertEqual(_lastLogLevel, RCTLogLevelWarning); XCTAssertEqual(_lastLogSource, RCTLogSourceJavaScript); XCTAssertEqualObjects(_lastLogMessage, @"Generating warning"); - [_bridge enqueueJSCall:@"LoggingTestModule.invariant" args:@[@"Invariant failed"]]; + [_bridge enqueueJSCall:@"LoggingTestModule.invariant" args:@[ @"Invariant failed" ]]; dispatch_semaphore_wait(_logSem, DISPATCH_TIME_FOREVER); XCTAssertEqual(_lastLogLevel, RCTLogLevelError); XCTAssertEqual(_lastLogSource, RCTLogSourceJavaScript); - XCTAssertEqualObjects(_lastLogMessage, @"Invariant Violation: Invariant failed"); + XCTAssertTrue([_lastLogMessage containsString:@"Invariant Violation: Invariant failed"]); - [_bridge enqueueJSCall:@"LoggingTestModule.logErrorToConsole" args:@[@"Invoking console.error"]]; + [_bridge enqueueJSCall:@"LoggingTestModule.logErrorToConsole" args:@[ @"Invoking console.error" ]]; dispatch_semaphore_wait(_logSem, DISPATCH_TIME_FOREVER); // For local bundles, we'll first get a warning about symbolication @@ -104,7 +108,7 @@ - (void)testLogging XCTAssertEqual(_lastLogSource, RCTLogSourceJavaScript); XCTAssertEqualObjects(_lastLogMessage, @"Invoking console.error"); - [_bridge enqueueJSCall:@"LoggingTestModule.throwError" args:@[@"Throwing an error"]]; + [_bridge enqueueJSCall:@"LoggingTestModule.throwError" args:@[ @"Throwing an error" ]]; dispatch_semaphore_wait(_logSem, DISPATCH_TIME_FOREVER); // For local bundles, we'll first get a warning about symbolication @@ -114,7 +118,7 @@ - (void)testLogging XCTAssertEqual(_lastLogLevel, RCTLogLevelError); XCTAssertEqual(_lastLogSource, RCTLogSourceJavaScript); - XCTAssertEqualObjects(_lastLogMessage, @"Error: Throwing an error"); + XCTAssertTrue([_lastLogMessage containsString:@"Error: Throwing an error"]); } @end diff --git a/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m b/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m index 690f86493a5e46..a6d374f935a2c7 100644 --- a/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m +++ b/packages/rn-tester/RNTesterIntegrationTests/RCTRootViewIntegrationTests.m @@ -9,7 +9,7 @@ #import #import -#import +#import #import #import diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index e877dd0c278422..47fb7dd64bf7a9 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -3,11 +3,10 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 1317FC3A10A7E894D970D9F2 /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C2F0C3405B1D6741F52D4F6 /* libPods-RNTester.a */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 272E6B3F1BEA849E001FCF37 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; }; 27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; }; @@ -16,9 +15,10 @@ 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; }; 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; 5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */; }; + 682424F330D42708B52AA9A8 /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 88EFE7E584B42816405BA434 /* libPods-RNTester.a */; }; + 7B37A0C3E18EDC90CCD01CA2 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D00D70BA38970C7995F0A3 /* libPods-RNTesterIntegrationTests.a */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; - CE8B4DF18C0491DAC01826D8 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 240ABDF8133AF49081795AFC /* libPods-RNTesterUnitTests.a */; }; - DBA671A0680021020B916DDB /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4C76DE6ECEDBBAA2CA41B4D /* libPods-RNTesterIntegrationTests.a */; }; + DCB59B3E303512590BDA64B9 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6362DCCAA386FBF557077739 /* libPods-RNTesterUnitTests.a */; }; E7C1241A22BEC44B00DA25C0 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */; }; E7DB20D122B2BAA6005AC45F /* RCTBundleURLProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB20A922B2BAA3005AC45F /* RCTBundleURLProviderTests.m */; }; E7DB20D222B2BAA6005AC45F /* RCTModuleInitNotificationRaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB20AA22B2BAA3005AC45F /* RCTModuleInitNotificationRaceTests.m */; }; @@ -60,6 +60,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + ADA4EF572546F3F8000B7E75 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = RNTester; + }; E7DB215822B2F332005AC45F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; @@ -74,7 +81,6 @@ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RNTester/AppDelegate.h; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = ""; }; - 240ABDF8133AF49081795AFC /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = ""; }; 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UpdatePropertiesExampleView.m; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.m; sourceTree = ""; }; 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlexibleSizeExampleView.m; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.m; sourceTree = ""; }; @@ -83,16 +89,17 @@ 34028D6B10F47E490042EB27 /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = ""; }; 383889D923A7398900D06C3E /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = ""; }; 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = ""; }; - 4C2F0C3405B1D6741F52D4F6 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 5BEC8567F3741044B6A5EFC5 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; 5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = ""; }; 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RNTesterTurboModuleProvider.mm; path = RNTester/RNTesterTurboModuleProvider.mm; sourceTree = ""; }; 5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNTesterTurboModuleProvider.h; path = RNTester/RNTesterTurboModuleProvider.h; sourceTree = ""; }; + 6362DCCAA386FBF557077739 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7D51F73F0DA20287418D98BD /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = ""; }; 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = ""; }; + 88EFE7E584B42816405BA434 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 972A459EE6CF8CC63531A088 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = ""; }; 98233960D1D6A1977D1C7EAF /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = ""; }; - E4C76DE6ECEDBBAA2CA41B4D /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + E6D00D70BA38970C7995F0A3 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E771AEEA22B44E3100EA1189 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = ""; }; E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests.m; sourceTree = ""; }; E7DB209F22B2BA84005AC45F /* RNTesterUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -164,7 +171,7 @@ E7DB215F22B2F3EC005AC45F /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = ""; }; E7DB216022B2F3EC005AC45F /* RNTesterSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterSnapshotTests.m; sourceTree = ""; }; E7DB216122B2F3EC005AC45F /* RCTRootViewIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootViewIntegrationTests.m; sourceTree = ""; }; - E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; }; + E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; }; E9618482EC8608D4872A6E28 /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -173,7 +180,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1317FC3A10A7E894D970D9F2 /* libPods-RNTester.a in Frameworks */, + 682424F330D42708B52AA9A8 /* libPods-RNTester.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -183,7 +190,7 @@ files = ( E7DB213122B2C649005AC45F /* JavaScriptCore.framework in Frameworks */, E7DB213222B2C67D005AC45F /* libOCMock.a in Frameworks */, - CE8B4DF18C0491DAC01826D8 /* libPods-RNTesterUnitTests.a in Frameworks */, + DCB59B3E303512590BDA64B9 /* libPods-RNTesterUnitTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -193,7 +200,7 @@ files = ( E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */, E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */, - DBA671A0680021020B916DDB /* libPods-RNTesterIntegrationTests.a in Frameworks */, + 7B37A0C3E18EDC90CCD01CA2 /* libPods-RNTesterIntegrationTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -263,9 +270,9 @@ E7DB211822B2BD53005AC45F /* libReact-RCTText.a */, E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */, E7DB212222B2BD53005AC45F /* libyoga.a */, - 4C2F0C3405B1D6741F52D4F6 /* libPods-RNTester.a */, - E4C76DE6ECEDBBAA2CA41B4D /* libPods-RNTesterIntegrationTests.a */, - 240ABDF8133AF49081795AFC /* libPods-RNTesterUnitTests.a */, + 88EFE7E584B42816405BA434 /* libPods-RNTester.a */, + E6D00D70BA38970C7995F0A3 /* libPods-RNTesterIntegrationTests.a */, + 6362DCCAA386FBF557077739 /* libPods-RNTesterUnitTests.a */, ); name = Frameworks; sourceTree = ""; @@ -398,7 +405,7 @@ 13B07F8E1A680F5B00A75B9A /* Resources */, 68CD48B71D2BCB2C007E06A9 /* Build JS Bundle */, 5CF0FD27207FC6EC00C13D65 /* Start Metro */, - C1C7A9D58CE1D09515F20577 /* [CP] Copy Pods Resources */, + CD2B49A7F80C8171E7A5B233 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -417,11 +424,12 @@ E7DB209B22B2BA84005AC45F /* Sources */, E7DB209C22B2BA84005AC45F /* Frameworks */, E7DB209D22B2BA84005AC45F /* Resources */, - D45F7C4830D42738CAAC9684 /* [CP] Copy Pods Resources */, + 71ADC6D58A978687B97C823F /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( + ADA4EF582546F3F8000B7E75 /* PBXTargetDependency */, ); name = RNTesterUnitTests; productName = RNTesterUnitTests; @@ -436,7 +444,7 @@ E7DB214F22B2F332005AC45F /* Sources */, E7DB215022B2F332005AC45F /* Frameworks */, E7DB215122B2F332005AC45F /* Resources */, - CD1D70F24AD74F4E13B7435D /* [CP] Copy Pods Resources */, + 87FAF758B87BEA78F26A2B92 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -454,7 +462,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1160; + LastUpgradeCheck = 1210; ORGANIZATIONNAME = Facebook; TargetAttributes = { E7DB209E22B2BA84005AC45F = { @@ -467,7 +475,7 @@ }; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RNTesterPods" */; - compatibilityVersion = "Xcode 9.3"; + compatibilityVersion = "Xcode 12.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -586,26 +594,26 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\nexport PROJECT_ROOT=$SRCROOT/..\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true\n\"$SRCROOT/../../scripts/react-native-xcode.sh\" $SRCROOT/../../packages/rn-tester/js/RNTesterApp.ios.js\n"; + shellScript = "set -e\n\nexport NODE_BINARY=node\nexport PROJECT_ROOT=\"$SRCROOT/../../\"\nexport SOURCEMAP_FILE=../sourcemap.ios.map\n# export FORCE_BUNDLING=true\n\"$SRCROOT/../../scripts/react-native-xcode.sh\" $SRCROOT/../../packages/rn-tester/js/RNTesterApp.ios.js\n"; }; - C1C7A9D58CE1D09515F20577 /* [CP] Copy Pods Resources */ = { + 71ADC6D58A978687B97C823F /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - CD1D70F24AD74F4E13B7435D /* [CP] Copy Pods Resources */ = { + 87FAF758B87BEA78F26A2B92 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -622,21 +630,21 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - D45F7C4830D42738CAAC9684 /* [CP] Copy Pods Resources */ = { + CD2B49A7F80C8171E7A5B233 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNTester/Pods-RNTester-resources.sh\"\n"; showEnvVarsInLog = 0; }; F9CB97B0D9633939D43E75E0 /* [CP] Check Pods Manifest.lock */ = { @@ -723,6 +731,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + ADA4EF582546F3F8000B7E75 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* RNTester */; + targetProxy = ADA4EF572546F3F8000B7E75 /* PBXContainerItemProxy */; + }; E7DB215922B2F332005AC45F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 13B07F861A680F5B00A75B9A /* RNTester */; @@ -739,12 +752,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++14"; DEVELOPMENT_TEAM = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "FB_SONARKIT_ENABLED=1", - ); INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, "$(inherited)", @@ -755,10 +764,6 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", ); "LIBRARY_SEARCH_PATHS[arch=*]" = "$(inherited)"; - OTHER_CFLAGS = ( - "$(inherited)", - "-DFB_SONARKIT_ENABLED=1", - ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -766,7 +771,6 @@ "-framework", "\"JavaScriptCore\"", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -DFB_SONARKIT_ENABLED"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; TARGETED_DEVICE_FAMILY = "1,2"; @@ -781,8 +785,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++14"; DEVELOPMENT_TEAM = ""; + EXCLUDED_ARCHS = ""; INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( /usr/lib/swift, "$(inherited)", @@ -792,10 +797,6 @@ "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", ); - OTHER_CFLAGS = ( - "$(inherited)", - "-DFB_SONARKIT_ENABLED=1", - ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -803,7 +804,6 @@ "-framework", "\"JavaScriptCore\"", ); - OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -DFB_SONARKIT_ENABLED"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.react.uiapp; PRODUCT_NAME = RNTester; TARGETED_DEVICE_FAMILY = "1,2"; @@ -836,6 +836,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -870,7 +871,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CPLUSPLUSFLAGS = ( @@ -918,6 +919,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -945,7 +947,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme b/packages/rn-tester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme index 7342976848dd0d..2731ada4d7698e 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme +++ b/packages/rn-tester/RNTesterPods.xcodeproj/xcshareddata/xcschemes/RNTester.xcscheme @@ -1,6 +1,6 @@ - - = 130000 diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index 3bad38b8dc353f..59a2e64275a35c 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -66,7 +66,7 @@ plugins { * // Root dir for all JS files for the app. Defaults to `root` above. * jsRootDir: "../..", * - * // Enable Fabric at build time and runtime. + * // Enable Fabric at runtime. * enableFabric: true, * * // Java package name to use for any codegen artifacts produced during build time. @@ -85,6 +85,7 @@ project.ext.react = [ hermesCommand: "$rootDir/node_modules/hermes-engine/%OS-BIN%/hermesc", enableHermesForVariant: { def v -> v.name.contains("hermes") }, jsRootDir: "$rootDir/RNTester", + enableCodegen: true, // Keep this here until it's sync'ed to Android template. enableFabric: (System.getenv('USE_FABRIC') ?: '0').toBoolean(), ] @@ -107,7 +108,12 @@ def enableSeparateBuildPerCPUArchitecture = true def enableProguardInReleaseBuilds = true /** - * Build and enable Fabric in RN Tester app. + * Build and enable codegen-related output in RN Tester app. + */ +def enableCodegen = project.ext.react.enableCodegen + +/** + * Enable Fabric in RN Tester app. */ def enableFabric = project.ext.react.enableFabric @@ -121,7 +127,7 @@ def useIntlJsc = false android { compileSdkVersion 29 - + ndkVersion ANDROID_NDK_VERSION compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -141,13 +147,14 @@ android { defaultConfig { applicationId "com.facebook.react.uiapp" - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' buildConfigField("boolean", "ENABLE_FABRIC", "$enableFabric") + buildConfigField("boolean", "ENABLE_TURBOMODULE", "$enableCodegen") // If using codegen, assume using TurboModule } signingConfigs { release { @@ -177,6 +184,14 @@ android { proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" } } + sourceSets.main { + java { + // SampleTurboModule. + srcDirs += [ + "$rootDir/ReactCommon/react/nativemodule/samples/platform/android", + ] + } + } } configurations { @@ -220,8 +235,64 @@ dependencies { } react { - enableCodegen = System.getenv("USE_CODEGEN") ?: false jsRootDir = file("$rootDir/packages/rn-tester") reactNativeRootDir = file("$rootDir") useJavaGenerator = System.getenv("USE_CODEGEN_JAVAPOET") ?: false } + +if (enableCodegen) { + // TODO: Move all this logic to CodegenPlugin.java. + def reactAndroidProjectDir = project(':ReactAndroid').projectDir; + def reactAndroidBuildDir = project(':ReactAndroid').buildDir; + + android { + defaultConfig { + externalNativeBuild { + ndkBuild { + abiFilters "armeabi-v7a", "x86", "x86_64", "arm64-v8a" + arguments "APP_PLATFORM=android-21", + "APP_STL=c++_shared", + "NDK_TOOLCHAIN_VERSION=clang", + // The following paths assume building React Native from source. + "GENERATED_SRC_DIR=$buildDir/generated/source", + "PROJECT_BUILD_DIR=$buildDir", + "REACT_ANDROID_DIR=$reactAndroidProjectDir", + "REACT_ANDROID_BUILD_DIR=$reactAndroidBuildDir" + cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" + cppFlags "-std=c++1y" + targets "rntester_appmodules" + } + } + } + externalNativeBuild { + ndkBuild { + path "$projectDir/src/main/jni/Android.mk" + } + } + } + + def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) { + // TODO: handle extracting .so from prebuilt :ReactAndroid. + dependsOn(":ReactAndroid:packageReactNdkLibs") + from("$reactAndroidBuildDir/react-ndk/exported") + into("$buildDir/react-ndk/exported") + } + + def cleanProjectNdkBuild = tasks.register("cleanProjectNdkBuild", Exec) { + ignoreExitValue(true) + tasks.forEach { + t -> + if (t.name.startsWith("externalNativeBuildClean")) { + dependsOn(t); + } + } + // This .cxx folder may cause stale ndkBuild configuration. + // See https://stackoverflow.com/a/58288851. + commandLine("rm", "-rf", "$projectDir/.cxx") + } + + afterEvaluate { + preBuild.dependsOn(packageReactNdkLibs) + clean.dependsOn(cleanProjectNdkBuild) + } +} diff --git a/packages/rn-tester/android/app/gradle.properties b/packages/rn-tester/android/app/gradle.properties index bba40bc51018e2..5c93b3bca832dc 100644 --- a/packages/rn-tester/android/app/gradle.properties +++ b/packages/rn-tester/android/app/gradle.properties @@ -10,4 +10,4 @@ android.useAndroidX=true android.enableJetifier=true # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.37.0 +FLIPPER_VERSION=0.54.0 diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.java b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.java index d7a315ca26dae4..4cbb384cded703 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.java +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.java @@ -7,8 +7,6 @@ package com.facebook.react.uiapp; -import static com.facebook.react.uiapp.RNTesterApplication.IS_FABRIC_ENABLED; - import android.content.res.Configuration; import android.os.Bundle; import androidx.annotation.Nullable; @@ -31,7 +29,7 @@ public RNTesterActivityDelegate(ReactActivity activity, String mainComponentName @Override protected ReactRootView createRootView() { ReactRootView reactRootView = new ReactRootView(getContext()); - reactRootView.setIsFabric(IS_FABRIC_ENABLED); + reactRootView.setIsFabric(BuildConfig.ENABLE_FABRIC); return reactRootView; } diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java index e9a946ee224f75..e8eec3ae80b7a3 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java @@ -7,39 +7,45 @@ package com.facebook.react.uiapp; -import static com.facebook.react.uiapp.BuildConfig.ENABLE_FABRIC; - import android.app.Application; import android.content.Context; import androidx.annotation.Nullable; -import com.facebook.react.BuildConfig; +import com.facebook.fbreact.specs.SampleTurboModule; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; +import com.facebook.react.TurboReactPackage; +import com.facebook.react.bridge.JSIModule; import com.facebook.react.bridge.JSIModulePackage; import com.facebook.react.bridge.JSIModuleProvider; import com.facebook.react.bridge.JSIModuleSpec; import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.UIManager; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.fabric.ComponentFactory; import com.facebook.react.fabric.CoreComponentsRegistry; import com.facebook.react.fabric.FabricJSIModuleProvider; import com.facebook.react.fabric.ReactNativeConfig; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.shell.MainReactPackage; +import com.facebook.react.turbomodule.core.TurboModuleManager; +import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.react.views.text.ReactFontManager; import com.facebook.soloader.SoLoader; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class RNTesterApplication extends Application implements ReactApplication { - static final boolean IS_FABRIC_ENABLED = ENABLE_FABRIC; - private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override @@ -59,13 +65,53 @@ public boolean getUseDeveloperSupport() { @Override public List getPackages() { - return Arrays.asList(new MainReactPackage()); + return Arrays.asList( + new MainReactPackage(), + new TurboReactPackage() { + public NativeModule getModule( + final String name, final ReactApplicationContext reactContext) { + if (!ReactFeatureFlags.useTurboModules) { + return null; + } + + if (SampleTurboModule.NAME.equals(name)) { + return new SampleTurboModule(reactContext); + } + + return null; + } + + // Note: Specialized annotation processor for @ReactModule isn't configured in OSS + // yet. For now, hardcode this information, though it's not necessary for most + // modules. + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return new ReactModuleInfoProvider() { + public Map getReactModuleInfos() { + final Map moduleInfos = new HashMap<>(); + if (ReactFeatureFlags.useTurboModules) { + moduleInfos.put( + SampleTurboModule.NAME, + new ReactModuleInfo( + SampleTurboModule.NAME, + "SampleTurboModule", + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + true // isTurboModule + )); + } + return moduleInfos; + } + }; + } + }); } @Nullable @Override protected JSIModulePackage getJSIModulePackage() { - if (!IS_FABRIC_ENABLED) { + if (!BuildConfig.ENABLE_FABRIC && !ReactFeatureFlags.useTurboModules) { return null; } @@ -74,45 +120,91 @@ protected JSIModulePackage getJSIModulePackage() { public List getJSIModules( final ReactApplicationContext reactApplicationContext, final JavaScriptContextHolder jsContext) { - List specs = new ArrayList<>(); - specs.add( - new JSIModuleSpec() { - @Override - public JSIModuleType getJSIModuleType() { - return JSIModuleType.UIManager; - } + final List specs = new ArrayList<>(); - @Override - public JSIModuleProvider getJSIModuleProvider() { - ComponentFactory ComponentFactory = new ComponentFactory(); - CoreComponentsRegistry.register(ComponentFactory); - return new FabricJSIModuleProvider( - reactApplicationContext, - ComponentFactory, - // TODO: T71362667 add ReactNativeConfig's support in RNTester - new ReactNativeConfig() { - @Override - public boolean getBool(String s) { - return true; - } - - @Override - public int getInt64(String s) { - return 0; - } - - @Override - public String getString(String s) { - return ""; - } - - @Override - public double getDouble(String s) { - return 0; - } - }); - } - }); + // Install the new native module system. + if (ReactFeatureFlags.useTurboModules) { + specs.add( + new JSIModuleSpec() { + @Override + public JSIModuleType getJSIModuleType() { + return JSIModuleType.TurboModuleManager; + } + + @Override + public JSIModuleProvider getJSIModuleProvider() { + return new JSIModuleProvider() { + @Override + public JSIModule get() { + final ReactInstanceManager reactInstanceManager = + getReactInstanceManager(); + final List packages = reactInstanceManager.getPackages(); + + return new TurboModuleManager( + reactApplicationContext.getCatalystInstance().getRuntimeExecutor(), + new RNTesterTurboModuleManagerDelegate( + reactApplicationContext, packages), + reactApplicationContext + .getCatalystInstance() + .getJSCallInvokerHolder(), + reactApplicationContext + .getCatalystInstance() + .getNativeCallInvokerHolder()); + } + }; + } + }); + } + + // Install the new renderer. + if (BuildConfig.ENABLE_FABRIC) { + specs.add( + new JSIModuleSpec() { + @Override + public JSIModuleType getJSIModuleType() { + return JSIModuleType.UIManager; + } + + @Override + public JSIModuleProvider getJSIModuleProvider() { + final ComponentFactory ComponentFactory = new ComponentFactory(); + CoreComponentsRegistry.register(ComponentFactory); + final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); + + ViewManagerRegistry viewManagerRegistry = + new ViewManagerRegistry( + reactInstanceManager.getOrCreateViewManagers( + reactApplicationContext)); + + return new FabricJSIModuleProvider( + reactApplicationContext, + ComponentFactory, + // TODO: T71362667 add ReactNativeConfig's support in RNTester + new ReactNativeConfig() { + @Override + public boolean getBool(final String s) { + return false; + } + + @Override + public int getInt64(final String s) { + return 0; + } + + @Override + public String getString(final String s) { + return ""; + } + + @Override + public double getDouble(final String s) { + return 0; + } + }, + viewManagerRegistry); + } + }); + } return specs; } @@ -122,6 +214,7 @@ public double getDouble(String s) { @Override public void onCreate() { + ReactFeatureFlags.useTurboModules = BuildConfig.ENABLE_TURBOMODULE; ReactFontManager.getInstance().addCustomFont(this, "Rubik", R.font.rubik); super.onCreate(); SoLoader.init(this, /* native exopackage */ false); @@ -141,24 +234,24 @@ public ReactNativeHost getReactNativeHost() { * @param reactInstanceManager */ private static void initializeFlipper( - Context context, ReactInstanceManager reactInstanceManager) { + final Context context, final ReactInstanceManager reactInstanceManager) { if (BuildConfig.DEBUG) { try { /* We use reflection here to pick up the class that initializes Flipper, since Flipper library is not available in release mode */ - Class aClass = Class.forName("com.facebook.react.uiapp.ReactNativeFlipper"); + final Class aClass = Class.forName("com.facebook.react.uiapp.ReactNativeFlipper"); aClass .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { + } catch (final ClassNotFoundException e) { e.printStackTrace(); - } catch (NoSuchMethodException e) { + } catch (final NoSuchMethodException e) { e.printStackTrace(); - } catch (IllegalAccessException e) { + } catch (final IllegalAccessException e) { e.printStackTrace(); - } catch (InvocationTargetException e) { + } catch (final InvocationTargetException e) { e.printStackTrace(); } } diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterTurboModuleManagerDelegate.java b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterTurboModuleManagerDelegate.java new file mode 100644 index 00000000000000..95c2b6b93fc616 --- /dev/null +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterTurboModuleManagerDelegate.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uiapp; + +import androidx.annotation.VisibleForTesting; +import com.facebook.jni.HybridData; +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.turbomodule.core.ReactPackageTurboModuleManagerDelegate; +import com.facebook.soloader.SoLoader; +import java.util.List; + +/** This class is responsible for creating all the TurboModules for the RNTester app. */ +public class RNTesterTurboModuleManagerDelegate extends ReactPackageTurboModuleManagerDelegate { + private static volatile boolean sIsSoLibraryLoaded; + + protected native HybridData initHybrid(); + + @VisibleForTesting + native boolean canCreateTurboModule(String moduleName); + + public RNTesterTurboModuleManagerDelegate( + ReactApplicationContext context, List packages) { + super(context, packages); + } + + @Override + protected void maybeLoadOtherSoLibraries() { + maybeLoadSoLibraries(); + } + + // Prevents issues with initializer interruptions. + private static synchronized void maybeLoadSoLibraries() { + if (!sIsSoLibraryLoaded) { + SoLoader.loadLibrary("rntester_appmodules"); + sIsSoLibraryLoaded = true; + } + } +} diff --git a/packages/rn-tester/android/app/src/main/jni/Android.mk b/packages/rn-tester/android/app/src/main/jni/Android.mk new file mode 100644 index 00000000000000..e11ca0b62fbb6f --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/Android.mk @@ -0,0 +1,26 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +THIS_DIR := $(call my-dir) + +include $(REACT_ANDROID_DIR)/Android-prebuilt.mk + +# SampleNativeModule +include $(REACT_COMMON_DIR)/react/nativemodule/samples/platform/android/Android.mk + +LOCAL_PATH := $(THIS_DIR) + +include $(CLEAR_VARS) +LOCAL_MODULE := rntester_appmodules +# Note: Build the react-native-codegen output along with other app-specific C++ files. +LOCAL_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni +LOCAL_SHARED_LIBRARIES := libfbjni libglog libfolly_json libyoga libreact_nativemodule_core libturbomodulejsijni libreact_render_components_view libreact_render_core libreact_render_graphics libreact_codegen_rncore +LOCAL_STATIC_LIBRARIES := libsampleturbomodule +LOCAL_CFLAGS := \ + -DLOG_TAG=\"ReactNative\" +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall +include $(BUILD_SHARED_LIBRARY) diff --git a/packages/rn-tester/android/app/src/main/jni/OnLoad.cpp b/packages/rn-tester/android/app/src/main/jni/OnLoad.cpp new file mode 100644 index 00000000000000..f4ed589bcbd37d --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/OnLoad.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include "RNTesterTurboModuleManagerDelegate.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return facebook::jni::initialize(vm, [] { + // TODO: dvacca ramanpreet unify this with the way "ComponentDescriptorFactory" is defined in Fabric + facebook::react::RNTesterTurboModuleManagerDelegate::registerNatives(); + }); +} diff --git a/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp new file mode 100644 index 00000000000000..615cdc5d907265 --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "RNTesterAppModuleProvider.h" + +#include +#include +#include + +namespace facebook { +namespace react { + +std::shared_ptr RNTesterAppModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { + auto module = PackagesRnTesterAndroidAppSpec_ModuleProvider(moduleName, params); + if (module != nullptr) { + return module; + } + + module = SampleTurboModuleSpec_ModuleProvider(moduleName, params); + if (module != nullptr) { + return module; + } + + return rncore_ModuleProvider(moduleName, params); +} + +} // namespace react +} // namespace facebook diff --git a/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.h b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.h new file mode 100644 index 00000000000000..1bdc8477ed5ac9 --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +#include + +namespace facebook { +namespace react { + +std::shared_ptr RNTesterAppModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook diff --git a/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.cpp b/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.cpp new file mode 100644 index 00000000000000..e6ca3d0ecd0ac2 --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "RNTesterTurboModuleManagerDelegate.h" + +#include "RNTesterAppModuleProvider.h" + +namespace facebook { +namespace react { + +jni::local_ref RNTesterTurboModuleManagerDelegate::initHybrid(jni::alias_ref) { + return makeCxxInstance(); +} + +void RNTesterTurboModuleManagerDelegate::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", RNTesterTurboModuleManagerDelegate::initHybrid), + makeNativeMethod("canCreateTurboModule", RNTesterTurboModuleManagerDelegate::canCreateTurboModule), + }); +} + +std::shared_ptr RNTesterTurboModuleManagerDelegate::getTurboModule(const std::string name, const std::shared_ptr jsInvoker) { + // Not implemented yet: provide pure-C++ NativeModules here. + return nullptr; +} + +std::shared_ptr RNTesterTurboModuleManagerDelegate::getTurboModule(const std::string name, const JavaTurboModule::InitParams ¶ms) { + return RNTesterAppModuleProvider(name, params); +} + +bool RNTesterTurboModuleManagerDelegate::canCreateTurboModule(std::string name) { + return getTurboModule(name, nullptr) != nullptr || getTurboModule(name, {.moduleName = name}) != nullptr; +} + +} // namespace react +} // namespace facebook diff --git a/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.h b/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.h new file mode 100644 index 00000000000000..8091b73569c1e1 --- /dev/null +++ b/packages/rn-tester/android/app/src/main/jni/RNTesterTurboModuleManagerDelegate.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +#include +#include + +namespace facebook { +namespace react { + +class RNTesterTurboModuleManagerDelegate : public jni::HybridClass { +public: + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/uiapp/RNTesterTurboModuleManagerDelegate;"; + + static jni::local_ref initHybrid(jni::alias_ref); + + static void registerNatives(); + + std::shared_ptr getTurboModule(const std::string name, const std::shared_ptr jsInvoker) override; + std::shared_ptr getTurboModule(const std::string name, const JavaTurboModule::InitParams ¶ms) override; + + /** + * Test-only method. Allows user to verify whether a TurboModule can be created + * by instances of this class. + */ + bool canCreateTurboModule(std::string name); + +private: + friend HybridBase; + using HybridBase::HybridBase; + +}; + +} // namespace react +} // namespace facebook diff --git a/packages/rn-tester/e2e/__tests__/Alert-test.js b/packages/rn-tester/e2e/__tests__/Alert-test.js new file mode 100644 index 00000000000000..2e9f57906b06a5 --- /dev/null +++ b/packages/rn-tester/e2e/__tests__/Alert-test.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +/* global device, element, by, expect, waitFor */ +const {openExampleWithTitle} = require('../e2e-helpers'); + +describe('Alert', () => { + beforeAll(async () => { + await element(by.id('apis-tab')).tap(); + await element(by.id('explorer_search')).replaceText('Alert'); + await element(by.label('Alerts')).tap(); + }); + + afterAll(async () => { + await element(by.label('Back')).tap(); + }); + + it('AlertWithDefaultButton: should show alert dialog with message and default button', async () => { + const alertMessage = 'An external USB drive has been detected!'; + + await openExampleWithTitle('Alert with default Button'); + await element(by.id('alert-with-default-button')).tap(); + await expect(element(by.text(alertMessage))).toBeVisible(); + await element(by.text('OK')).tap(); + }); + + it('AlertWithThreeButtons: should show alert dialog with three buttons', async () => { + const alertMessage = 'Do you want to save your changes?'; + + await openExampleWithTitle('Alert with three Buttons'); + await element(by.id('alert-with-three-buttons')).tap(); + await expect(element(by.text(alertMessage))).toBeVisible(); + await expect(element(by.text('Cancel'))).toBeVisible(); + await expect(element(by.text('No'))).toBeVisible(); + await expect(element(by.text('Yes'))).toBeVisible(); + await element(by.text('Yes')).tap(); + }); + + it('AlertWithThreeButtons: should successfully call the callback on button press', async () => { + await openExampleWithTitle('Alert with three Buttons'); + await element(by.id('alert-with-three-buttons')).tap(); + await element(by.text('Cancel')).tap(); + await expect(element(by.text('Log: Cancel Pressed!'))).toBeVisible(); + }); +}); diff --git a/packages/rn-tester/e2e/__tests__/Button-test.js b/packages/rn-tester/e2e/__tests__/Button-test.js index 53588b168a525a..1b67f2a5871209 100644 --- a/packages/rn-tester/e2e/__tests__/Button-test.js +++ b/packages/rn-tester/e2e/__tests__/Button-test.js @@ -23,36 +23,75 @@ describe('Button', () => { ); }); - it('Simple button should be tappable', async () => { - await openExampleWithTitle('Simple Button'); - await element(by.id('simple_button')).tap(); - await expect(element(by.text('Simple has been pressed!'))).toBeVisible(); + it('Default Styling button should be tappable', async () => { + await openExampleWithTitle('Default Styling'); + await element(by.id('button_default_styling')).tap(); + await expect( + element(by.text('Your application has been submitted!')), + ).toBeVisible(); await element(by.text('OK')).tap(); }); - it('Adjusted color button should be tappable', async () => { - await openExampleWithTitle('Adjusted color'); - await element(by.id('purple_button')).tap(); - await expect(element(by.text('Purple has been pressed!'))).toBeVisible(); + it('Red color button should be tappable', async () => { + await openExampleWithTitle('Color'); + await element(by.id('cancel_button')).tap(); + await expect( + element(by.text('Your application has been cancelled!')), + ).toBeVisible(); await element(by.text('OK')).tap(); }); it("Two buttons with JustifyContent:'space-between' should be tappable", async () => { - await openExampleWithTitle('Fit to text layout'); - await element(by.id('left_button')).tap(); - await expect(element(by.text('Left has been pressed!'))).toBeVisible(); + await openExampleWithTitle('Two Buttons'); + await element(by.id('two_cancel_button')).tap(); + await expect( + element(by.text('Your application has been cancelled!')), + ).toBeVisible(); + await element(by.text('OK')).tap(); + + await element(by.id('two_submit_button')).tap(); + await expect( + element(by.text('Your application has been submitted!')), + ).toBeVisible(); + await element(by.text('OK')).tap(); + }); + + it("Three buttons with JustifyContent:'space-between' should be tappable", async () => { + await openExampleWithTitle('Three Buttons'); + await element(by.id('three_cancel_button')).tap(); + await expect( + element(by.text('Your application has been cancelled!')), + ).toBeVisible(); await element(by.text('OK')).tap(); - await element(by.id('right_button')).tap(); - await expect(element(by.text('Right has been pressed!'))).toBeVisible(); + await openExampleWithTitle('Three Buttons'); + await element(by.id('three_save_button')).tap(); + await expect( + element(by.text('Your application has been saved!')), + ).toBeVisible(); + await element(by.text('OK')).tap(); + + await element(by.id('three_submit_button')).tap(); + await expect( + element(by.text('Your application has been submitted!')), + ).toBeVisible(); await element(by.text('OK')).tap(); }); it('Disabled button should not interact', async () => { - await openExampleWithTitle('Disabled Button'); + await openExampleWithTitle('Disabled'); await element(by.id('disabled_button')).tap(); await expect( - element(by.text('Disabled has been pressed!')), + element(by.text('Your application has been submitted!')), ).toBeNotVisible(); }); + + it('AccessibilityLabel button should be tappable', async () => { + await openExampleWithTitle('AccessibilityLabel'); + await element(by.id('accessibilityLabel_button')).tap(); + await expect( + element(by.text('Your application has been submitted!')), + ).toBeVisible(); + await element(by.text('OK')).tap(); + }); }); diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index 5d82b93e3e5dd7..70380c39699cfa 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -45,11 +45,12 @@ const APP_STATE_KEY = 'RNTesterAppState.v3'; // TODO: Vendor AsyncStorage or create our own. LogBox.ignoreLogs([/AsyncStorage has been extracted from react-native/]); -const DisplayIfVisible = ({isVisible, children}) => ( - - {children} - -); +const DisplayIfVisible = ({isVisible, children}) => + isVisible ? ( + + {children} + + ) : null; type ExampleListsContainerProps = $ReadOnly<{| theme: RNTesterTheme, @@ -139,13 +140,22 @@ const RNTesterApp = (): React.Node => { // Setup hardware back button press listener React.useEffect(() => { - BackHandler.addEventListener('hardwareBackPress', () => { + const handleHardwareBackPress = () => { if (openExample) { handleBackPress(); return true; } return false; - }); + }; + + BackHandler.addEventListener('hardwareBackPress', handleHardwareBackPress); + + return () => { + BackHandler.removeEventListener( + 'hardwareBackPress', + handleHardwareBackPress, + ); + }; }, [openExample, handleBackPress]); const handleExampleCardPress = React.useCallback( diff --git a/packages/rn-tester/js/components/ExamplePage.js b/packages/rn-tester/js/components/ExamplePage.js index ff9bf7f6f3ac85..23dc5158799d68 100644 --- a/packages/rn-tester/js/components/ExamplePage.js +++ b/packages/rn-tester/js/components/ExamplePage.js @@ -11,7 +11,7 @@ 'use strict'; import * as React from 'react'; -import {StyleSheet, View, Text, Dimensions} from 'react-native'; +import {StyleSheet, View, Text} from 'react-native'; type Props = $ReadOnly<{| children?: React.Node, @@ -22,7 +22,6 @@ type Props = $ReadOnly<{| android?: ?boolean, |}>; -const ScreenWidth = Dimensions.get('window').width; import {RNTesterThemeContext} from './RNTesterTheme'; export default function ExamplePage(props: Props): React.Node { @@ -76,8 +75,8 @@ const styles = StyleSheet.create({ justifyContent: 'flex-end', }, examplesContainer: { - width: ScreenWidth, flexGrow: 1, + flex: 1, }, description: { marginVertical: 8, diff --git a/packages/rn-tester/js/components/ListExampleShared.js b/packages/rn-tester/js/components/ListExampleShared.js index 522d72e3d93318..2312ee69c22f93 100644 --- a/packages/rn-tester/js/components/ListExampleShared.js +++ b/packages/rn-tester/js/components/ListExampleShared.js @@ -225,34 +225,26 @@ function getItemLayout( return {length, offset: (length + separator) * index + header, index}; } -function pressItem(context: Object, key: string) { - const index = Number(key); - const pressed = !context.state.data[index].pressed; - context.setState(state => { - const newData = [...state.data]; - newData[index] = { - ...state.data[index], - pressed, - title: 'Item ' + key + (pressed ? ' (pressed)' : ''), - }; - return {data: newData}; - }); +function pressItem(item: Item): Item { + const title = `Item ${item.key}${!item.pressed ? ' (pressed)' : ''}`; + return {...item, title, pressed: !item.pressed}; } function renderSmallSwitchOption( - context: Object, - key: string, + label: string, + value: boolean, + setValue: boolean => void, ): null | React.Node { if (Platform.isTV) { return null; } return ( - {key}: + {label}: context.setState({[key]: value})} + value={value} + onValueChange={setValue} /> ); diff --git a/packages/rn-tester/js/components/RNTesterBookmark.js b/packages/rn-tester/js/components/RNTesterBookmark.js deleted file mode 100644 index 62142bd8ad7026..00000000000000 --- a/packages/rn-tester/js/components/RNTesterBookmark.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import * as React from 'react'; -import type {RNTesterExample} from '../types/RNTesterTypes'; - -export type RNTesterBookmark = { - Components: {...}, - Api: {...}, - AddApi: (apiName: string, api: RNTesterExample) => mixed, - AddComponent: (componentName: string, component: RNTesterExample) => mixed, - RemoveApi: (apiName: string) => mixed, - RemoveComponent: (componentName: string) => mixed, - checkBookmark: (title: string, key: string) => mixed, -}; - -export const bookmarks: RNTesterBookmark = { - Components: {}, - Api: {}, - AddComponent: () => {}, - RemoveComponent: () => {}, - AddApi: () => {}, - RemoveApi: () => {}, - checkBookmark: () => {}, -}; - -export const RNTesterBookmarkContext: React.Context = React.createContext( - bookmarks, -); diff --git a/packages/rn-tester/js/components/RNTesterButton.js b/packages/rn-tester/js/components/RNTesterButton.js index 25ffd42ceecb7f..d006e17f2b1c6a 100644 --- a/packages/rn-tester/js/components/RNTesterButton.js +++ b/packages/rn-tester/js/components/RNTesterButton.js @@ -14,7 +14,7 @@ const React = require('react'); const {StyleSheet, Text, TouchableHighlight} = require('react-native'); -import type {PressEvent} from '../../../../Libraries/Types/CoreEventTypes'; +import type {PressEvent} from 'react-native/Libraries/Types/CoreEventTypes'; type Props = $ReadOnly<{| children?: React.Node, diff --git a/packages/rn-tester/js/components/RNTesterDocumentationURL.js b/packages/rn-tester/js/components/RNTesterDocumentationURL.js index 8d6d8423591e81..0a8b20823fb860 100644 --- a/packages/rn-tester/js/components/RNTesterDocumentationURL.js +++ b/packages/rn-tester/js/components/RNTesterDocumentationURL.js @@ -5,15 +5,20 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; -import React from 'react'; +import * as React from 'react'; import {Image, StyleSheet, TouchableOpacity} from 'react-native'; import openURLInBrowser from 'react-native/Libraries/Core/Devtools/openURLInBrowser'; -const RNTesterDocumentationURL = ({documentationURL}) => ( +type Props = $ReadOnly<{| + documentationURL: string, +|}>; + +const RNTesterDocumentationURL = ({documentationURL}: Props): React.Node => ( openURLInBrowser(documentationURL)}> @@ -28,7 +33,6 @@ export default RNTesterDocumentationURL; const styles = StyleSheet.create({ container: { - textDecorationLine: 'underline', position: 'absolute', bottom: 0, right: -15, diff --git a/packages/rn-tester/js/components/RNTesterExampleList.js b/packages/rn-tester/js/components/RNTesterExampleList.js index 3b14304272a734..2b32664b7853a5 100644 --- a/packages/rn-tester/js/components/RNTesterExampleList.js +++ b/packages/rn-tester/js/components/RNTesterExampleList.js @@ -39,6 +39,7 @@ const ExampleCard = ({ const onAndroid = !platform || platform === 'android'; return ( = React.memo( page="components_page" sections={sections} filter={filter} + hideFilterPills={true} render={({filteredSections}) => ( ( + + + + handleNavBarPress({screen: 'bookmarks'})}> + + + + + + +); + +const NavbarButton = ({ + testID, + theme, + isActive, + activeImage, + inactiveImage, + label, + handlePress, + iconStyle, +}) => ( + + + + + {label} + + + +); + +const ComponentTab = ({isComponentActive, handleNavBarPress, theme}) => ( + handleNavBarPress({screen: 'components'})} + activeImage={require('./../assets/bottom-nav-components-icon-active.png')} + inactiveImage={require('./../assets/bottom-nav-components-icon-inactive.png')} + isActive={isComponentActive} + theme={theme} + iconStyle={styles.componentIcon} + /> +); + +const APITab = ({isAPIActive, handleNavBarPress, theme}) => ( + handleNavBarPress({screen: 'apis'})} + activeImage={require('./../assets/bottom-nav-apis-icon-active.png')} + inactiveImage={require('./../assets/bottom-nav-apis-icon-inactive.png')} + isActive={isAPIActive} + theme={theme} + iconStyle={styles.apiIcon} + /> +); + type Props = $ReadOnly<{| handleNavBarPress: (data: {screen: string}) => void, screen: string, @@ -33,84 +113,21 @@ const RNTesterNavbar = ({ return ( - handleNavBarPress({screen: 'components'})} - style={[styles.navButton, {backgroundColor: theme.BackgroundColor}]}> - - - - Components - - - - - - - - - handleNavBarPress({screen: 'bookmarks'})}> - - - - - - - - handleNavBarPress({screen: 'apis'})} - style={[styles.navButton, {backgroundColor: theme.BackgroundColor}]}> - - - - APIs - - - + + + ); diff --git a/packages/rn-tester/js/components/RNTesterTheme.js b/packages/rn-tester/js/components/RNTesterTheme.js index 5727f64da5ce80..4a9371296321a8 100644 --- a/packages/rn-tester/js/components/RNTesterTheme.js +++ b/packages/rn-tester/js/components/RNTesterTheme.js @@ -33,7 +33,8 @@ export type RNTesterTheme = { SeparatorColor: ColorValue, OpaqueSeparatorColor: ColorValue, LinkColor: ColorValue, - SystemPurpleColor: ColorValue, + SystemRedColor: ColorValue, + SystemGreenColor: ColorValue, ToolbarColor: ColorValue, BackgroundColor: ColorValue, BorderColor: ColorValue, @@ -59,7 +60,8 @@ export const RNTesterLightTheme = { SeparatorColor: '#3c3c4349', OpaqueSeparatorColor: '#c6c6c8ff', LinkColor: '#007affff', - SystemPurpleColor: '#af52deff', + SystemRedColor: '#ff3b30ff', + SystemGreenColor: '#34c759ff', ToolbarColor: '#e9eaedff', BackgroundColor: '#f3f8ffff', BorderColor: '#005dffff', @@ -84,7 +86,8 @@ export const RNTesterDarkTheme = { SeparatorColor: '#54545899', OpaqueSeparatorColor: '#38383aff', LinkColor: '#0984ffff', - SystemPurpleColor: '#bf5af2ff', + SystemRedColor: '#ff375fff', + SystemGreenColor: '#30d158ff', ToolbarColor: '#3c3c43ff', BackgroundColor: '#0c0700ff', BorderColor: '#005dffff', diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index f9e8e6c12e5089..22b2c0710eb594 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -20,6 +20,7 @@ const { TouchableWithoutFeedback, Alert, StyleSheet, + Platform, } = require('react-native'); const RNTesterBlock = require('../../components/RNTesterBlock'); @@ -27,6 +28,7 @@ const RNTesterBlock = require('../../components/RNTesterBlock'); const checkImageSource = require('./check.png'); const uncheckImageSource = require('./uncheck.png'); const mixedCheckboxImageSource = require('./mixed.png'); +const {createRef} = require('react'); const styles = StyleSheet.create({ image: { @@ -692,58 +694,152 @@ class FakeSliderExample extends React.Component { } } -class ScreenReaderStatusExample extends React.Component<{}> { +class AnnounceForAccessibility extends React.Component<{}> { + _handleOnPress = () => + AccessibilityInfo.announceForAccessibility('Announcement Test'); + + render() { + return ( + + - - Transparent - {this.renderSwitch()} - + {this.renderSwitch()} {this.renderPickers()} - + ); } renderPickers() { @@ -219,17 +257,39 @@ class ModalExample extends React.Component<{...}, $FlowFixMeState> { - this.setState({selectedSupportedOrientation: i}) + this.setState({selectedSupportedOrientation: i.toString()}) } itemStyle={styles.pickerItem}> - - - - - - + + + + + + + + + Actions + {Platform.OS === 'ios' ? ( + this.setState({action})} + itemStyle={styles.pickerItem}> + + + + + ) : ( + this.setState({action})} + itemStyle={styles.pickerItem}> + + + + )} + ); } @@ -282,4 +342,8 @@ const styles = StyleSheet.create({ pickerItem: { fontSize: 16, }, + ScrollView: { + paddingTop: 10, + paddingBottom: 100, + }, }); diff --git a/packages/rn-tester/js/examples/MultiColumn/MultiColumnExample.js b/packages/rn-tester/js/examples/MultiColumn/MultiColumnExample.js index ca822b22c07d01..6ca4431bb43fe5 100644 --- a/packages/rn-tester/js/examples/MultiColumn/MultiColumnExample.js +++ b/packages/rn-tester/js/examples/MultiColumn/MultiColumnExample.js @@ -12,7 +12,7 @@ const RNTesterPage = require('../../components/RNTesterPage'); const React = require('react'); -const infoLog = require('../../../../../Libraries/Utilities/infoLog'); +const infoLog = require('react-native/Libraries/Utilities/infoLog'); const { FooterComponent, @@ -56,6 +56,10 @@ class MultiColumnExample extends React.PureComponent< _onChangeNumColumns = numColumns => { this.setState(() => ({numColumns: Number(numColumns)})); }; + + _setBooleanValue: string => boolean => void = key => value => + this.setState({[key]: value}); + render(): React.Node { const filterRegex = new RegExp(String(this.state.filterText), 'i'); const filter = item => @@ -81,9 +85,21 @@ class MultiColumnExample extends React.PureComponent< /> - {renderSmallSwitchOption(this, 'virtualized')} - {renderSmallSwitchOption(this, 'fixedHeight')} - {renderSmallSwitchOption(this, 'logViewable')} + {renderSmallSwitchOption( + 'Virtualized', + this.state.virtualized, + this._setBooleanValue('virtualized'), + )} + {renderSmallSwitchOption( + 'Fixed Height', + this.state.fixedHeight, + this._setBooleanValue('fixedHeight'), + )} + {renderSmallSwitchOption( + 'Log Viewable', + this.state.logViewable, + this._setBooleanValue('logViewable'), + )} @@ -151,8 +167,18 @@ class MultiColumnExample extends React.PureComponent< ); } }; + _pressItem = (key: string) => { - pressItem(this, key); + const index = Number(key); + const itemState = pressItem(this.state.data[index]); + this.setState(state => ({ + ...state, + data: [ + ...state.data.slice(0, index), + itemState, + ...state.data.slice(index + 1), + ], + })); }; } diff --git a/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js b/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js index 7afe58e886bf4c..81851e1e2f7ff2 100644 --- a/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js +++ b/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js @@ -195,13 +195,13 @@ class InternalSettings extends React.Component< initialValue={false} label="Track JS Stalls" onEnable={() => { - require('../../../../../Libraries/Interaction/JSEventLoopWatchdog').install( + require('react-native/Libraries/Interaction/JSEventLoopWatchdog').install( { thresholdMS: 25, }, ); this.setState({busyTime: ''}); - require('../../../../../Libraries/Interaction/JSEventLoopWatchdog').addHandler( + require('react-native/Libraries/Interaction/JSEventLoopWatchdog').addHandler( { onStall: ({busyTime}) => this.setState(state => ({ diff --git a/packages/rn-tester/js/examples/NewAppScreen/NewAppScreenExample.js b/packages/rn-tester/js/examples/NewAppScreen/NewAppScreenExample.js index 277cdc9a5d8945..5dad9e2fc52eaa 100644 --- a/packages/rn-tester/js/examples/NewAppScreen/NewAppScreenExample.js +++ b/packages/rn-tester/js/examples/NewAppScreen/NewAppScreenExample.js @@ -18,7 +18,7 @@ const { Colors, DebugInstructions, ReloadInstructions, -} = require('../../../../../Libraries/NewAppScreen'); +} = require('react-native/Libraries/NewAppScreen'); exports.title = 'New App Screen'; exports.description = 'Displays the content of the new app screen'; diff --git a/packages/rn-tester/js/examples/OrientationChange/OrientationChangeExample.js b/packages/rn-tester/js/examples/OrientationChange/OrientationChangeExample.js index 1cf3d45e20f3d6..c8b2df92d3ed80 100644 --- a/packages/rn-tester/js/examples/OrientationChange/OrientationChangeExample.js +++ b/packages/rn-tester/js/examples/OrientationChange/OrientationChangeExample.js @@ -14,7 +14,7 @@ const React = require('react'); const {DeviceEventEmitter, Text, View} = require('react-native'); -import {type EventSubscription} from '../../../../../Libraries/vendor/emitter/EventEmitter'; +import {type EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; class OrientationChangeExample extends React.Component<{...}, $FlowFixMeState> { _orientationSubscription: EventSubscription; diff --git a/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js b/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js index 33dcf037b430bc..f45ec746a84e81 100644 --- a/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js +++ b/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow weak + * @flow */ 'use strict'; @@ -17,8 +17,8 @@ const RNTesterPage = require('../../components/RNTesterPage'); import type { PanResponderInstance, GestureState, -} from '../../../../../Libraries/Interaction/PanResponder'; -import type {PressEvent} from '../../../../../Libraries/Types/CoreEventTypes'; +} from 'react-native/Libraries/Interaction/PanResponder'; +import type {PressEvent} from 'react-native/Libraries/Types/CoreEventTypes'; type CircleStyles = { backgroundColor?: string, @@ -110,6 +110,7 @@ class PanResponderExample extends React.Component { }} style={[ styles.circle, + // $FlowFixMe[incompatible-type] { translateX: this.state.left, translateY: this.state.top, diff --git a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js index cda369e62e1e76..e542f70ff3b0db 100644 --- a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js +++ b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js @@ -12,7 +12,7 @@ const React = require('react'); const ReactNative = require('react-native'); -import Platform from '../../../../../Libraries/Utilities/Platform'; +import Platform from 'react-native/Libraries/Utilities/Platform'; const {DynamicColorIOS, PlatformColor, StyleSheet, Text, View} = ReactNative; function PlatformColorsExample() { @@ -110,6 +110,8 @@ function PlatformColorsExample() { {label: 'systemGray4', color: PlatformColor('systemGray4')}, {label: 'systemGray5', color: PlatformColor('systemGray5')}, {label: 'systemGray6', color: PlatformColor('systemGray6')}, + // Transparent Color + {label: 'clear', color: PlatformColor('clear')}, ]; } else if (Platform.OS === 'android') { colors = [ diff --git a/packages/rn-tester/js/examples/RTL/RTLExample.js b/packages/rn-tester/js/examples/RTL/RTLExample.js index d6b1c1827edbc3..d93995a0388b21 100644 --- a/packages/rn-tester/js/examples/RTL/RTLExample.js +++ b/packages/rn-tester/js/examples/RTL/RTLExample.js @@ -21,6 +21,7 @@ const { Platform, StyleSheet, Text, + TextInput, TouchableWithoutFeedback, Switch, View, @@ -86,6 +87,18 @@ const TextAlignmentExample = withRTLState(({isRTL, setRTL, ...props}) => { ); }); +const TextInputExample = withRTLState(({isRTL, setRTL, ...props}) => { + return ( + + + + LRT or RTL TextInput. + + + + ); +}); + const IconsExample = withRTLState(({isRTL, setRTL}) => { return ( @@ -682,6 +695,13 @@ exports.examples = [ ); }, }, + { + title: "Using textAlign: 'right' for TextInput", + description: ('Flip TextInput direction to RTL': string), + render: function(): React.Element { + return ; + }, + }, { title: 'Working With Icons', render: function(): React.Element { diff --git a/packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js b/packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js index 76e9147080e810..3c85eb457bc203 100644 --- a/packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js +++ b/packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js @@ -15,15 +15,20 @@ const React = require('react'); const { Platform, ScrollView, + Picker, StyleSheet, Text, TouchableOpacity, View, + TextInput, + RefreshControl, } = require('react-native'); const nullthrows = require('nullthrows'); -import type {ViewStyleProp} from '../../../../../Libraries/StyleSheet/StyleSheet'; +import {useState, useCallback} from 'react'; +import type {RNTesterExampleModuleItem} from '../../types/RNTesterTypes'; +import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet'; exports.displayName = 'ScrollViewExample'; exports.title = 'ScrollView'; @@ -31,8 +36,9 @@ exports.documentationURL = 'https://reactnative.dev/docs/scrollview'; exports.category = 'Basic'; exports.description = 'Component that enables scrolling through child components'; -exports.examples = [ +exports.examples = ([ { + name: 'scrollTo', title: '\n', description: 'To make content scrollable, wrap it within a component', @@ -49,7 +55,8 @@ exports.examples = [ console.log('onScroll!'); }} scrollEventThrottle={200} - style={styles.scrollView}> + style={styles.scrollView} + testID="scroll_vertical"> {ITEMS.map(createItemRow)}