diff --git a/.circleci/config.yml b/.circleci/config.yml index a5892859d8..97b47fa2cc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -329,7 +329,7 @@ jobs: - run: name: "Run Tests: JavaScript Tests" command: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2 - # [macOS] Github#949 Disable this failing test + # TODO(macOS GH#949): Disable this failing test # - run_e2e: # platform: js @@ -388,8 +388,6 @@ jobs: steps: - brew_install: package: watchman - - brew_install: - package: node@16 - run: name: "Brew: Tap wix/brew" command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null @@ -576,41 +574,39 @@ jobs: steps: - checkout - run_yarn + - attach_workspace: + at: . - run: - name: Setup the Android Template + name: Create Android template project command: | + REPO_ROOT=$(pwd) + PACKAGE=$(cat build/react-native-package-version) + PATH_TO_PACKAGE="$REPO_ROOT/build/$PACKAGE" cd template - # We replace the "react-native" dependency version with file:.. so we use it from source. - sed -i 's/\"react-native\"\:.*/\"react-native\"\: \"file\:\.\.\"/g' package.json + npm add $PATH_TO_PACKAGE npm install - # react-native-community/cli is needed as the Android template is referencing a .gradle file inside it. - npm i @react-native-community/cli - - - run: - name: Bundle the latest version of ReactAndroid - command: ./gradlew :ReactAndroid:publishReleasePublicationToNpmRepository - run: name: Build the template application command: cd template/android/ && ./gradlew assembleDebug # ------------------------- - # JOBS: Test Docker + # JOBS: Test Android RNTester # ------------------------- - test_docker: - machine: true + test_android_rntester: + executor: reactnativeandroid steps: - checkout + - run_yarn + - run: - name: Build Docker container for Android RNTester App - command: | - source ~/.bashrc - nvm i node - npm i -g yarn - echo y | npx envinfo@latest - yarn run docker-setup-android - yarn run docker-build-android + name: Generate artifacts for Maven + command: ./gradlew :ReactAndroid:installArchives + + - run: + name: Assemble RNTester + command: ./gradlew :packages:rn-tester:android:app:assembleDebug # ------------------------- # JOBS: Test iOS Template @@ -645,6 +641,40 @@ jobs: -scheme $PROJECT_NAME \ -sdk iphonesimulator + # ------------------------- + # JOBS: Test iOS RNTester + # ------------------------- + test_ios_rntester: + executor: reactnativeios + parameters: + use_hermes: + type: boolean + default: false + steps: + - checkout + - run_yarn + + - when: + condition: << parameters.use_hermes >> + steps: + - run: + name: Set USE_HERMES=1 + command: echo "export USE_HERMES=1" >> $BASH_ENV + + - run: + name: Install CocoaPods dependencies + command: | + rm -rf packages/rn-tester/Pods + cd packages/rn-tester && bundle exec pod install + + - run: + name: Build RNTester + command: | + xcodebuild build \ + -workspace packages/rn-tester/RNTesterPods.xcworkspace \ + -scheme RNTester \ + -sdk iphonesimulator + # ------------------------- # JOBS: Windows # ------------------------- @@ -890,11 +920,6 @@ workflows: - build_npm_package: # Build a release package on every untagged commit, but do not publish to npm. publish_npm_args: --dry-run - filters: - branches: - only: - - main - - /^pull\/.*$/ - test_js: run_disabled_tests: false filters: @@ -904,19 +929,34 @@ workflows: run_disabled_tests: false filters: branches: - # [macOS] disable this test which is redundant to Azure Devops test and it requires a CCI plan with resource-class:large. - ignore: /.*/ + ignore: gh-pages - test_android_template: + requires: + - build_npm_package filters: branches: - # [macOS] disable this test which is redundant to Azure Devops test and it requires a CCI plan with resource-class:large. - ignore: /.*/ + ignore: gh-pages + - test_android_rntester: + filters: + branches: + ignore: gh-pages - test_ios_template: requires: - build_npm_package filters: branches: ignore: gh-pages + - test_ios_rntester: + name: test_ios_rntester_hermes + use_hermes: true + filters: + branches: + ignore: gh-pages + - test_ios_rntester: + name: test_ios_rntester_jsc + filters: + branches: + ignore: gh-pages - test_ios: name: test_ios_unit_jsc run_unit_tests: true @@ -941,25 +981,16 @@ workflows: # use_hermes: true # use_frameworks: true # run_unit_tests: true - # [macOS] Github#949 Disable this failing test - # - test_js: - # name: test_js_prev_lts - # executor: nodeprevlts - # filters: - # branches: - # ignore: gh-pages - - test_docker: + - test_js: + name: test_js_prev_lts + executor: nodeprevlts filters: branches: - # [macOS] disable this test which is redundant to Azure Devops test and in the fork it fails because of Microsoft's V8 upgrade to Android - ignore: /.*/ + ignore: gh-pages - test_windows: filters: branches: - # [macOS disable this test which requires a CCI plan. - # ignore: gh-pages - ignore: /.*/ - # macOS] + ignore: gh-pages run_disabled_tests: false # This workflow should only be triggered by release script @@ -1009,11 +1040,10 @@ workflows: # Gather coverage - js_coverage: - # [macOS disable this test, it fails in the fork due to not being set up for coveralls filters: branches: - ignore: /.*/ - # macOS] + ignore: gh-pages + nightly: unless: << pipeline.parameters.run_package_release_workflow_only >> triggers: @@ -1021,13 +1051,13 @@ workflows: cron: "0 20 * * *" filters: branches: - # [macOS disable this release. We never want to release anything from this fork via CCI. + # [TODO(macOS GH#774): disable this release. We never want to release anything from this fork via CCI. ignore: /.*/ # only: # - main - # macOS] + # ]TODO(macOS GH#774) jobs: - nightly_job - build_npm_package: - publish_npm_args: --nightly + publish_npm_args: --nightly \ No newline at end of file diff --git a/.flowconfig b/.flowconfig index 34fda34c1f..4f096efa2e 100644 --- a/.flowconfig +++ b/.flowconfig @@ -78,4 +78,4 @@ untyped-import untyped-type-import [version] -^0.170.0 +^0.171.0 diff --git a/.flowconfig.android b/.flowconfig.android index 4156e60b64..6e27866c96 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -81,4 +81,4 @@ untyped-import untyped-type-import [version] -^0.170.0 +^0.171.0 diff --git a/.flowconfig.macos b/.flowconfig.macos index bb1300f5fb..c0ed79dd08 100644 --- a/.flowconfig.macos +++ b/.flowconfig.macos @@ -1,6 +1,5 @@ [ignore] -; [macOS] -; We fork some components by platform +; We fork some components by platform [macOS] .*/*[.]ios.js .*/*[.]android.js @@ -13,7 +12,7 @@ ; Ignore "BUCK" generated dirs /\.buckd/ -; [macOS Ignore metro.config.js +; [macOS] Ignore metro.config.js /metro.config.js ; Flow doesn't support platforms @@ -39,8 +38,11 @@ emoji=true exact_by_default=true +format.bracket_spacing=false + module.file_ext=.js module.file_ext=.json +; [macOS] module.file_ext=.macos.js munge_underscores=true @@ -55,19 +57,16 @@ suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_type=$FlowFixMeEmpty -experimental.abstract_locations=true - [lints] sketchy-null-number=warn sketchy-null-mixed=warn sketchy-number=warn untyped-type-import=warn nonstrict-import=warn -deprecated-type=warn +deprecated-type=error unsafe-getters-setters=warn unnecessary-invariant=warn signature-verification-failure=warn -deprecated-utility=error [strict] deprecated-type @@ -79,4 +78,4 @@ untyped-import untyped-type-import [version] -^0.170.0 +^0.171.0 diff --git a/BUCK b/BUCK index b9d639adff..cdbf57b399 100644 --- a/BUCK +++ b/BUCK @@ -434,6 +434,7 @@ rn_xplat_cxx_library2( "//fbobjc/Libraries/FBQPLMetadataProviders/...", "//fbobjc/Libraries/FBReactKit/...", "//fbobjc/Libraries/FBiOSSecurityUtils/...", + "//fbobjc/Libraries/RCTPrerendering/...", "//fbobjc/VendorLib/react-native-maps:react-native-maps", "//xplat/js:", "//xplat/js/react-native-github/React/...", @@ -723,7 +724,6 @@ rn_library( "//xplat/js:node_modules__abort_19controller", "//xplat/js:node_modules__anser", "//xplat/js:node_modules__base64_19js", - "//xplat/js:node_modules__deprecated_19react_19native_19prop_19types", "//xplat/js:node_modules__event_19target_19shim", "//xplat/js:node_modules__invariant", "//xplat/js:node_modules__nullthrows", diff --git a/Libraries/Animated/NativeAnimatedHelper.js b/Libraries/Animated/NativeAnimatedHelper.js index a8671013cb..3ceb741dae 100644 --- a/Libraries/Animated/NativeAnimatedHelper.js +++ b/Libraries/Animated/NativeAnimatedHelper.js @@ -90,6 +90,18 @@ const API = { NativeAnimatedModule.createAnimatedNode(tag, config), ); }, + updateAnimatedNodeConfig: function ( + tag: number, + config: AnimatedNodeConfig, + ): void { + invariant(NativeAnimatedModule, 'Native animated module is not available'); + if (typeof NativeAnimatedModule.updateAnimatedNodeConfig === 'function') { + API.queueOperation(() => + // $FlowIgnore[not-a-function] - checked above + NativeAnimatedModule.updateAnimatedNodeConfig(tag, config), + ); + } + }, startListeningToAnimatedNodeValue: function (tag: number) { invariant(NativeAnimatedModule, 'Native animated module is not available'); API.queueOperation(() => diff --git a/Libraries/Animated/NativeAnimatedModule.js b/Libraries/Animated/NativeAnimatedModule.js index 167ca596d8..39ffb002f8 100644 --- a/Libraries/Animated/NativeAnimatedModule.js +++ b/Libraries/Animated/NativeAnimatedModule.js @@ -29,6 +29,7 @@ export interface Spec extends TurboModule { +startOperationBatch: () => void; +finishOperationBatch: () => void; +createAnimatedNode: (tag: number, config: AnimatedNodeConfig) => void; + +updateAnimatedNodeConfig?: (tag: number, config: AnimatedNodeConfig) => void; +getValue: (tag: number, saveValueCallback: SaveValueCallback) => void; +startListeningToAnimatedNodeValue: (tag: number) => void; +stopListeningToAnimatedNodeValue: (tag: number) => void; diff --git a/Libraries/Animated/NativeAnimatedTurboModule.js b/Libraries/Animated/NativeAnimatedTurboModule.js index b67fe15013..7c0fbe8f8e 100644 --- a/Libraries/Animated/NativeAnimatedTurboModule.js +++ b/Libraries/Animated/NativeAnimatedTurboModule.js @@ -29,6 +29,7 @@ export interface Spec extends TurboModule { +startOperationBatch: () => void; +finishOperationBatch: () => void; +createAnimatedNode: (tag: number, config: AnimatedNodeConfig) => void; + +updateAnimatedNodeConfig?: (tag: number, config: AnimatedNodeConfig) => void; +getValue: (tag: number, saveValueCallback: SaveValueCallback) => void; +startListeningToAnimatedNodeValue: (tag: number) => void; +stopListeningToAnimatedNodeValue: (tag: number) => void; diff --git a/Libraries/Animated/nodes/AnimatedColor.js b/Libraries/Animated/nodes/AnimatedColor.js index 4a5cdc5d74..603b329fa7 100644 --- a/Libraries/Animated/nodes/AnimatedColor.js +++ b/Libraries/Animated/nodes/AnimatedColor.js @@ -14,6 +14,7 @@ import AnimatedValue from './AnimatedValue'; import AnimatedWithChildren from './AnimatedWithChildren'; import normalizeColor from '../../StyleSheet/normalizeColor'; import {processColorObject} from '../../StyleSheet/PlatformColorValueTypes'; +import NativeAnimatedHelper from '../NativeAnimatedHelper'; import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; @@ -91,6 +92,7 @@ export default class AnimatedColor extends AnimatedWithChildren { g: AnimatedValue; b: AnimatedValue; a: AnimatedValue; + nativeColor: Object; _listeners: { [key: string]: { r: string, @@ -105,8 +107,16 @@ export default class AnimatedColor extends AnimatedWithChildren { constructor(valueIn?: ?(RgbaValue | RgbaAnimatedValue | ColorValue)) { super(); let value: RgbaValue | RgbaAnimatedValue | ColorValue = - valueIn || defaultColor; + valueIn ?? defaultColor; + this.setValue(value); + this._listeners = {}; + } + /** + * Directly set the value. This will stop any animations running on the value + * and update all the bound properties. + */ + setValue(value: RgbaValue | RgbaAnimatedValue | ColorValue): void { if (isRgbaAnimatedValue(value)) { // $FlowIgnore[incompatible-cast] - Type is verified above const rgbaAnimatedValue: RgbaAnimatedValue = (value: RgbaAnimatedValue); @@ -118,29 +128,60 @@ export default class AnimatedColor extends AnimatedWithChildren { // Handle potential parsable string color or platform color object if (!isRgbaValue(value)) { // $FlowIgnore[incompatible-cast] - Type is verified via conditionals - value = processColor((value: ColorValue)) || {r: 0, g: 0, b: 0, a: 1.0}; - // TODO: support platform color + value = processColor((value: ColorValue)) ?? defaultColor; } - // $FlowIgnore[incompatible-cast] - Type is verified via conditionals - const rgbaValue: RgbaValue = (value: RgbaValue); - this.r = new AnimatedValue(rgbaValue.r); - this.g = new AnimatedValue(rgbaValue.g); - this.b = new AnimatedValue(rgbaValue.b); - this.a = new AnimatedValue(rgbaValue.a); - } - this._listeners = {}; - } + if (!isRgbaValue(value)) { + // We are using a platform color + this.nativeColor = value; + value = defaultColor; + } - /** - * Directly set the value. This will stop any animations running on the value - * and update all the bound properties. - */ - setValue(value: {r: number, g: number, b: number, a: number, ...}): void { - this.r.setValue(value.r); - this.g.setValue(value.g); - this.b.setValue(value.b); - this.a.setValue(value.a); + if (isRgbaValue(value)) { + // $FlowIgnore[incompatible-cast] - Type is verified via conditionals + const rgbaValue: RgbaValue = (value: RgbaValue); + + if (this.r) { + this.r.setValue(rgbaValue.r); + } else { + this.r = new AnimatedValue(rgbaValue.r); + } + + if (this.g) { + this.g.setValue(rgbaValue.g); + } else { + this.g = new AnimatedValue(rgbaValue.g); + } + + if (this.b) { + this.b.setValue(rgbaValue.b); + } else { + this.b = new AnimatedValue(rgbaValue.b); + } + + if (this.a) { + this.a.setValue(rgbaValue.a); + } else { + this.a = new AnimatedValue(rgbaValue.a); + } + } + + if (this.nativeColor) { + if (!this.__isNative) { + this.__makeNative(); + } + + const nativeTag = this.__getNativeTag(); + NativeAnimatedHelper.API.setWaitingForIdentifier(nativeTag.toString()); + NativeAnimatedHelper.API.updateAnimatedNodeConfig( + nativeTag, + this.__getNativeConfig(), + ); + NativeAnimatedHelper.API.unsetWaitingForIdentifier( + nativeTag.toString(), + ); + } + } } /** @@ -148,7 +189,7 @@ export default class AnimatedColor extends AnimatedWithChildren { * via `setValue`, an animation, or `Animated.event`. Useful for compensating * things like the start of a pan gesture. */ - setOffset(offset: {r: number, g: number, b: number, a: number, ...}): void { + setOffset(offset: RgbaValue): void { this.r.setOffset(offset.r); this.g.setOffset(offset.g); this.b.setOffset(offset.b); @@ -280,6 +321,7 @@ export default class AnimatedColor extends AnimatedWithChildren { g: this.g.__getNativeTag(), b: this.b.__getNativeTag(), a: this.a.__getNativeTag(), + nativeColor: this.nativeColor, }; } } diff --git a/Libraries/Animated/nodes/AnimatedInterpolation.js b/Libraries/Animated/nodes/AnimatedInterpolation.js index 5ebea80ba1..d6f5deed04 100644 --- a/Libraries/Animated/nodes/AnimatedInterpolation.js +++ b/Libraries/Animated/nodes/AnimatedInterpolation.js @@ -23,14 +23,14 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; type ExtrapolateType = 'extend' | 'identity' | 'clamp'; -export type InterpolationConfigType = { +export type InterpolationConfigType = $ReadOnly<{ inputRange: $ReadOnlyArray, outputRange: $ReadOnlyArray | $ReadOnlyArray, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, -}; +}>; const linear = (t: number) => t; diff --git a/Libraries/Animated/nodes/AnimatedNode.js b/Libraries/Animated/nodes/AnimatedNode.js index 30e802cc91..b4a649ff30 100644 --- a/Libraries/Animated/nodes/AnimatedNode.js +++ b/Libraries/Animated/nodes/AnimatedNode.js @@ -130,12 +130,12 @@ class AnimatedNode { if (data.tag !== this.__getNativeTag()) { return; } - this._onAnimatedValueUpdateReceived(data.value); + this.__onAnimatedValueUpdateReceived(data.value); }, ); } - _onAnimatedValueUpdateReceived(value: number) { + __onAnimatedValueUpdateReceived(value: number) { this.__callListeners(value); } diff --git a/Libraries/Animated/nodes/AnimatedValue.js b/Libraries/Animated/nodes/AnimatedValue.js index c0e8f7341c..c829d3e595 100644 --- a/Libraries/Animated/nodes/AnimatedValue.js +++ b/Libraries/Animated/nodes/AnimatedValue.js @@ -211,7 +211,7 @@ class AnimatedValue extends AnimatedWithChildren { } } - _onAnimatedValueUpdateReceived(value: number): void { + __onAnimatedValueUpdateReceived(value: number): void { this._updateValue(value, false /*flush*/); } diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index c3cb5e1d34..973bf0eb91 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -370,20 +370,6 @@ type IOSProps = $ReadOnly<{| | 'never' | 'always' ), - /** - * Experimental: specifies how much to adjust the content view by when using - * the keyboard to scroll. This value adjusts the content's horizontal offset. - * - * @platform macos - */ - horizontalLineScroll?: number, // [macOS] - /** - * Experimental: specifies how much to adjust the content view by when using - * the keyboard to scroll. This value adjusts the content's vertical offset. - * - * @platform macos - */ - verticalLineScroll?: number, // [macOS] |}>; type AndroidProps = $ReadOnly<{| @@ -500,7 +486,7 @@ export type Props = $ReadOnly<{| */ invertStickyHeaders?: ?boolean, /** - * Reverses the direction of scroll. Uses native inversion on macOS and scale transforms of -1 elsewhere + * Reverses the direction of scroll. Uses native inversion on macOS and scale transforms of -1 elsewhere // [macOS] */ inverted?: ?boolean, // [macOS] /** diff --git a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 49fa3bfc3c..879d3aa17f 100644 --- a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -11,6 +11,7 @@ import type {ScrollViewNativeProps as Props} from './ScrollViewNativeComponentType'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import {ConditionallyIgnoredEventHandlers} from '../../NativeComponent/ViewConfigIgnore'; import Platform from '../../Utilities/Platform'; const RCTScrollViewViewConfig = @@ -138,6 +139,18 @@ const RCTScrollViewViewConfig = snapToOffsets: true, snapToStart: true, zoomScale: true, + ...ConditionallyIgnoredEventHandlers({ + onScrollBeginDrag: true, + onMomentumScrollEnd: true, + onScrollEndDrag: true, + onMomentumScrollBegin: true, + onScrollToTop: true, + onScroll: true, + // [macOS + onInvertedDidChange: true, + onPreferredScrollerStyleDidChange: true, + // macOS] + }), }, }; diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js index 2feda14cde..ebd8f6d52b 100644 --- a/Libraries/Components/Slider/Slider.js +++ b/Libraries/Components/Slider/Slider.js @@ -235,7 +235,6 @@ const Slider = ( } : null; - const onChangeEvent = onValueChangeEvent; const onSlidingCompleteEvent = onSlidingComplete ? (event: Event) => { onSlidingComplete(event.nativeEvent.value); @@ -257,7 +256,6 @@ const Slider = ( disabled={disabled} maximumValue={maximumValue} minimumValue={minimumValue} - onChange={onChangeEvent} onResponderTerminationRequest={() => false} onSlidingComplete={onSlidingCompleteEvent} onStartShouldSetResponder={() => true} diff --git a/Libraries/Components/Slider/SliderNativeComponent.js b/Libraries/Components/Slider/SliderNativeComponent.js index 739bce7b2a..9846c1a9de 100644 --- a/Libraries/Components/Slider/SliderNativeComponent.js +++ b/Libraries/Components/Slider/SliderNativeComponent.js @@ -47,7 +47,6 @@ type NativeProps = $ReadOnly<{| value?: WithDefault, // Events - onChange?: ?BubblingEventHandler, onValueChange?: ?BubblingEventHandler, onSlidingComplete?: ?DirectEventHandler, |}>; diff --git a/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/Libraries/Components/TextInput/RCTTextInputViewConfig.js index f5802d4502..4acd36ae8f 100644 --- a/Libraries/Components/TextInput/RCTTextInputViewConfig.js +++ b/Libraries/Components/TextInput/RCTTextInputViewConfig.js @@ -9,6 +9,7 @@ */ import type {PartialViewConfig} from '../../Renderer/shims/ReactNativeTypes'; +import {ConditionallyIgnoredEventHandlers} from '../../NativeComponent/ViewConfigIgnore'; type PartialViewConfigWithoutName = $Rest< PartialViewConfig, @@ -130,7 +131,6 @@ const RCTTextInputViewConfig = { blurOnSubmit: true, mostRecentEventCount: true, scrollEnabled: true, - hideVerticalScrollIndicator: true, selectionColor: {process: require('../../StyleSheet/processColor')}, contextMenuHidden: true, secureTextEntry: true, @@ -142,13 +142,35 @@ const RCTTextInputViewConfig = { autoCapitalize: true, keyboardAppearance: true, passwordRules: true, - grammarCheck: true, // [macOS] spellCheck: true, selectTextOnFocus: true, text: true, clearTextOnFocus: true, showSoftInputOnFocus: true, autoFocus: true, + // [macOS + clearTextOnSubmit: true, + grammarCheck: true, + hideVerticalScrollIndicator: true, + pastedTypes: true, + submitKeyEvents: true, + tooltip: true, + // macOS] + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + onSelectionChange: true, + onContentSizeChange: true, + onScroll: true, + onChangeSync: true, + onKeyPressSync: true, + onTextInput: true, + // [macOS + onPaste: true, + onAutoCorrectChange: true, + onSpellCheckChange: true, + onGrammarCheckChange: true, + // macOS] + }), }, }; diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index c3abb171be..11f00e9098 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -327,21 +327,6 @@ type IOSProps = $ReadOnly<{| */ scrollEnabled?: ?boolean, - // [macOS - /** - * If `true`, hide vertical scrollbar on the underlying multiline scrollview - * The default value is `false`. - * @platform macos - */ - hideVerticalScrollIndicator?: ?boolean, - - /** - * If `false`, disables grammar-check. - * @platform macos - */ - grammarCheck?: ?boolean, - // macOS] - /** * If `false`, disables spell-check style (i.e. red underlines). * The default value is inherited from `autoCorrect`. @@ -370,10 +355,26 @@ export type SubmitKeyEvent = $ReadOnly<{| type MacOSProps = $ReadOnly<{| /** * If `true`, clears the text field synchronously before `onSubmitEditing` is emitted. + * * @platform macos */ clearTextOnSubmit?: ?boolean, + /** + * If `false`, disables grammar-check. + * + * @platform macos + */ + grammarCheck?: ?boolean, + + /** + * If `true`, hide vertical scrollbar on the underlying multiline scrollview + * The default value is `false`. + * + * @platform macos + */ + hideVerticalScrollIndicator?: ?boolean, + /** * Fired when a supported element is pasted * @@ -381,6 +382,36 @@ type MacOSProps = $ReadOnly<{| */ onPaste?: (event: PasteEvent) => void, + /** + * Callback that is called when the text input's autoCorrect setting changes. + * This will be called with + * `{ nativeEvent: { enabled } }`. + * Does only work with 'multiline={true}'. + * + * @platform macos + */ + onAutoCorrectChange?: ?(e: SettingChangeEvent) => mixed, + + /** + * Callback that is called when the text input's spellCheck setting changes. + * This will be called with + * `{ nativeEvent: { enabled } }`. + * Does only work with 'multiline={true}'. + * + * @platform macos + */ + onSpellCheckChange?: ?(e: SettingChangeEvent) => mixed, + + /** + * Callback that is called when the text input's grammarCheck setting changes. + * This will be called with + * `{ nativeEvent: { enabled } }`. + * Does only work with 'multiline={true}'. + * + * @platform macos + */ + onGrammarCheckChange?: ?(e: SettingChangeEvent) => mixed, + /** * Enables Paste support for certain types of pasted types * @@ -399,6 +430,13 @@ type MacOSProps = $ReadOnly<{| * @platform macos */ submitKeyEvents?: ?$ReadOnlyArray, + + /** + * Specifies the tooltip. + * + * @platform macos + */ + tooltip?: ?string, |}>; // macOS] @@ -717,38 +755,6 @@ export type Props = $ReadOnly<{| */ onChangeText?: ?(text: string) => mixed, - // [macOS - /** - * Callback that is called when the text input's autoCorrect setting changes. - * This will be called with - * `{ nativeEvent: { enabled } }`. - * Does only work with 'multiline={true}'. - * - * @platform macos - */ - onAutoCorrectChange?: ?(e: SettingChangeEvent) => mixed, - - /** - * Callback that is called when the text input's spellCheck setting changes. - * This will be called with - * `{ nativeEvent: { enabled } }`. - * Does only work with 'multiline={true}'. - * - * @platform macos - */ - onSpellCheckChange?: ?(e: SettingChangeEvent) => mixed, - - /** - * Callback that is called when the text input's grammarCheck setting changes. - * This will be called with - * `{ nativeEvent: { enabled } }`. - * Does only work with 'multiline={true}'. - * - * @platform macos - */ - onGrammarCheckChange?: ?(e: SettingChangeEvent) => mixed, - // macOS] - /** * DANGER: this API is not stable and will change in the future. * @@ -921,12 +927,6 @@ export type Props = $ReadOnly<{| */ style?: ?TextStyleProp, - // [macOS - /* - * Specifies the tooltip. - */ - tooltip?: ?string, // macOS ] - /** * The value to show for the text input. `TextInput` is a controlled * component, which means the native value will be forced to match this @@ -1499,9 +1499,6 @@ const ExportedForwardRef: React.AbstractComponent< ); }); -ExportedForwardRef.propTypes = - require('deprecated-react-native-prop-types').TextInputPropTypes; - // $FlowFixMe[prop-missing] ExportedForwardRef.State = { currentlyFocusedInput: TextInputState.currentlyFocusedInput, diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index f9cf6f1cf3..b7cb8cb221 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -308,7 +308,12 @@ class TouchableOpacity extends React.Component { componentDidUpdate(prevProps: Props, prevState: State) { this.state.pressability.configure(this._createPressabilityConfig()); - if (this.props.disabled !== prevProps.disabled) { + if ( + this.props.disabled !== prevProps.disabled || + (flattenStyle(prevProps.style)?.opacity !== + flattenStyle(this.props.style)?.opacity) !== + undefined + ) { this._opacityInactive(250); } } diff --git a/Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap b/Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap index 63c3e3507a..244045f005 100644 --- a/Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap +++ b/Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap @@ -6,7 +6,6 @@ exports[` should render as expected 1`] = ` enabled={true} maximumValue={1} minimumValue={0} - onChange={null} onResponderTerminationRequest={[Function]} onSlidingComplete={null} onStartShouldSetResponder={[Function]} @@ -27,7 +26,6 @@ exports[` should set disabled as false 1`] = ` enabled={true} maximumValue={1} minimumValue={0} - onChange={null} onResponderTerminationRequest={[Function]} onSlidingComplete={null} onStartShouldSetResponder={[Function]} @@ -53,7 +51,6 @@ exports[` should set disabled as false 2`] = ` enabled={true} maximumValue={1} minimumValue={0} - onChange={null} onResponderTerminationRequest={[Function]} onSlidingComplete={null} onStartShouldSetResponder={[Function]} @@ -79,7 +76,6 @@ exports[` should set disabled as true 1`] = ` enabled={false} maximumValue={1} minimumValue={0} - onChange={null} onResponderTerminationRequest={[Function]} onSlidingComplete={null} onStartShouldSetResponder={[Function]} @@ -105,7 +101,6 @@ exports[` should set disabled as true 2`] = ` enabled={false} maximumValue={1} minimumValue={0} - onChange={null} onResponderTerminationRequest={[Function]} onSlidingComplete={null} onStartShouldSetResponder={[Function]} diff --git a/Libraries/Core/RawEventEmitter.js b/Libraries/Core/RawEventEmitter.js new file mode 100644 index 0000000000..cd330469cd --- /dev/null +++ b/Libraries/Core/RawEventEmitter.js @@ -0,0 +1,38 @@ +/** + * Copyright (c) Meta Platforms, Inc. and 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 EventEmitter from '../vendor/emitter/EventEmitter'; +import type {IEventEmitter} from '../vendor/emitter/EventEmitter'; + +export type RawEventEmitterEvent = $ReadOnly<{| + eventName: string, + // We expect, but do not/cannot require, that nativeEvent is an object + // with the properties: key, elementType (string), type (string), tag (numeric), + // and a stateNode of the native element/Fiber the event was emitted to. + nativeEvent: {[string]: mixed}, +|}>; + +type RawEventDefinitions = { + [eventChannel: string]: [RawEventEmitterEvent], +}; + +const RawEventEmitter: IEventEmitter = + new EventEmitter(); + +// See the React renderer / react repo for how this is used. +// Raw events are emitted here when they are received in JS +// and before any event Plugins process them or before components +// have a chance to respond to them. This allows you to implement +// app-specific perf monitoring, which is unimplemented by default, +// making this entire RawEventEmitter do nothing by default until +// *you* add listeners for your own app. +// Besides perf monitoring and maybe debugging, this RawEventEmitter +// should not be used. +export default RawEventEmitter; diff --git a/Libraries/EventEmitter/NativeEventEmitter.js b/Libraries/EventEmitter/NativeEventEmitter.js index b1e3b66146..8a78719922 100644 --- a/Libraries/EventEmitter/NativeEventEmitter.js +++ b/Libraries/EventEmitter/NativeEventEmitter.js @@ -10,9 +10,9 @@ 'use strict'; -import { - type EventSubscription, - type IEventEmitter, +import type { + EventSubscription, + IEventEmitter, } from '../vendor/emitter/EventEmitter'; import Platform from '../Utilities/Platform'; import RCTDeviceEventEmitter from './RCTDeviceEventEmitter'; diff --git a/Libraries/EventEmitter/RCTDeviceEventEmitter.js b/Libraries/EventEmitter/RCTDeviceEventEmitter.js index 4b41b2fa7c..c9f182f765 100644 --- a/Libraries/EventEmitter/RCTDeviceEventEmitter.js +++ b/Libraries/EventEmitter/RCTDeviceEventEmitter.js @@ -8,7 +8,8 @@ * @format */ -import EventEmitter, {type IEventEmitter} from '../vendor/emitter/EventEmitter'; +import EventEmitter from '../vendor/emitter/EventEmitter'; +import type {IEventEmitter} from '../vendor/emitter/EventEmitter'; // FIXME: use typed events type RCTDeviceEventDefinitions = $FlowFixMe; diff --git a/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js b/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js index 136be278ee..fe388c81ff 100644 --- a/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +++ b/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js @@ -8,9 +8,9 @@ * @flow strict-local */ -import { - type EventSubscription, - type IEventEmitter, +import type { + EventSubscription, + IEventEmitter, } from '../../vendor/emitter/EventEmitter'; import RCTDeviceEventEmitter from '../RCTDeviceEventEmitter'; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 2dd43e4dfb..bce7152717 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -306,12 +306,6 @@ Image.queryCache = queryCache; * comment and run Flow. */ Image.resolveAssetSource = resolveAssetSource; -/** - * Switch to `deprecated-react-native-prop-types` for compatibility with future - * releases. This is deprecated and will be removed in the future. - */ -Image.propTypes = require('deprecated-react-native-prop-types').ImagePropTypes; - const styles = StyleSheet.create({ base: { overflow: 'hidden', diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index de862a8b7d..8e72bae4eb 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -235,12 +235,6 @@ Image.queryCache = queryCache; * delete this comment and run Flow. */ Image.resolveAssetSource = resolveAssetSource; -/** - * Switch to `deprecated-react-native-prop-types` for compatibility with future - * releases. This is deprecated and will be removed in the future. - */ -Image.propTypes = require('deprecated-react-native-prop-types').ImagePropTypes; - const styles = StyleSheet.create({ base: { overflow: 'hidden', diff --git a/Libraries/Image/ImageViewNativeComponent.js b/Libraries/Image/ImageViewNativeComponent.js index d0e0206827..69b21ea226 100644 --- a/Libraries/Image/ImageViewNativeComponent.js +++ b/Libraries/Image/ImageViewNativeComponent.js @@ -12,6 +12,7 @@ import type {ResolvedAssetSource} from './AssetSourceResolver'; import type {ImageProps} from './ImageProps'; import type {ViewProps} from '../Components/View/ViewPropTypes'; import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry'; +import {ConditionallyIgnoredEventHandlers} from '../NativeComponent/ViewConfigIgnore'; import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; import type { ColorValue, @@ -125,6 +126,14 @@ const ImageViewViewConfig = tintColor: { process: require('../StyleSheet/processColor'), }, + ...ConditionallyIgnoredEventHandlers({ + onLoadStart: true, + onLoad: true, + onLoadEnd: true, + onProgress: true, + onError: true, + onPartialLoad: true, + }), }, }; diff --git a/Libraries/Linking/Linking.js b/Libraries/Linking/Linking.js index 543078f37f..8e0f5cbb90 100644 --- a/Libraries/Linking/Linking.js +++ b/Libraries/Linking/Linking.js @@ -8,7 +8,7 @@ * @flow strict-local */ -import {type EventSubscription} from '../vendor/emitter/EventEmitter'; +import type {EventSubscription} from '../vendor/emitter/EventEmitter'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import InteractionManager from '../Interaction/InteractionManager'; import Platform from '../Utilities/Platform'; diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 62d2adea97..c98630daee 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -440,7 +440,7 @@ class VirtualizedList extends React.PureComponent { scrollToEnd(params?: ?{animated?: ?boolean, ...}) { const animated = params ? params.animated : true; const veryLast = this.props.getItemCount(this.props.data) - 1; - const frame = this._getFrameMetricsApprox(veryLast); + const frame = this.__getFrameMetricsApprox(veryLast); const offset = Math.max( 0, frame.offset + @@ -514,7 +514,7 @@ class VirtualizedList extends React.PureComponent { }); return; } - const frame = this._getFrameMetricsApprox(index); + const frame = this.__getFrameMetricsApprox(index); const offset = Math.max( 0, @@ -595,7 +595,7 @@ class VirtualizedList extends React.PureComponent { // [macOS ensureItemAtIndexIsVisible(rowIndex: number) { - const frame = this._getFrameMetricsApprox(rowIndex); + const frame = this.__getFrameMetricsApprox(rowIndex); const visTop = this._scrollMetrics.offset; const visLen = this._scrollMetrics.visibleLength; const visEnd = visTop + visLen; @@ -1044,8 +1044,8 @@ class VirtualizedList extends React.PureComponent { // See if there are any sticky headers in the virtualized space that we need to render. for (let ii = firstAfterInitial - 1; ii > lastInitialIndex; ii--) { if (stickyIndicesFromProps.has(ii + stickyOffset)) { - const initBlock = this._getFrameMetricsApprox(lastInitialIndex); - const stickyBlock = this._getFrameMetricsApprox(ii); + const initBlock = this.__getFrameMetricsApprox(lastInitialIndex); + const stickyBlock = this.__getFrameMetricsApprox(ii); const leadSpace = stickyBlock.offset - initBlock.offset - @@ -1062,7 +1062,7 @@ class VirtualizedList extends React.PureComponent { inversionStyle, ); const trailSpace = - this._getFrameMetricsApprox(first).offset - + this.__getFrameMetricsApprox(first).offset - (stickyBlock.offset + stickyBlock.length); cells.push( , @@ -1073,9 +1073,9 @@ class VirtualizedList extends React.PureComponent { } } if (!insertedStickySpacer) { - const initBlock = this._getFrameMetricsApprox(lastInitialIndex); + const initBlock = this.__getFrameMetricsApprox(lastInitialIndex); const firstSpace = - this._getFrameMetricsApprox(first).offset - + this.__getFrameMetricsApprox(first).offset - (initBlock.offset + initBlock.length); cells.push( , @@ -1099,14 +1099,14 @@ class VirtualizedList extends React.PureComponent { this._hasWarned.keys = true; } if (!isVirtualizationDisabled && last < itemCount - 1) { - const lastFrame = this._getFrameMetricsApprox(last); + const lastFrame = this.__getFrameMetricsApprox(last); // Without getItemLayout, we limit our tail spacer to the _highestMeasuredFrameIndex to // prevent the user for hyperscrolling into un-measured area because otherwise content will // likely jump around as it renders in above the viewport. const end = this.props.getItemLayout ? itemCount - 1 : Math.min(itemCount - 1, this._highestMeasuredFrameIndex); - const endFrame = this._getFrameMetricsApprox(end); + const endFrame = this.__getFrameMetricsApprox(end); const tailSpacerLength = endFrame.offset + endFrame.length - @@ -1629,7 +1629,7 @@ class VirtualizedList extends React.PureComponent { const framesInLayout = []; const itemCount = this.props.getItemCount(this.props.data); for (let ii = 0; ii < itemCount; ii++) { - const frame = this._getFrameMetricsApprox(ii); + const frame = this.__getFrameMetricsApprox(ii); /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This comment * suppresses an error found when Flow v0.68 was deployed. To see the * error delete this comment and run Flow. */ @@ -1637,8 +1637,8 @@ class VirtualizedList extends React.PureComponent { framesInLayout.push(frame); } } - const windowTop = this._getFrameMetricsApprox(this.state.first).offset; - const frameLast = this._getFrameMetricsApprox(this.state.last); + const windowTop = this.__getFrameMetricsApprox(this.state.first).offset; + const frameLast = this.__getFrameMetricsApprox(this.state.last); const windowLen = frameLast.offset + frameLast.length - windowTop; const visTop = this._scrollMetrics.offset; const visLen = this._scrollMetrics.visibleLength; @@ -1852,7 +1852,7 @@ class VirtualizedList extends React.PureComponent { // Mark as high priority if we're close to the start of the first item // But only if there are items before the first rendered item if (first > 0) { - const distTop = offset - this._getFrameMetricsApprox(first).offset; + const distTop = offset - this.__getFrameMetricsApprox(first).offset; hiPri = hiPri || distTop < 0 || (velocity < -2 && distTop < scrollingThreshold); } @@ -1860,7 +1860,7 @@ class VirtualizedList extends React.PureComponent { // But only if there are items after the last rendered item if (last < itemCount - 1) { const distBottom = - this._getFrameMetricsApprox(last).offset - (offset + visibleLength); + this.__getFrameMetricsApprox(last).offset - (offset + visibleLength); hiPri = hiPri || distBottom < 0 || @@ -1962,7 +1962,7 @@ class VirtualizedList extends React.PureComponent { maxToRenderPerBatchOrDefault(this.props.maxToRenderPerBatch), windowSizeOrDefault(this.props.windowSize), state, - this._getFrameMetricsApprox, + this.__getFrameMetricsApprox, this._scrollMetrics, ); } @@ -2025,13 +2025,11 @@ class VirtualizedList extends React.PureComponent { return {index, item, key: this._keyExtractor(item, index), isViewable}; }; - _getFrameMetricsApprox = ( - index: number, - ): { + __getFrameMetricsApprox: (index: number) => { length: number, offset: number, ... - } => { + } = index => { const frame = this._getFrameMetrics(index); if (frame && frame.index === index) { // check for invalid frames due to row re-ordering diff --git a/Libraries/Lists/VirtualizedSectionList.js b/Libraries/Lists/VirtualizedSectionList.js index 0750972195..e8b81a519c 100644 --- a/Libraries/Lists/VirtualizedSectionList.js +++ b/Libraries/Lists/VirtualizedSectionList.js @@ -171,8 +171,7 @@ class VirtualizedSectionList< return; } if (params.itemIndex > 0 && this.props.stickySectionHeadersEnabled) { - // $FlowFixMe[prop-missing] Cannot access private property - const frame = this._listRef._getFrameMetricsApprox( + const frame = this._listRef.__getFrameMetricsApprox( index - params.itemIndex, ); viewOffset += frame.length; diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm b/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm index eac3e9fe00..b05721d04a 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm +++ b/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm @@ -96,6 +96,14 @@ RCT_EXPORT_METHOD(createAnimatedNode:(double)tag }]; } +RCT_EXPORT_METHOD(updateAnimatedNodeConfig:(double)tag + config:(NSDictionary *)config) +{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager updateAnimatedNodeConfig:[NSNumber numberWithDouble:tag] config:config]; + }]; +} + RCT_EXPORT_METHOD(connectAnimatedNodes:(double)parentTag childTag:(double)childTag) { diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h index 974d56ebea..7b558ab10a 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h @@ -64,6 +64,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)extractAnimatedNodeOffset:(NSNumber *)nodeTag; +- (void)updateAnimatedNodeConfig:(NSNumber *)tag + config:(NSDictionary *)config; + // drivers - (void)startAnimatingNode:(NSNumber *)animationId diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m index 802c707a2f..5ca4d02f26 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m +++ b/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.m @@ -261,6 +261,12 @@ static NSString *RCTNormalizeAnimatedEventName(NSString *eventName) saveCallback(@[@(valueNode.value)]); } +- (void)updateAnimatedNodeConfig:(NSNumber *)tag + config:(NSDictionary *)config +{ + // TODO (T111179606): Support platform colors for color animations +} + #pragma mark -- Drivers - (void)startAnimatingNode:(NSNumber *)animationId diff --git a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm index e627475bb6..0e3be34504 100644 --- a/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +++ b/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm @@ -102,6 +102,14 @@ RCT_EXPORT_METHOD(createAnimatedNode:(double)tag }]; } +RCT_EXPORT_METHOD(updateAnimatedNodeConfig:(double)tag + config:(NSDictionary *)config) +{ + [self addOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) { + [nodesManager updateAnimatedNodeConfig:[NSNumber numberWithDouble:tag] config:config]; + }]; +} + RCT_EXPORT_METHOD(connectAnimatedNodes:(double)parentTag childTag:(double)childTag) { diff --git a/Libraries/NativeComponent/PlatformBaseViewConfig.js b/Libraries/NativeComponent/PlatformBaseViewConfig.js index 40a9d6a47c..07c84a8679 100644 --- a/Libraries/NativeComponent/PlatformBaseViewConfig.js +++ b/Libraries/NativeComponent/PlatformBaseViewConfig.js @@ -11,7 +11,10 @@ import {Platform} from 'react-native'; import type {PartialViewConfig} from '../Renderer/shims/ReactNativeTypes'; import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes'; -import {DynamicallyInjectedByGestureHandler} from './ViewConfigIgnore'; +import { + DynamicallyInjectedByGestureHandler, + ConditionallyIgnoredEventHandlers, +} from './ViewConfigIgnore'; type PartialViewConfigWithoutName = $Rest< PartialViewConfig, @@ -35,13 +38,13 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = registrationName: 'onAccessibilityAction', }, topPointerEnter: { - registrationName: 'pointerenter', + registrationName: 'onPointerEnter', }, topPointerLeave: { - registrationName: 'pointerleave', + registrationName: 'onPointerLeave', }, topPointerMove: { - registrationName: 'pointermove', + registrationName: 'onPointerMove', }, onGestureHandlerEvent: DynamicallyInjectedByGestureHandler({ registrationName: 'onGestureHandlerEvent', @@ -216,9 +219,31 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = position: true, onLayout: true, - pointerenter: true, - pointerleave: true, - pointermove: true, + // Pointer events + onPointerEnter: true, + onPointerLeave: true, + onPointerMove: true, + + // PanResponder handlers + onMoveShouldSetResponder: true, + onMoveShouldSetResponderCapture: true, + onStartShouldSetResponder: true, + onStartShouldSetResponderCapture: true, + onResponderGrant: true, + onResponderReject: true, + onResponderStart: true, + onResponderEnd: true, + onResponderRelease: true, + onResponderMove: true, + onResponderTerminate: true, + onResponderTerminationRequest: true, + onShouldBlockNativeResponder: true, + + // Touch events + onTouchStart: true, + onTouchMove: true, + onTouchEnd: true, + onTouchCancel: true, style: ReactNativeStyleAttributes, }, @@ -351,6 +376,7 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = }), // macOS] }, + // $FlowFixMe: Flow doesn't like these nested spreads // [macOS] validAttributes: { // View Props accessible: true, @@ -361,8 +387,7 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = accessibilityViewIsModal: true, accessibilityElementsHidden: true, accessibilityIgnoresInvertColors: true, - apple_fontSmoothing: true, // TODO(OSS Candidate ISS#2710739) - testID: true, + apple_fontSmoothing: true, // [macOS] backgroundColor: {process: require('../StyleSheet/processColor')}, backfaceVisibility: true, opacity: true, @@ -477,6 +502,7 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = style: ReactNativeStyleAttributes, // [macOS + // $FlowFixMe: Flow doesn't like these nested spreads ...(Platform.OS === 'macos' && { acceptsFirstMouse: true, accessibilityTraits: true, @@ -484,22 +510,57 @@ const PlatformBaseViewConfig: PartialViewConfigWithoutName = draggedTypes: true, enableFocusRing: true, nextKeyViewTag: true, - onBlur: true, - onClick: true, - onDoubleClick: true, - onDragEnter: true, - onDragLeave: true, - onDrop: true, - onFocus: true, - onKeyDown: true, - onKeyUp: true, - onMouseEnter: true, - onMouseLeave: true, tooltip: true, validKeysDown: true, validKeysUp: true, }), // macOS] + // $FlowFixMe: Flow doesn't like these nested spreads // [macOS] + ...ConditionallyIgnoredEventHandlers({ + onLayout: true, + onMagicTap: true, + onAccessibilityAction: true, + onAccessibilityEscape: true, + onAccessibilityTap: true, + + // PanResponder handlers + onMoveShouldSetResponder: true, + onMoveShouldSetResponderCapture: true, + onStartShouldSetResponder: true, + onStartShouldSetResponderCapture: true, + onResponderGrant: true, + onResponderReject: true, + onResponderStart: true, + onResponderEnd: true, + onResponderRelease: true, + onResponderMove: true, + onResponderTerminate: true, + onResponderTerminationRequest: true, + onShouldBlockNativeResponder: true, + + // Touch events + onTouchStart: true, + onTouchMove: true, + onTouchEnd: true, + onTouchCancel: true, + + // [macOS + // $FlowFixMe: Flow doesn't like these nested spreads + ...(Platform.OS === 'macos' && { + onBlur: true, + onClick: true, + onDoubleClick: true, + onDragEnter: true, + onDragLeave: true, + onDrop: true, + onFocus: true, + onKeyDown: true, + onKeyUp: true, + onMouseEnter: true, + onMouseLeave: true, + }), + // macOS] + }), }, }; diff --git a/Libraries/NativeComponent/StaticViewConfigValidator.js b/Libraries/NativeComponent/StaticViewConfigValidator.js index ce48473d47..f1217d849e 100644 --- a/Libraries/NativeComponent/StaticViewConfigValidator.js +++ b/Libraries/NativeComponent/StaticViewConfigValidator.js @@ -9,13 +9,9 @@ */ import {type ViewConfig} from '../Renderer/shims/ReactNativeTypes'; -// $FlowFixMe[nonstrict-import] -import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; -// $FlowFixMe[nonstrict-import] -import {createViewConfig} from './ViewConfig'; import {isIgnored} from './ViewConfigIgnore'; -type Difference = +export type Difference = | { type: 'missing', path: Array, @@ -33,7 +29,7 @@ type Difference = staticValue: mixed, }; -type ValidationResult = ValidResult | InvalidResult; +export type ValidationResult = ValidResult | InvalidResult; type ValidResult = { type: 'valid', }; @@ -42,41 +38,6 @@ type InvalidResult = { differences: Array, }; -type ViewConfigValidationResult = { - componentName: string, - nativeViewConfig?: ?ViewConfig, - staticViewConfig?: ?ViewConfig, - validationResult?: ?ValidationResult, -}; - -// e.g. require('MyNativeComponent') where MyNativeComponent.js exports a HostComponent -type JSModule = $FlowFixMe; - -export function validateStaticViewConfigs( - nativeComponent: JSModule, -): ViewConfigValidationResult { - const nativeViewConfig = getNativeComponentAttributes( - nativeComponent.default || nativeComponent, - ); - - const generatedPartialViewConfig = nativeComponent.__INTERNAL_VIEW_CONFIG; - const staticViewConfig: ?ViewConfig = - generatedPartialViewConfig && createViewConfig(generatedPartialViewConfig); - - const componentName: string = nativeComponent.default || nativeComponent; - const validationResult: ?ValidationResult = - nativeViewConfig && - staticViewConfig && - validate(componentName, nativeViewConfig, staticViewConfig); - - return { - componentName, - nativeViewConfig, - staticViewConfig, - validationResult, - }; -} - /** * During the migration from native view configs to static view configs, this is * used to validate that the two are equivalent. diff --git a/Libraries/NativeComponent/ViewConfigIgnore.js b/Libraries/NativeComponent/ViewConfigIgnore.js index 78ccbb4044..8c7056ec6c 100644 --- a/Libraries/NativeComponent/ViewConfigIgnore.js +++ b/Libraries/NativeComponent/ViewConfigIgnore.js @@ -8,6 +8,8 @@ * @format */ +import Platform from '../Utilities/Platform'; + const ignoredViewConfigProps = new WeakSet<{...}>(); /** @@ -19,6 +21,30 @@ export function DynamicallyInjectedByGestureHandler(object: T): T { return object; } +/** + * On iOS, ViewManager event declarations generate {eventName}: true entries + * in ViewConfig valueAttributes. These entries aren't generated for Android. + * This annotation allows Static ViewConfigs to insert these entries into + * iOS but not Android. + * + * In the future, we want to remove this platform-inconsistency. + * This annotation also allows us to safely test this removal by setting + * global.RN$ViewConfigEventValidAttributesDisabled = true server-side. + * + * TODO(T110872225): Remove this logic, after achieving platform-consistency + */ +export function ConditionallyIgnoredEventHandlers( + value: T, +): T | void { + if ( + (Platform.OS === 'ios' || Platform.OS === 'macos') && + !(global.RN$ViewConfigEventValidAttributesDisabled === true) + ) { + return value; + } + return undefined; +} + export function isIgnored(value: mixed): boolean { if (typeof value === 'object' && value != null) { return ignoredViewConfigProps.has(value); diff --git a/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js b/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js index e4252de820..93f79effa9 100644 --- a/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +++ b/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js @@ -29,6 +29,7 @@ type Notification = {| +repeatInterval?: ?string, +applicationIconBadgeNumber?: ?number, +isSilent?: ?boolean, + +soundName?: ?string, |}; export interface Spec extends TurboModule { diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm b/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm index 72c197969d..d85a32369c 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm @@ -407,10 +407,12 @@ RCT_EXPORT_METHOD(requestPermissions:(JS::NativePushNotificationManagerIOS::Spec if (error != NULL) { reject(@"-1", @"Error - Push authorization request failed.", error); } else { - [RCTSharedApplication() registerForRemoteNotifications]; - [UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { - resolve(RCTPromiseResolveValueForUNNotificationSettings(settings)); - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [RCTSharedApplication() registerForRemoteNotifications]; + [UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { + resolve(RCTPromiseResolveValueForUNNotificationSettings(settings)); + }]; + }); } }]; #else // [macOS @@ -486,6 +488,9 @@ RCT_EXPORT_METHOD(presentLocalNotification:(JS::NativePushNotificationManagerIOS } if (notification.isSilent()) { notificationDict[@"isSilent"] = @(*notification.isSilent()); + if ([notificationDict[@"isSilent"] isEqualToNumber:@(NO)]) { + notificationDict[@"soundName"] = notification.soundName(); + } } [RCTSharedApplication() presentLocalNotificationNow:[RCTConvert UILocalNotification:notificationDict]]; } @@ -514,6 +519,9 @@ RCT_EXPORT_METHOD(scheduleLocalNotification:(JS::NativePushNotificationManagerIO } if (notification.isSilent()) { notificationDict[@"isSilent"] = @(*notification.isSilent()); + if ([notificationDict[@"isSilent"] isEqualToNumber:@(NO)]) { + notificationDict[@"soundName"] = notification.soundName(); + } } [RCTSharedApplication() scheduleLocalNotification:[RCTConvert UILocalNotification:notificationDict]]; } diff --git a/Libraries/ReactPrivate/ReactNativePrivateInterface.js b/Libraries/ReactPrivate/ReactNativePrivateInterface.js index e7c9d2a983..d671212dca 100644 --- a/Libraries/ReactPrivate/ReactNativePrivateInterface.js +++ b/Libraries/ReactPrivate/ReactNativePrivateInterface.js @@ -21,6 +21,7 @@ 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'; +import typeof RawEventEmitter from '../Core/RawEventEmitter'; // flowlint unsafe-getters-setters:off module.exports = { @@ -62,4 +63,7 @@ module.exports = { get legacySendAccessibilityEvent(): legacySendAccessibilityEvent { return require('../Components/AccessibilityInfo/legacySendAccessibilityEvent'); }, + get RawEventEmitter(): RawEventEmitter { + return require('../Core/RawEventEmitter').default; + }, }; diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index b3c49ffc21..17b725fb85 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -51947a14bb24bd151f76f6fc0acdbbc404de13f7 \ No newline at end of file +a3bde7974c48cfa749b18531700f895c86cbad91 \ 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 f37be3e0ef..d8d4d08bef 100644 --- a/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<10efd73d5435b5750183622476c68681>> + * @generated SignedSource<<5cd13a68c6b2a6d7a0ea84aff011af30>> */ 'use strict'; @@ -3888,7 +3888,34 @@ function dispatchEvent(target, topLevelType, nativeEvent) { } batchedUpdates(function() { - // Heritage plugin event system + // Emit event to the RawEventEmitter. This is an unused-by-default EventEmitter + // that can be used to instrument event performance monitoring (primarily - could be useful + // for other things too). + // + // NOTE: this merely emits events into the EventEmitter below. + // If *you* do not add listeners to the `RawEventEmitter`, + // then all of these emitted events will just blackhole and are no-ops. + // It is available (although not officially supported... yet) if you want to collect + // perf data on event latency in your application, and could also be useful for debugging + // low-level events issues. + // + // If you do not have any event perf monitoring and are extremely concerned about event perf, + // it is safe to disable these "emit" statements; it will prevent checking the size of + // an empty array twice and prevent two no-ops. Practically the overhead is so low that + // we don't think it's worth thinking about in prod; your perf issues probably lie elsewhere. + // + // We emit two events here: one for listeners to this specific event, + // and one for the catchall listener '*', for any listeners that want + // to be notified for all events. + // Note that extracted events are *not* emitted, + // only events that have a 1:1 mapping with a native event, at least for now. + var event = { + eventName: topLevelType, + nativeEvent: nativeEvent + }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); // Heritage plugin event system + runExtractedPluginEventsInBatch( topLevelType, targetFiber, @@ -4040,12 +4067,17 @@ function injectInternals(internals) { } try { - rendererID = hook.inject( - Object.assign({}, internals, { + if (enableSchedulingProfiler) { + // Conditionally inject these hooks only if Timeline profiler is supported by this build. + // This gives DevTools a way to feature detect that isn't tied to version number + // (since profiling and timeline are controlled by different feature flags). + internals = Object.assign({}, internals, { getLaneLabelMap: getLaneLabelMap, injectProfilingHooks: injectProfilingHooks - }) - ); // We have successfully injected, so now it is safe to set up hooks. + }); + } + + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. injectedHook = hook; } catch (err) { @@ -4179,16 +4211,18 @@ function injectProfilingHooks(profilingHooks) { } function getLaneLabelMap() { - var map = new Map(); - var lane = 1; + { + var map = new Map(); + var lane = 1; - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } + + return map; } - - return map; } function markCommitStarted(lanes) { @@ -6941,7 +6975,7 @@ function popProvider(context, providerFiber) { context._currentValue2 = currentValue; } } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { // Update the child lanes of all the ancestors, including the alternates. var node = parent; @@ -6959,14 +6993,23 @@ function scheduleWorkOnParentPath(parent, renderLanes) { !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } else { - // Neither alternate was updated, which means the rest of the - // ancestor path already has sufficient priority. + } + + if (node === propagationRoot) { break; } node = node.return; } + + { + if (node !== propagationRoot) { + error( + "Expected to find the propagation root when scheduling context work. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } } function propagateContextChange(workInProgress, context, renderLanes) { { @@ -7031,7 +7074,11 @@ function propagateContextChange_eager(workInProgress, context, renderLanes) { alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderLanes); // Mark the updated lanes on the list, too. + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the // dependency list. @@ -8906,7 +8953,7 @@ function popTreeContext(workInProgress) { } } -var isHydrating = false; +var isHydrating = false; // Hydration errors that were thrown inside this boundary function enterHydrationState(fiber) { { @@ -13866,7 +13913,7 @@ function throwException( // over and traverse parent path again, this time treating the exception // as an error. - renderDidError(); + renderDidError(value); value = createCapturedValue(value, sourceFiber); var workInProgress = returnFiber; @@ -16912,7 +16959,7 @@ function updateSuspenseFallbackChildren( return fallbackChildFragment; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; @@ -16920,7 +16967,7 @@ function scheduleWorkOnFiber(fiber, renderLanes) { alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function propagateSuspenseContextChange( @@ -16938,7 +16985,7 @@ function propagateSuspenseContextChange( var state = node.memoizedState; if (state !== null) { - scheduleWorkOnFiber(node, renderLanes); + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); } } else if (node.tag === SuspenseListComponent) { // If the tail is hidden there might not be an Suspense boundaries @@ -16946,7 +16993,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, renderLanes); + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); } else if (node.child !== null) { node.child.return = node; node = node.child; @@ -18238,6 +18285,16 @@ function safelyDetachRef(current, nearestMountedAncestor) { reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } + + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(current) + ); + } + } } else { ref.current = null; } @@ -18946,6 +19003,16 @@ function commitAttachRef(finishedWork) { } else { retVal = ref(instanceToUse); } + + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(finishedWork) + ); + } + } } else { { if (!ref.hasOwnProperty("current")) { @@ -20070,9 +20137,12 @@ var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). -var workInProgressRootRenderPhaseUpdatedLanes = NoLanes; // Lanes that were pinged (in an interleaved event) during this render. +var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. -var workInProgressRootPingedLanes = NoLanes; // The most recent time we committed a fallback. This lets us ensure a train +var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. +// We will log them once the tree commits. + +var workInProgressRootRecoverableErrors = 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; @@ -20220,11 +20290,6 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { // function), but there are some internal React features that use this as // an implementation detail, like selective hydration. warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase - - workInProgressRootRenderPhaseUpdatedLanes = mergeLanes( - workInProgressRootRenderPhaseUpdatedLanes, - lane - ); } else { // This is a normal update, scheduled from outside the render phase. For // example, during an input event. @@ -20601,30 +20666,34 @@ function recoverFromConcurrentError(root, errorRetryLanes) { } } - var exitStatus; - var MAX_ERROR_RETRY_ATTEMPTS = 50; + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + var exitStatus = renderRootSync(root, errorRetryLanes); - for (var i = 0; i < MAX_ERROR_RETRY_ATTEMPTS; i++) { - exitStatus = renderRootSync(root, errorRetryLanes); - - if ( - exitStatus === RootErrored && - workInProgressRootRenderPhaseUpdatedLanes !== NoLanes - ) { - // There was a render phase update during this render. Some internal React - // implementation details may use this as a trick to schedule another - // render pass. To protect against an inifinite loop, eventually - // we'll give up. - continue; + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + if (errorsFromFirstAttempt !== null) { + // The errors from the failed first attempt have been recovered. Add + // them to the collection of recoverable errors. We'll log them in the + // commit phase. + queueRecoverableErrors(errorsFromFirstAttempt); } - - break; } executionContext = prevExecutionContext; return exitStatus; } +function queueRecoverableErrors(errors) { + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errors + ); + } +} + function finishConcurrentRender(root, exitStatus, lanes) { switch (exitStatus) { case RootIncomplete: @@ -20638,7 +20707,7 @@ function finishConcurrentRender(root, exitStatus, lanes) { case RootErrored: { // We should have already attempted to retry this tree. If we reached // this point, it errored again. Commit it. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -20678,14 +20747,14 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), msUntilTimeout ); break; } } // The work expired. Commit immediately. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -20716,20 +20785,20 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), _msUntilTimeout ); break; } } // Commit the placeholder. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } case RootCompleted: { // The work completed. Ready to commit. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -20860,7 +20929,7 @@ function performSyncWorkOnRoot(root) { 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 + commitRoot(root, workInProgressRootRecoverableErrors); // Before exiting, make sure there's a callback scheduled for the next // pending level. ensureRootIsScheduled(root, now()); @@ -20967,8 +21036,9 @@ function prepareFreshStack(root, lanes) { workInProgressRootFatalError = null; workInProgressRootSkippedLanes = NoLanes; workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootRenderPhaseUpdatedLanes = NoLanes; workInProgressRootPingedLanes = NoLanes; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; enqueueInterleavedUpdates(); { @@ -21121,10 +21191,16 @@ function renderDidSuspendDelayIfPossible() { markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); } } -function renderDidError() { +function renderDidError(error) { if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { workInProgressRootExitStatus = RootErrored; } + + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; + } else { + workInProgressRootConcurrentErrors.push(error); + } } // Called during render to determine if anything has suspended. // Returns false if we're not sure. @@ -21393,7 +21469,7 @@ function completeUnitOfWork(unitOfWork) { } } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { // TODO: This no longer makes any sense. We already wrap the mutation and // layout phases. Should be able to remove. var previousUpdateLanePriority = getCurrentUpdatePriority(); @@ -21402,7 +21478,7 @@ function commitRoot(root) { try { ReactCurrentBatchConfig$2.transition = 0; setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { ReactCurrentBatchConfig$2.transition = prevTransition; setCurrentUpdatePriority(previousUpdateLanePriority); @@ -21411,7 +21487,7 @@ function commitRoot(root) { return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do { // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which // means `flushPassiveEffects` will sometimes result in additional @@ -21616,6 +21692,19 @@ function commitRootImpl(root, renderPriorityLevel) { ensureRootIsScheduled(root, now()); + if (recoverableErrors !== null) { + // There were errors during this render, but recovered from them without + // needing to surface it to the UI. We log them here. + for (var i = 0; i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + var onRecoverableError = root.onRecoverableError; + + if (onRecoverableError !== null) { + onRecoverableError(recoverableError); + } + } + } + if (hasUncaughtError) { hasUncaughtError = false; var error$1 = firstUncaughtError; @@ -23443,7 +23532,13 @@ function assignFiberPropertiesInDEV(target, source) { return target; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.pendingChildren = null; @@ -23467,6 +23562,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = NoLanes; this.entanglements = createLaneMap(NoLanes); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; { this.effectDuration = 0; @@ -23501,10 +23597,20 @@ function createFiberRoot( hydrate, hydrationCallbacks, isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix + concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the + // host config, but because they are passed in at runtime, we have to thread + // them through the root constructor. Perhaps we should put them all into a + // single type, like a DynamicHostConfig that is defined by the renderer. + identifierPrefix, + onRecoverableError ) { - var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix); + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ); // stateNode is any. var uninitializedFiber = createHostRootFiber( @@ -23526,7 +23632,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.0.0-rc.0-51947a14b-20220113"; +var ReactVersion = "18.0.0-rc.0-a3bde7974-20220208"; function createPortal( children, @@ -23654,7 +23760,8 @@ function createContainer( hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, - identifierPrefix + identifierPrefix, + onRecoverableError ) { return createFiberRoot( containerInfo, @@ -23663,7 +23770,8 @@ function createContainer( hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, - identifierPrefix + identifierPrefix, + onRecoverableError ); } function updateContainer(element, container, parentComponent, callback) { @@ -24458,7 +24566,8 @@ function render(element, containerTag, callback, concurrentRoot) { null, false, null, - "" + "", + null ); roots.set(containerTag, root); } diff --git a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js index bd8208a27d..5014f1e088 100644 --- a/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<97d9d60e7b93063137af17ba2abdf915>> */ "use strict"; @@ -927,7 +927,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_220 = { +var injectedNamesToPlugins$jscomp$inline_219 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -962,33 +962,33 @@ var injectedNamesToPlugins$jscomp$inline_220 = { } } }, - isOrderingDirty$jscomp$inline_221 = !1, - pluginName$jscomp$inline_222; -for (pluginName$jscomp$inline_222 in injectedNamesToPlugins$jscomp$inline_220) + isOrderingDirty$jscomp$inline_220 = !1, + pluginName$jscomp$inline_221; +for (pluginName$jscomp$inline_221 in injectedNamesToPlugins$jscomp$inline_219) if ( - injectedNamesToPlugins$jscomp$inline_220.hasOwnProperty( - pluginName$jscomp$inline_222 + injectedNamesToPlugins$jscomp$inline_219.hasOwnProperty( + pluginName$jscomp$inline_221 ) ) { - var pluginModule$jscomp$inline_223 = - injectedNamesToPlugins$jscomp$inline_220[pluginName$jscomp$inline_222]; + var pluginModule$jscomp$inline_222 = + injectedNamesToPlugins$jscomp$inline_219[pluginName$jscomp$inline_221]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_222) || - namesToPlugins[pluginName$jscomp$inline_222] !== - pluginModule$jscomp$inline_223 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_221) || + namesToPlugins[pluginName$jscomp$inline_221] !== + pluginModule$jscomp$inline_222 ) { - if (namesToPlugins[pluginName$jscomp$inline_222]) + if (namesToPlugins[pluginName$jscomp$inline_221]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_222 + "`.") + (pluginName$jscomp$inline_221 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_222 - ] = pluginModule$jscomp$inline_223; - isOrderingDirty$jscomp$inline_221 = !0; + pluginName$jscomp$inline_221 + ] = pluginModule$jscomp$inline_222; + isOrderingDirty$jscomp$inline_220 = !0; } } -isOrderingDirty$jscomp$inline_221 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_220 && recomputePluginOrdering(); function getInstanceFromInstance(instanceHandle) { return instanceHandle; } @@ -1559,7 +1559,10 @@ function dispatchEvent(target, topLevelType, nativeEvent) { null != stateNode && (eventTarget = stateNode.canonical); } batchedUpdates(function() { - var JSCompiler_inline_result = eventTarget; + var event = { eventName: topLevelType, nativeEvent: nativeEvent }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); + event = eventTarget; for ( var events = null, legacyPlugins = plugins, i = 0; i < legacyPlugins.length; @@ -1571,29 +1574,25 @@ function dispatchEvent(target, topLevelType, nativeEvent) { topLevelType, target, nativeEvent, - JSCompiler_inline_result + event )) && (events = accumulateInto(events, possiblePlugin)); } - JSCompiler_inline_result = events; - null !== JSCompiler_inline_result && - (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); - JSCompiler_inline_result = eventQueue; + event = events; + null !== event && (eventQueue = accumulateInto(eventQueue, event)); + event = eventQueue; eventQueue = null; - if (JSCompiler_inline_result) { - forEachAccumulated( - JSCompiler_inline_result, - executeDispatchesAndReleaseTopLevel - ); + if (event) { + forEachAccumulated(event, 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 ((JSCompiler_inline_result = rethrowError), + throw ((event = rethrowError), (hasRethrowError = !1), (rethrowError = null), - JSCompiler_inline_result); + event); } }); } @@ -1619,12 +1618,6 @@ function onCommitRoot(root) { ); } catch (err) {} } -function injectProfilingHooks() {} -function getLaneLabelMap() { - for (var map = new Map(), lane = 1, index$3 = 0; 31 > index$3; index$3++) - map.set(lane, void 0), (lane *= 2); - return map; -} var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log = Math.log, LN2 = Math.LN2; @@ -1797,21 +1790,21 @@ function markRootFinished(root, remainingLanes) { remainingLanes = root.entanglements; var eventTimes = root.eventTimes; for (root = root.expirationTimes; 0 < noLongerPendingLanes; ) { - var index$8 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$8; - remainingLanes[index$8] = 0; - eventTimes[index$8] = -1; - root[index$8] = -1; + var index$7 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$7; + remainingLanes[index$7] = 0; + eventTimes[index$7] = -1; + root[index$7] = -1; noLongerPendingLanes &= ~lane; } } function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); for (root = root.entanglements; rootEntangledLanes; ) { - var index$9 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$9; - (lane & entangledLanes) | (root[index$9] & entangledLanes) && - (root[index$9] |= entangledLanes); + var index$8 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$8; + (lane & entangledLanes) | (root[index$8] & entangledLanes) && + (root[index$8] |= entangledLanes); rootEntangledLanes &= ~lane; } } @@ -2185,19 +2178,16 @@ function popProvider(context) { pop(valueCursor); context._currentValue2 = currentValue; } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { for (; null !== parent; ) { var alternate = parent.alternate; - 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.childLanes & renderLanes) !== renderLanes + ? ((parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes)) + : null !== alternate && + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); + if (parent === propagationRoot) break; parent = parent.return; } } @@ -3666,28 +3656,37 @@ function updateMutableSource(source, getSnapshot, subscribe) { var hook = updateWorkInProgressHook(); return useMutableSource(hook, source, getSnapshot, subscribe); } -function mountSyncExternalStore(subscribe, getSnapshot) { +function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, - hook = mountWorkInProgressHook(); - var nextSnapshot = getSnapshot(); - var root = workInProgressRoot; - if (null === root) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + hook = updateWorkInProgressHook(), + nextSnapshot = getSnapshot(), + snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); + snapshotChanged && + ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); + hook = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ + subscribe + ]); + if ( + hook.getSnapshot !== getSnapshot || + snapshotChanged || + (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1) + ) { + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, hook, nextSnapshot, getSnapshot), + void 0, + null ); - includesBlockingLane(root, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - hook.memoizedState = nextSnapshot; - root = { value: nextSnapshot, getSnapshot: getSnapshot }; - hook.queue = root; - mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [subscribe]); - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), - void 0, - null - ); + subscribe = workInProgressRoot; + if (null === subscribe) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(subscribe, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } return nextSnapshot; } function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { @@ -4075,7 +4074,32 @@ var ContextOnlyDispatcher = { }; return useMutableSource(hook, source, getSnapshot, subscribe); }, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: function(subscribe, getSnapshot) { + var fiber = currentlyRenderingFiber$1, + hook = mountWorkInProgressHook(); + var nextSnapshot = getSnapshot(); + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(root, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + hook.memoizedState = nextSnapshot; + root = { value: nextSnapshot, getSnapshot: getSnapshot }; + hook.queue = root; + mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [ + subscribe + ]); + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), + void 0, + null + ); + return nextSnapshot; + }, useId: function() { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, @@ -4124,46 +4148,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: function(subscribe, getSnapshot) { - var fiber = currentlyRenderingFiber$1, - hook = updateWorkInProgressHook(), - nextSnapshot = getSnapshot(), - snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); - snapshotChanged && - ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); - hook = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ - subscribe - ]); - if ( - hook.getSnapshot !== getSnapshot || - snapshotChanged || - (null !== workInProgressHook && - workInProgressHook.memoizedState.tag & 1) - ) { - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind( - null, - fiber, - hook, - nextSnapshot, - getSnapshot - ), - void 0, - null - ); - subscribe = workInProgressRoot; - if (null === subscribe) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - includesBlockingLane(subscribe, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - return nextSnapshot; - }, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -4206,7 +4191,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }; @@ -4454,14 +4439,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$36 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$36 = lastTailNode), + for (var lastTailNode$35 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$35 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$36 + null === lastTailNode$35 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$36.sibling = null); + : (lastTailNode$35.sibling = null); } } function bubbleProperties(completedWork) { @@ -4471,19 +4456,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$37 = completedWork.child; null !== child$37; ) - (newChildLanes |= child$37.lanes | child$37.childLanes), - (subtreeFlags |= child$37.subtreeFlags & 14680064), - (subtreeFlags |= child$37.flags & 14680064), - (child$37.return = completedWork), - (child$37 = child$37.sibling); + for (var child$36 = completedWork.child; null !== child$36; ) + (newChildLanes |= child$36.lanes | child$36.childLanes), + (subtreeFlags |= child$36.subtreeFlags & 14680064), + (subtreeFlags |= child$36.flags & 14680064), + (child$36.return = completedWork), + (child$36 = child$36.sibling); else - for (child$37 = completedWork.child; null !== child$37; ) - (newChildLanes |= child$37.lanes | child$37.childLanes), - (subtreeFlags |= child$37.subtreeFlags), - (subtreeFlags |= child$37.flags), - (child$37.return = completedWork), - (child$37 = child$37.sibling); + for (child$36 = completedWork.child; null !== child$36; ) + (newChildLanes |= child$36.lanes | child$36.childLanes), + (subtreeFlags |= child$36.subtreeFlags), + (subtreeFlags |= child$36.flags), + (child$36.return = completedWork), + (child$36 = child$36.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5548,11 +5533,11 @@ function updateSuspenseFallbackChildren( workInProgress.child = current; return fallbackChildren; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; var alternate = fiber.alternate; null !== alternate && (alternate.lanes |= renderLanes); - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function initSuspenseListRenderState( workInProgress, @@ -5591,8 +5576,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderLanes); - else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); + else if (19 === current.tag) + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -5906,8 +5892,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$81 = effect.create; - effect.destroy = create$81(); + var create$80 = effect.create; + effect.destroy = create$80(); } effect = effect.next; } while (effect !== finishedWork); @@ -6084,8 +6070,8 @@ function commitMutationEffects(root, firstChild) { switch (root.tag) { case 13: if (null !== root.memoizedState) { - var current$85 = root.alternate; - if (null === current$85 || null === current$85.memoizedState) + var current$84 = root.alternate; + if (null === current$84 || null === current$84.memoizedState) globalMostRecentFallbackTime = now(); } } @@ -6162,8 +6148,8 @@ function commitLayoutEffects(finishedWork) { commitUpdateQueue(firstChild, updateQueue, instance); break; case 3: - var updateQueue$82 = firstChild.updateQueue; - if (null !== updateQueue$82) { + var updateQueue$81 = firstChild.updateQueue; + if (null !== updateQueue$81) { current = null; if (null !== firstChild.child) switch (firstChild.child.tag) { @@ -6173,7 +6159,7 @@ function commitLayoutEffects(finishedWork) { case 1: current = firstChild.child.stateNode; } - commitUpdateQueue(firstChild, updateQueue$82, current); + commitUpdateQueue(firstChild, updateQueue$81, current); } break; case 5: @@ -6250,8 +6236,9 @@ var ceil = Math.ceil, workInProgressRootFatalError = null, workInProgressRootSkippedLanes = 0, workInProgressRootInterleavedUpdatedLanes = 0, - workInProgressRootRenderPhaseUpdatedLanes = 0, workInProgressRootPingedLanes = 0, + workInProgressRootConcurrentErrors = null, + workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, hasUncaughtError = !1, @@ -6310,19 +6297,18 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (null === root) return null; markRootUpdated(root, lane, eventTime); - 0 !== (executionContext & 2) && root === workInProgressRoot - ? (workInProgressRootRenderPhaseUpdatedLanes |= lane) - : (root === workInProgressRoot && - (0 === (executionContext & 2) && - (workInProgressRootInterleavedUpdatedLanes |= lane), - 4 === workInProgressRootExitStatus && - markRootSuspended$1(root, workInProgressRootRenderLanes)), + if (0 === (executionContext & 2) || root !== workInProgressRoot) + root === workInProgressRoot && + (0 === (executionContext & 2) && + (workInProgressRootInterleavedUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(root, workInProgressRootRenderLanes)), ensureRootIsScheduled(root, eventTime), 1 === lane && 0 === executionContext && 0 === (fiber.mode & 1) && ((workInProgressRootRenderTargetTime = now() + 500), - includesLegacySyncCallbacks && flushSyncCallbacks())); + includesLegacySyncCallbacks && flushSyncCallbacks()); return root; } function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { @@ -6348,12 +6334,12 @@ function ensureRootIsScheduled(root, currentTime) { 0 < lanes; ) { - var index$6 = 31 - clz32(lanes), - lane = 1 << index$6, - expirationTime = expirationTimes[index$6]; + var index$5 = 31 - clz32(lanes), + lane = 1 << index$5, + expirationTime = expirationTimes[index$5]; if (-1 === expirationTime) { if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$6] = computeExpirationTime(lane, currentTime); + expirationTimes[index$5] = computeExpirationTime(lane, currentTime); } else expirationTime <= currentTime && (root.expiredLanes |= lane); lanes &= ~lane; } @@ -6493,7 +6479,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 3: markRootSuspended$1(root, lanes); @@ -6510,22 +6496,22 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), didTimeout ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 4: markRootSuspended$1(root, lanes); if ((lanes & 4194240) === lanes) break; didTimeout = root.eventTimes; for (prevExecutionContext = -1; 0 < lanes; ) { - var index$5 = 31 - clz32(lanes); - prevDispatcher = 1 << index$5; - index$5 = didTimeout[index$5]; - index$5 > prevExecutionContext && (prevExecutionContext = index$5); + var index$4 = 31 - clz32(lanes); + prevDispatcher = 1 << index$4; + index$4 = didTimeout[index$4]; + index$4 > prevExecutionContext && (prevExecutionContext = index$4); lanes &= ~prevDispatcher; } lanes = prevExecutionContext; @@ -6546,15 +6532,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), lanes ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 5: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; default: throw Error("Unknown root exit status."); @@ -6569,15 +6555,18 @@ function recoverFromConcurrentError(root, errorRetryLanes) { var prevExecutionContext = executionContext; executionContext |= 8; root.isDehydrated && (root.isDehydrated = !1); - for ( - var exitStatus, i = 0; - 50 > i && - ((exitStatus = renderRootSync(root, errorRetryLanes)), - 2 === exitStatus && 0 !== workInProgressRootRenderPhaseUpdatedLanes); - i++ - ); + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + root = renderRootSync(root, errorRetryLanes); + 2 !== root && + null !== errorsFromFirstAttempt && + (null === workInProgressRootConcurrentErrors + ? (workInProgressRootRecoverableErrors = errorsFromFirstAttempt) + : (workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errorsFromFirstAttempt + ))); executionContext = prevExecutionContext; - return exitStatus; + return root; } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -6619,9 +6608,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$7 = 31 - clz32(suspendedLanes), - lane = 1 << index$7; - root[index$7] = -1; + var index$6 = 31 - clz32(suspendedLanes), + lane = 1 << index$6; + root[index$6] = -1; suspendedLanes &= ~lane; } } @@ -6646,7 +6635,7 @@ function performSyncWorkOnRoot(root) { exitStatus); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); ensureRootIsScheduled(root, now()); return null; } @@ -6703,7 +6692,8 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootPingedLanes = workInProgressRootRenderPhaseUpdatedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootPingedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors = null; if (null !== interleavedQueues) { for (root = 0; root < interleavedQueues.length; root++) if ( @@ -6871,8 +6861,12 @@ function handleError(root$jscomp$0, thrownValue) { " 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." ); } + root = value; 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); value = createCapturedValue(value, sourceFiber); root = returnFiber; do { @@ -6904,12 +6898,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$32 = createClassErrorUpdate( + var update$31 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$32); + enqueueCapturedUpdate(root, update$31); break a; } } @@ -7004,20 +6998,20 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = 0), (currentUpdatePriority = 1), - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) @@ -7072,6 +7066,15 @@ function commitRootImpl(root, renderPriorityLevel) { 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); onCommitRoot(finishedWork.stateNode, renderPriorityLevel); ensureRootIsScheduled(root, now()); + if (null !== recoverableErrors) + for ( + renderPriorityLevel = 0; + renderPriorityLevel < recoverableErrors.length; + renderPriorityLevel++ + ) + (finishedWork = recoverableErrors[renderPriorityLevel]), + (lanes = root.onRecoverableError), + null !== lanes && lanes(finishedWork); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7644,7 +7647,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { newValue.lanes |= renderLanes; dependency = newValue.alternate; null !== dependency && (dependency.lanes |= renderLanes); - scheduleWorkOnParentPath(newValue.return, renderLanes); + scheduleContextWorkOnParentPath( + newValue.return, + renderLanes, + workInProgress + ); list.lanes |= renderLanes; break; } @@ -7949,7 +7956,13 @@ function createFiberFromPortal(portal, mode, lanes) { }; return mode; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; @@ -7963,6 +7976,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; this.entanglements = createLaneMap(0); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; } function createPortal(children, containerInfo, implementation) { var key = @@ -8166,10 +8180,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_926 = { + devToolsConfig$jscomp$inline_927 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-rc.0-51947a14b-20220113", + version: "18.0.0-rc.0-a3bde7974-20220208", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8184,11 +8198,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1179 = { - bundleType: devToolsConfig$jscomp$inline_926.bundleType, - version: devToolsConfig$jscomp$inline_926.version, - rendererPackageName: devToolsConfig$jscomp$inline_926.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_926.rendererConfig, +var internals$jscomp$inline_1181 = { + bundleType: devToolsConfig$jscomp$inline_927.bundleType, + version: devToolsConfig$jscomp$inline_927.version, + rendererPackageName: devToolsConfig$jscomp$inline_927.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_927.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8204,29 +8218,26 @@ var internals$jscomp$inline_1179 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_926.findFiberByHostInstance || + devToolsConfig$jscomp$inline_927.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-rc.0-51947a14b-20220113" + reconcilerVersion: "18.0.0-rc.0-a3bde7974-20220208" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1180 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1182 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1180.isDisabled && - hook$jscomp$inline_1180.supportsFiber + !hook$jscomp$inline_1182.isDisabled && + hook$jscomp$inline_1182.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1180.inject( - Object.assign({}, internals$jscomp$inline_1179, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }) + (rendererID = hook$jscomp$inline_1182.inject( + internals$jscomp$inline_1181 )), - (injectedHook = hook$jscomp$inline_1180); + (injectedHook = hook$jscomp$inline_1182); } catch (err) {} } exports.createPortal = function(children, containerTag) { @@ -8266,7 +8277,7 @@ exports.render = function(element, containerTag, callback, concurrentRoot) { var root = roots.get(containerTag); root || ((root = concurrentRoot ? 1 : 0), - (concurrentRoot = new FiberRootNode(containerTag, root, !1, "")), + (concurrentRoot = new FiberRootNode(containerTag, root, !1, "", null)), (root = createFiber(3, null, null, 1 === root ? 1 : 0)), (concurrentRoot.current = root), (root.stateNode = concurrentRoot), diff --git a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js index 88a4d7e8f7..6df38b40d9 100644 --- a/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<5c079c38f5734a3f694bc72a4da400d4>> */ @@ -1570,7 +1570,10 @@ function dispatchEvent(target, topLevelType, nativeEvent) { null != stateNode && (eventTarget = stateNode.canonical); } batchedUpdates(function() { - var JSCompiler_inline_result = eventTarget; + var event = { eventName: topLevelType, nativeEvent: nativeEvent }; + ReactNativePrivateInterface.RawEventEmitter.emit(topLevelType, event); + ReactNativePrivateInterface.RawEventEmitter.emit("*", event); + event = eventTarget; for ( var events = null, legacyPlugins = plugins, i = 0; i < legacyPlugins.length; @@ -1582,29 +1585,25 @@ function dispatchEvent(target, topLevelType, nativeEvent) { topLevelType, target, nativeEvent, - JSCompiler_inline_result + event )) && (events = accumulateInto(events, possiblePlugin)); } - JSCompiler_inline_result = events; - null !== JSCompiler_inline_result && - (eventQueue = accumulateInto(eventQueue, JSCompiler_inline_result)); - JSCompiler_inline_result = eventQueue; + event = events; + null !== event && (eventQueue = accumulateInto(eventQueue, event)); + event = eventQueue; eventQueue = null; - if (JSCompiler_inline_result) { - forEachAccumulated( - JSCompiler_inline_result, - executeDispatchesAndReleaseTopLevel - ); + if (event) { + forEachAccumulated(event, 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 ((JSCompiler_inline_result = rethrowError), + throw ((event = rethrowError), (hasRethrowError = !1), (rethrowError = null), - JSCompiler_inline_result); + event); } }); } @@ -2306,19 +2305,16 @@ function popProvider(context) { pop(valueCursor); context._currentValue2 = currentValue; } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { for (; null !== parent; ) { var alternate = parent.alternate; - 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.childLanes & renderLanes) !== renderLanes + ? ((parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes)) + : null !== alternate && + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); + if (parent === propagationRoot) break; parent = parent.return; } } @@ -3792,28 +3788,37 @@ function updateMutableSource(source, getSnapshot, subscribe) { var hook = updateWorkInProgressHook(); return useMutableSource(hook, source, getSnapshot, subscribe); } -function mountSyncExternalStore(subscribe, getSnapshot) { +function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, - hook = mountWorkInProgressHook(); - var nextSnapshot = getSnapshot(); - var root = workInProgressRoot; - if (null === root) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + hook = updateWorkInProgressHook(), + nextSnapshot = getSnapshot(), + snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); + snapshotChanged && + ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); + hook = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ + subscribe + ]); + if ( + hook.getSnapshot !== getSnapshot || + snapshotChanged || + (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1) + ) { + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, hook, nextSnapshot, getSnapshot), + void 0, + null ); - includesBlockingLane(root, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - hook.memoizedState = nextSnapshot; - root = { value: nextSnapshot, getSnapshot: getSnapshot }; - hook.queue = root; - mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [subscribe]); - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), - void 0, - null - ); + subscribe = workInProgressRoot; + if (null === subscribe) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(subscribe, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } return nextSnapshot; } function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { @@ -4203,7 +4208,32 @@ var ContextOnlyDispatcher = { }; return useMutableSource(hook, source, getSnapshot, subscribe); }, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: function(subscribe, getSnapshot) { + var fiber = currentlyRenderingFiber$1, + hook = mountWorkInProgressHook(); + var nextSnapshot = getSnapshot(); + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(root, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + hook.memoizedState = nextSnapshot; + root = { value: nextSnapshot, getSnapshot: getSnapshot }; + hook.queue = root; + mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [ + subscribe + ]); + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), + void 0, + null + ); + return nextSnapshot; + }, useId: function() { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, @@ -4252,46 +4282,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: function(subscribe, getSnapshot) { - var fiber = currentlyRenderingFiber$1, - hook = updateWorkInProgressHook(), - nextSnapshot = getSnapshot(), - snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); - snapshotChanged && - ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); - hook = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ - subscribe - ]); - if ( - hook.getSnapshot !== getSnapshot || - snapshotChanged || - (null !== workInProgressHook && - workInProgressHook.memoizedState.tag & 1) - ) { - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind( - null, - fiber, - hook, - nextSnapshot, - getSnapshot - ), - void 0, - null - ); - subscribe = workInProgressRoot; - if (null === subscribe) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - includesBlockingLane(subscribe, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - return nextSnapshot; - }, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -4334,7 +4325,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -5806,11 +5797,11 @@ function updateSuspenseFallbackChildren( workInProgress.child = current; return fallbackChildren; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; var alternate = fiber.alternate; null !== alternate && (alternate.lanes |= renderLanes); - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function initSuspenseListRenderState( workInProgress, @@ -5849,8 +5840,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderLanes); - else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); + else if (19 === current.tag) + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -6698,8 +6690,9 @@ var ceil = Math.ceil, workInProgressRootFatalError = null, workInProgressRootSkippedLanes = 0, workInProgressRootInterleavedUpdatedLanes = 0, - workInProgressRootRenderPhaseUpdatedLanes = 0, workInProgressRootPingedLanes = 0, + workInProgressRootConcurrentErrors = null, + workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, hasUncaughtError = !1, @@ -6759,9 +6752,8 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (null === root) return null; markRootUpdated(root, lane, eventTime); - 0 !== (executionContext & 2) && root === workInProgressRoot - ? (workInProgressRootRenderPhaseUpdatedLanes |= lane) - : (isDevToolsPresent && addFiberToLanesMap(root, fiber, lane), + if (0 === (executionContext & 2) || root !== workInProgressRoot) + isDevToolsPresent && addFiberToLanesMap(root, fiber, lane), root === workInProgressRoot && (0 === (executionContext & 2) && (workInProgressRootInterleavedUpdatedLanes |= lane), @@ -6772,7 +6764,7 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { 0 === executionContext && 0 === (fiber.mode & 1) && ((workInProgressRootRenderTargetTime = now() + 500), - includesLegacySyncCallbacks && flushSyncCallbacks())); + includesLegacySyncCallbacks && flushSyncCallbacks()); return root; } function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { @@ -6957,7 +6949,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 3: markRootSuspended$1(root, lanes); @@ -6974,12 +6966,12 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), didTimeout ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 4: markRootSuspended$1(root, lanes); @@ -7010,15 +7002,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), lanes ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 5: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; default: throw Error("Unknown root exit status."); @@ -7033,15 +7025,18 @@ function recoverFromConcurrentError(root, errorRetryLanes) { var prevExecutionContext = executionContext; executionContext |= 8; root.isDehydrated && (root.isDehydrated = !1); - for ( - var exitStatus, i = 0; - 50 > i && - ((exitStatus = renderRootSync(root, errorRetryLanes)), - 2 === exitStatus && 0 !== workInProgressRootRenderPhaseUpdatedLanes); - i++ - ); + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + root = renderRootSync(root, errorRetryLanes); + 2 !== root && + null !== errorsFromFirstAttempt && + (null === workInProgressRootConcurrentErrors + ? (workInProgressRootRecoverableErrors = errorsFromFirstAttempt) + : (workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errorsFromFirstAttempt + ))); executionContext = prevExecutionContext; - return exitStatus; + return root; } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -7112,7 +7107,7 @@ function performSyncWorkOnRoot(root) { exitStatus); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); ensureRootIsScheduled(root, now()); return null; } @@ -7169,7 +7164,8 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootPingedLanes = workInProgressRootRenderPhaseUpdatedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootPingedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors = null; if (null !== interleavedQueues) { for (root = 0; root < interleavedQueues.length; root++) if ( @@ -7364,8 +7360,12 @@ function handleError(root, thrownValue) { " 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." ); } + wakeable = value; 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [wakeable]) + : workInProgressRootConcurrentErrors.push(wakeable); value = createCapturedValue(value, sourceFiber); wakeable = returnFiber; do { @@ -7528,20 +7528,20 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = 0), (currentUpdatePriority = 1), - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) @@ -7607,6 +7607,15 @@ function commitRootImpl(root, renderPriorityLevel) { onCommitRoot(finishedWork.stateNode, renderPriorityLevel); isDevToolsPresent && root.memoizedUpdaters.clear(); ensureRootIsScheduled(root, now()); + if (null !== recoverableErrors) + for ( + renderPriorityLevel = 0; + renderPriorityLevel < recoverableErrors.length; + renderPriorityLevel++ + ) + (finishedWork = recoverableErrors[renderPriorityLevel]), + (lanes = root.onRecoverableError), + null !== lanes && lanes(finishedWork); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -8261,7 +8270,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { newValue.lanes |= renderLanes; dependency = newValue.alternate; null !== dependency && (dependency.lanes |= renderLanes); - scheduleWorkOnParentPath(newValue.return, renderLanes); + scheduleContextWorkOnParentPath( + newValue.return, + renderLanes, + workInProgress + ); list.lanes |= renderLanes; break; } @@ -8582,7 +8595,13 @@ function createFiberFromPortal(portal, mode, lanes) { }; return mode; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; @@ -8596,6 +8615,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; this.entanglements = createLaneMap(0); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; this.passiveEffectDuration = this.effectDuration = 0; this.memoizedUpdaters = new Set(); containerInfo = this.pendingUpdatersLaneMap = []; @@ -8806,10 +8826,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1002 = { + devToolsConfig$jscomp$inline_1004 = { findFiberByHostInstance: getInstanceFromInstance, bundleType: 0, - version: "18.0.0-rc.0-51947a14b-20220113", + version: "18.0.0-rc.0-a3bde7974-20220208", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8824,11 +8844,24 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1279 = { - bundleType: devToolsConfig$jscomp$inline_1002.bundleType, - version: devToolsConfig$jscomp$inline_1002.version, - rendererPackageName: devToolsConfig$jscomp$inline_1002.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1002.rendererConfig, +(function(internals) { + if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled || !hook.supportsFiber) return !0; + try { + (internals = Object.assign({}, internals, { + getLaneLabelMap: getLaneLabelMap, + injectProfilingHooks: injectProfilingHooks + })), + (rendererID = hook.inject(internals)), + (injectedHook = hook); + } catch (err) {} + return hook.checkDCE ? !0 : !1; +})({ + bundleType: devToolsConfig$jscomp$inline_1004.bundleType, + version: devToolsConfig$jscomp$inline_1004.version, + rendererPackageName: devToolsConfig$jscomp$inline_1004.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1004.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8844,31 +8877,15 @@ var internals$jscomp$inline_1279 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1002.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1004.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-rc.0-51947a14b-20220113" -}; -if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1280 = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if ( - !hook$jscomp$inline_1280.isDisabled && - hook$jscomp$inline_1280.supportsFiber - ) - try { - (rendererID = hook$jscomp$inline_1280.inject( - Object.assign({}, internals$jscomp$inline_1279, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }) - )), - (injectedHook = hook$jscomp$inline_1280); - } catch (err) {} -} + reconcilerVersion: "18.0.0-rc.0-a3bde7974-20220208" +}); exports.createPortal = function(children, containerTag) { return createPortal( children, @@ -8906,7 +8923,7 @@ exports.render = function(element, containerTag, callback, concurrentRoot) { var root = roots.get(containerTag); root || ((root = concurrentRoot ? 1 : 0), - (concurrentRoot = new FiberRootNode(containerTag, root, !1, "")), + (concurrentRoot = new FiberRootNode(containerTag, root, !1, "", null)), (root = 1 === root ? 1 : 0), isDevToolsPresent && (root |= 2), (root = createFiber(3, null, null, root)), diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js index fa3df1e36c..c913b5af61 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<<3ab224d749aabfd2af41824a03d0c6ce>> + * @generated SignedSource<> */ 'use strict'; @@ -4283,12 +4283,17 @@ function injectInternals(internals) { } try { - rendererID = hook.inject( - Object.assign({}, internals, { + if (enableSchedulingProfiler) { + // Conditionally inject these hooks only if Timeline profiler is supported by this build. + // This gives DevTools a way to feature detect that isn't tied to version number + // (since profiling and timeline are controlled by different feature flags). + internals = Object.assign({}, internals, { getLaneLabelMap: getLaneLabelMap, injectProfilingHooks: injectProfilingHooks - }) - ); // We have successfully injected, so now it is safe to set up hooks. + }); + } + + rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. injectedHook = hook; } catch (err) { @@ -4422,16 +4427,18 @@ function injectProfilingHooks(profilingHooks) { } function getLaneLabelMap() { - var map = new Map(); - var lane = 1; + { + var map = new Map(); + var lane = 1; - for (var index = 0; index < TotalLanes; index++) { - var label = getLabelForLane(lane); - map.set(lane, label); - lane *= 2; + for (var index = 0; index < TotalLanes; index++) { + var label = getLabelForLane(lane); + map.set(lane, label); + lane *= 2; + } + + return map; } - - return map; } function markCommitStarted(lanes) { @@ -7175,7 +7182,7 @@ function popProvider(context, providerFiber) { context._currentValue = currentValue; } } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { // Update the child lanes of all the ancestors, including the alternates. var node = parent; @@ -7193,14 +7200,23 @@ function scheduleWorkOnParentPath(parent, renderLanes) { !isSubsetOfLanes(alternate.childLanes, renderLanes) ) { alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); - } else { - // Neither alternate was updated, which means the rest of the - // ancestor path already has sufficient priority. + } + + if (node === propagationRoot) { break; } node = node.return; } + + { + if (node !== propagationRoot) { + error( + "Expected to find the propagation root when scheduling context work. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + } } function propagateContextChange(workInProgress, context, renderLanes) { { @@ -7265,7 +7281,11 @@ function propagateContextChange_eager(workInProgress, context, renderLanes) { alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderLanes); // Mark the updated lanes on the list, too. + scheduleContextWorkOnParentPath( + fiber.return, + renderLanes, + workInProgress + ); // Mark the updated lanes on the list, too. list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the // dependency list. @@ -9140,7 +9160,7 @@ function popTreeContext(workInProgress) { } } -var isHydrating = false; +var isHydrating = false; // Hydration errors that were thrown inside this boundary function enterHydrationState(fiber) { { @@ -14081,7 +14101,7 @@ function throwException( // over and traverse parent path again, this time treating the exception // as an error. - renderDidError(); + renderDidError(value); value = createCapturedValue(value, sourceFiber); var workInProgress = returnFiber; @@ -16944,7 +16964,7 @@ function updateSuspenseFallbackChildren( return fallbackChildFragment; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes = mergeLanes(fiber.lanes, renderLanes); var alternate = fiber.alternate; @@ -16952,7 +16972,7 @@ function scheduleWorkOnFiber(fiber, renderLanes) { alternate.lanes = mergeLanes(alternate.lanes, renderLanes); } - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function propagateSuspenseContextChange( @@ -16970,7 +16990,7 @@ function propagateSuspenseContextChange( var state = node.memoizedState; if (state !== null) { - scheduleWorkOnFiber(node, renderLanes); + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); } } else if (node.tag === SuspenseListComponent) { // If the tail is hidden there might not be an Suspense boundaries @@ -16978,7 +16998,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, renderLanes); + scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); } else if (node.child !== null) { node.child.return = node; node = node.child; @@ -18270,6 +18290,16 @@ function safelyDetachRef(current, nearestMountedAncestor) { reportUncaughtErrorInDEV(error); captureCommitPhaseError(current, nearestMountedAncestor, error); } + + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(current) + ); + } + } } else { ref.current = null; } @@ -19051,6 +19081,16 @@ function commitAttachRef(finishedWork) { } else { retVal = ref(instanceToUse); } + + { + if (typeof retVal === "function") { + error( + "Unexpected return value from a callback ref in %s. " + + "A callback ref should not return a function.", + getComponentNameFromFiber(finishedWork) + ); + } + } } else { { if (!ref.hasOwnProperty("current")) { @@ -20486,9 +20526,12 @@ var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). -var workInProgressRootRenderPhaseUpdatedLanes = NoLanes; // Lanes that were pinged (in an interleaved event) during this render. +var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. -var workInProgressRootPingedLanes = NoLanes; // The most recent time we committed a fallback. This lets us ensure a train +var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. +// We will log them once the tree commits. + +var workInProgressRootRecoverableErrors = 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; @@ -20636,11 +20679,6 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { // function), but there are some internal React features that use this as // an implementation detail, like selective hydration. warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase - - workInProgressRootRenderPhaseUpdatedLanes = mergeLanes( - workInProgressRootRenderPhaseUpdatedLanes, - lane - ); } else { // This is a normal update, scheduled from outside the render phase. For // example, during an input event. @@ -21017,30 +21055,34 @@ function recoverFromConcurrentError(root, errorRetryLanes) { } } - var exitStatus; - var MAX_ERROR_RETRY_ATTEMPTS = 50; + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + var exitStatus = renderRootSync(root, errorRetryLanes); - for (var i = 0; i < MAX_ERROR_RETRY_ATTEMPTS; i++) { - exitStatus = renderRootSync(root, errorRetryLanes); - - if ( - exitStatus === RootErrored && - workInProgressRootRenderPhaseUpdatedLanes !== NoLanes - ) { - // There was a render phase update during this render. Some internal React - // implementation details may use this as a trick to schedule another - // render pass. To protect against an inifinite loop, eventually - // we'll give up. - continue; + if (exitStatus !== RootErrored) { + // Successfully finished rendering on retry + if (errorsFromFirstAttempt !== null) { + // The errors from the failed first attempt have been recovered. Add + // them to the collection of recoverable errors. We'll log them in the + // commit phase. + queueRecoverableErrors(errorsFromFirstAttempt); } - - break; } executionContext = prevExecutionContext; return exitStatus; } +function queueRecoverableErrors(errors) { + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootRecoverableErrors = errors; + } else { + workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errors + ); + } +} + function finishConcurrentRender(root, exitStatus, lanes) { switch (exitStatus) { case RootIncomplete: @@ -21054,7 +21096,7 @@ function finishConcurrentRender(root, exitStatus, lanes) { case RootErrored: { // We should have already attempted to retry this tree. If we reached // this point, it errored again. Commit it. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -21094,14 +21136,14 @@ function finishConcurrentRender(root, exitStatus, lanes) { // immediately, wait for more data to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), msUntilTimeout ); break; } } // The work expired. Commit immediately. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -21132,20 +21174,20 @@ function finishConcurrentRender(root, exitStatus, lanes) { // Instead of committing the fallback immediately, wait for more data // to arrive. root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), _msUntilTimeout ); break; } } // Commit the placeholder. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } case RootCompleted: { // The work completed. Ready to commit. - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; } @@ -21276,7 +21318,7 @@ function performSyncWorkOnRoot(root) { 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 + commitRoot(root, workInProgressRootRecoverableErrors); // Before exiting, make sure there's a callback scheduled for the next // pending level. ensureRootIsScheduled(root, now()); @@ -21383,8 +21425,9 @@ function prepareFreshStack(root, lanes) { workInProgressRootFatalError = null; workInProgressRootSkippedLanes = NoLanes; workInProgressRootInterleavedUpdatedLanes = NoLanes; - workInProgressRootRenderPhaseUpdatedLanes = NoLanes; workInProgressRootPingedLanes = NoLanes; + workInProgressRootConcurrentErrors = null; + workInProgressRootRecoverableErrors = null; enqueueInterleavedUpdates(); { @@ -21537,10 +21580,16 @@ function renderDidSuspendDelayIfPossible() { markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); } } -function renderDidError() { +function renderDidError(error) { if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { workInProgressRootExitStatus = RootErrored; } + + if (workInProgressRootConcurrentErrors === null) { + workInProgressRootConcurrentErrors = [error]; + } else { + workInProgressRootConcurrentErrors.push(error); + } } // Called during render to determine if anything has suspended. // Returns false if we're not sure. @@ -21809,7 +21858,7 @@ function completeUnitOfWork(unitOfWork) { } } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { // TODO: This no longer makes any sense. We already wrap the mutation and // layout phases. Should be able to remove. var previousUpdateLanePriority = getCurrentUpdatePriority(); @@ -21818,7 +21867,7 @@ function commitRoot(root) { try { ReactCurrentBatchConfig$2.transition = 0; setCurrentUpdatePriority(DiscreteEventPriority); - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { ReactCurrentBatchConfig$2.transition = prevTransition; setCurrentUpdatePriority(previousUpdateLanePriority); @@ -21827,7 +21876,7 @@ function commitRoot(root) { return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do { // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which // means `flushPassiveEffects` will sometimes result in additional @@ -22032,6 +22081,19 @@ function commitRootImpl(root, renderPriorityLevel) { ensureRootIsScheduled(root, now()); + if (recoverableErrors !== null) { + // There were errors during this render, but recovered from them without + // needing to surface it to the UI. We log them here. + for (var i = 0; i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + var onRecoverableError = root.onRecoverableError; + + if (onRecoverableError !== null) { + onRecoverableError(recoverableError); + } + } + } + if (hasUncaughtError) { hasUncaughtError = false; var error$1 = firstUncaughtError; @@ -23855,7 +23917,13 @@ function assignFiberPropertiesInDEV(target, source) { return target; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.pendingChildren = null; @@ -23879,6 +23947,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = NoLanes; this.entanglements = createLaneMap(NoLanes); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; { this.effectDuration = 0; @@ -23913,10 +23982,20 @@ function createFiberRoot( hydrate, hydrationCallbacks, isStrictMode, - concurrentUpdatesByDefaultOverride, - identifierPrefix + concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the + // host config, but because they are passed in at runtime, we have to thread + // them through the root constructor. Perhaps we should put them all into a + // single type, like a DynamicHostConfig that is defined by the renderer. + identifierPrefix, + onRecoverableError ) { - var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix); + var root = new FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError + ); // stateNode is any. var uninitializedFiber = createHostRootFiber( @@ -23938,7 +24017,7 @@ function createFiberRoot( return root; } -var ReactVersion = "18.0.0-rc.0-51947a14b-20220113"; +var ReactVersion = "18.0.0-rc.0-a3bde7974-20220208"; function createPortal( children, @@ -24066,7 +24145,8 @@ function createContainer( hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, - identifierPrefix + identifierPrefix, + onRecoverableError ) { return createFiberRoot( containerInfo, @@ -24075,7 +24155,8 @@ function createContainer( hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, - identifierPrefix + identifierPrefix, + onRecoverableError ); } function updateContainer(element, container, parentComponent, callback) { @@ -24861,7 +24942,8 @@ function render(element, containerTag, callback) { null, false, null, - "" + "", + null ); roots.set(containerTag, root); } diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js index 34c20b44f2..2087079f42 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<74ace7caaea78f5e62bae1f9669d8351>> */ "use strict"; @@ -926,7 +926,7 @@ eventPluginOrder = Array.prototype.slice.call([ "ReactNativeBridgeEventPlugin" ]); recomputePluginOrdering(); -var injectedNamesToPlugins$jscomp$inline_223 = { +var injectedNamesToPlugins$jscomp$inline_222 = { ResponderEventPlugin: ResponderEventPlugin, ReactNativeBridgeEventPlugin: { eventTypes: {}, @@ -961,33 +961,33 @@ var injectedNamesToPlugins$jscomp$inline_223 = { } } }, - isOrderingDirty$jscomp$inline_224 = !1, - pluginName$jscomp$inline_225; -for (pluginName$jscomp$inline_225 in injectedNamesToPlugins$jscomp$inline_223) + isOrderingDirty$jscomp$inline_223 = !1, + pluginName$jscomp$inline_224; +for (pluginName$jscomp$inline_224 in injectedNamesToPlugins$jscomp$inline_222) if ( - injectedNamesToPlugins$jscomp$inline_223.hasOwnProperty( - pluginName$jscomp$inline_225 + injectedNamesToPlugins$jscomp$inline_222.hasOwnProperty( + pluginName$jscomp$inline_224 ) ) { - var pluginModule$jscomp$inline_226 = - injectedNamesToPlugins$jscomp$inline_223[pluginName$jscomp$inline_225]; + var pluginModule$jscomp$inline_225 = + injectedNamesToPlugins$jscomp$inline_222[pluginName$jscomp$inline_224]; if ( - !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_225) || - namesToPlugins[pluginName$jscomp$inline_225] !== - pluginModule$jscomp$inline_226 + !namesToPlugins.hasOwnProperty(pluginName$jscomp$inline_224) || + namesToPlugins[pluginName$jscomp$inline_224] !== + pluginModule$jscomp$inline_225 ) { - if (namesToPlugins[pluginName$jscomp$inline_225]) + if (namesToPlugins[pluginName$jscomp$inline_224]) throw Error( "EventPluginRegistry: Cannot inject two different event plugins using the same name, `" + - (pluginName$jscomp$inline_225 + "`.") + (pluginName$jscomp$inline_224 + "`.") ); namesToPlugins[ - pluginName$jscomp$inline_225 - ] = pluginModule$jscomp$inline_226; - isOrderingDirty$jscomp$inline_224 = !0; + pluginName$jscomp$inline_224 + ] = pluginModule$jscomp$inline_225; + isOrderingDirty$jscomp$inline_223 = !0; } } -isOrderingDirty$jscomp$inline_224 && recomputePluginOrdering(); +isOrderingDirty$jscomp$inline_223 && recomputePluginOrdering(); var instanceCache = new Map(), instanceProps = new Map(); function getInstanceFromTag(tag) { @@ -1697,12 +1697,6 @@ function onCommitRoot(root) { ); } catch (err) {} } -function injectProfilingHooks() {} -function getLaneLabelMap() { - for (var map = new Map(), lane = 1, index$4 = 0; 31 > index$4; index$4++) - map.set(lane, void 0), (lane *= 2); - return map; -} var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log = Math.log, LN2 = Math.LN2; @@ -1875,21 +1869,21 @@ function markRootFinished(root, remainingLanes) { remainingLanes = root.entanglements; var eventTimes = root.eventTimes; for (root = root.expirationTimes; 0 < noLongerPendingLanes; ) { - var index$9 = 31 - clz32(noLongerPendingLanes), - lane = 1 << index$9; - remainingLanes[index$9] = 0; - eventTimes[index$9] = -1; - root[index$9] = -1; + var index$8 = 31 - clz32(noLongerPendingLanes), + lane = 1 << index$8; + remainingLanes[index$8] = 0; + eventTimes[index$8] = -1; + root[index$8] = -1; noLongerPendingLanes &= ~lane; } } function markRootEntangled(root, entangledLanes) { var rootEntangledLanes = (root.entangledLanes |= entangledLanes); for (root = root.entanglements; rootEntangledLanes; ) { - var index$10 = 31 - clz32(rootEntangledLanes), - lane = 1 << index$10; - (lane & entangledLanes) | (root[index$10] & entangledLanes) && - (root[index$10] |= entangledLanes); + var index$9 = 31 - clz32(rootEntangledLanes), + lane = 1 << index$9; + (lane & entangledLanes) | (root[index$9] & entangledLanes) && + (root[index$9] |= entangledLanes); rootEntangledLanes &= ~lane; } } @@ -2161,19 +2155,16 @@ function popProvider(context) { pop(valueCursor); context._currentValue = currentValue; } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { for (; null !== parent; ) { var alternate = parent.alternate; - 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.childLanes & renderLanes) !== renderLanes + ? ((parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes)) + : null !== alternate && + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); + if (parent === propagationRoot) break; parent = parent.return; } } @@ -3642,28 +3633,37 @@ function updateMutableSource(source, getSnapshot, subscribe) { var hook = updateWorkInProgressHook(); return useMutableSource(hook, source, getSnapshot, subscribe); } -function mountSyncExternalStore(subscribe, getSnapshot) { +function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, - hook = mountWorkInProgressHook(); - var nextSnapshot = getSnapshot(); - var root = workInProgressRoot; - if (null === root) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + hook = updateWorkInProgressHook(), + nextSnapshot = getSnapshot(), + snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); + snapshotChanged && + ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); + hook = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ + subscribe + ]); + if ( + hook.getSnapshot !== getSnapshot || + snapshotChanged || + (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1) + ) { + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, hook, nextSnapshot, getSnapshot), + void 0, + null ); - includesBlockingLane(root, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - hook.memoizedState = nextSnapshot; - root = { value: nextSnapshot, getSnapshot: getSnapshot }; - hook.queue = root; - mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [subscribe]); - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), - void 0, - null - ); + subscribe = workInProgressRoot; + if (null === subscribe) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(subscribe, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } return nextSnapshot; } function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { @@ -4051,7 +4051,32 @@ var ContextOnlyDispatcher = { }; return useMutableSource(hook, source, getSnapshot, subscribe); }, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: function(subscribe, getSnapshot) { + var fiber = currentlyRenderingFiber$1, + hook = mountWorkInProgressHook(); + var nextSnapshot = getSnapshot(); + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(root, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + hook.memoizedState = nextSnapshot; + root = { value: nextSnapshot, getSnapshot: getSnapshot }; + hook.queue = root; + mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [ + subscribe + ]); + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), + void 0, + null + ); + return nextSnapshot; + }, useId: function() { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, @@ -4100,46 +4125,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: function(subscribe, getSnapshot) { - var fiber = currentlyRenderingFiber$1, - hook = updateWorkInProgressHook(), - nextSnapshot = getSnapshot(), - snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); - snapshotChanged && - ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); - hook = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ - subscribe - ]); - if ( - hook.getSnapshot !== getSnapshot || - snapshotChanged || - (null !== workInProgressHook && - workInProgressHook.memoizedState.tag & 1) - ) { - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind( - null, - fiber, - hook, - nextSnapshot, - getSnapshot - ), - void 0, - null - ); - subscribe = workInProgressRoot; - if (null === subscribe) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - includesBlockingLane(subscribe, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - return nextSnapshot; - }, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -4182,7 +4168,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }; @@ -4298,14 +4284,14 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { break; case "collapsed": lastTailNode = renderState.tail; - for (var lastTailNode$36 = null; null !== lastTailNode; ) - null !== lastTailNode.alternate && (lastTailNode$36 = lastTailNode), + for (var lastTailNode$35 = null; null !== lastTailNode; ) + null !== lastTailNode.alternate && (lastTailNode$35 = lastTailNode), (lastTailNode = lastTailNode.sibling); - null === lastTailNode$36 + null === lastTailNode$35 ? hasRenderedATailFallback || null === renderState.tail ? (renderState.tail = null) : (renderState.tail.sibling = null) - : (lastTailNode$36.sibling = null); + : (lastTailNode$35.sibling = null); } } function bubbleProperties(completedWork) { @@ -4315,19 +4301,19 @@ function bubbleProperties(completedWork) { newChildLanes = 0, subtreeFlags = 0; if (didBailout) - for (var child$37 = completedWork.child; null !== child$37; ) - (newChildLanes |= child$37.lanes | child$37.childLanes), - (subtreeFlags |= child$37.subtreeFlags & 14680064), - (subtreeFlags |= child$37.flags & 14680064), - (child$37.return = completedWork), - (child$37 = child$37.sibling); + for (var child$36 = completedWork.child; null !== child$36; ) + (newChildLanes |= child$36.lanes | child$36.childLanes), + (subtreeFlags |= child$36.subtreeFlags & 14680064), + (subtreeFlags |= child$36.flags & 14680064), + (child$36.return = completedWork), + (child$36 = child$36.sibling); else - for (child$37 = completedWork.child; null !== child$37; ) - (newChildLanes |= child$37.lanes | child$37.childLanes), - (subtreeFlags |= child$37.subtreeFlags), - (subtreeFlags |= child$37.flags), - (child$37.return = completedWork), - (child$37 = child$37.sibling); + for (child$36 = completedWork.child; null !== child$36; ) + (newChildLanes |= child$36.lanes | child$36.childLanes), + (subtreeFlags |= child$36.subtreeFlags), + (subtreeFlags |= child$36.flags), + (child$36.return = completedWork), + (child$36 = child$36.sibling); completedWork.subtreeFlags |= subtreeFlags; completedWork.childLanes = newChildLanes; return didBailout; @@ -5321,11 +5307,11 @@ function updateSuspenseFallbackChildren( workInProgress.child = primaryChildren; return fallbackChildren; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; var alternate = fiber.alternate; null !== alternate && (alternate.lanes |= renderLanes); - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function initSuspenseListRenderState( workInProgress, @@ -5364,8 +5350,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderLanes); - else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); + else if (19 === current.tag) + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -5679,8 +5666,8 @@ function commitHookEffectListMount(flags, finishedWork) { var effect = (finishedWork = finishedWork.next); do { if ((effect.tag & flags) === flags) { - var create$81 = effect.create; - effect.destroy = create$81(); + var create$80 = effect.create; + effect.destroy = create$80(); } effect = effect.next; } while (effect !== finishedWork); @@ -6130,8 +6117,8 @@ function commitMutationEffects(root, firstChild) { switch (firstChild.tag) { case 13: if (null !== firstChild.memoizedState) { - var current$86 = firstChild.alternate; - if (null === current$86 || null === current$86.memoizedState) + var current$85 = firstChild.alternate; + if (null === current$85 || null === current$85.memoizedState) globalMostRecentFallbackTime = now(); } break; @@ -6282,8 +6269,8 @@ function commitLayoutEffects(finishedWork) { commitUpdateQueue(firstChild, updateQueue, instance); break; case 3: - var updateQueue$82 = firstChild.updateQueue; - if (null !== updateQueue$82) { + var updateQueue$81 = firstChild.updateQueue; + if (null !== updateQueue$81) { current = null; if (null !== firstChild.child) switch (firstChild.child.tag) { @@ -6293,7 +6280,7 @@ function commitLayoutEffects(finishedWork) { case 1: current = firstChild.child.stateNode; } - commitUpdateQueue(firstChild, updateQueue$82, current); + commitUpdateQueue(firstChild, updateQueue$81, current); } break; case 5: @@ -6366,8 +6353,9 @@ var ceil = Math.ceil, workInProgressRootFatalError = null, workInProgressRootSkippedLanes = 0, workInProgressRootInterleavedUpdatedLanes = 0, - workInProgressRootRenderPhaseUpdatedLanes = 0, workInProgressRootPingedLanes = 0, + workInProgressRootConcurrentErrors = null, + workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, hasUncaughtError = !1, @@ -6413,19 +6401,18 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (null === root) return null; markRootUpdated(root, lane, eventTime); - 0 !== (executionContext & 2) && root === workInProgressRoot - ? (workInProgressRootRenderPhaseUpdatedLanes |= lane) - : (root === workInProgressRoot && - (0 === (executionContext & 2) && - (workInProgressRootInterleavedUpdatedLanes |= lane), - 4 === workInProgressRootExitStatus && - markRootSuspended$1(root, workInProgressRootRenderLanes)), + if (0 === (executionContext & 2) || root !== workInProgressRoot) + root === workInProgressRoot && + (0 === (executionContext & 2) && + (workInProgressRootInterleavedUpdatedLanes |= lane), + 4 === workInProgressRootExitStatus && + markRootSuspended$1(root, workInProgressRootRenderLanes)), ensureRootIsScheduled(root, eventTime), 1 === lane && 0 === executionContext && 0 === (fiber.mode & 1) && ((workInProgressRootRenderTargetTime = now() + 500), - includesLegacySyncCallbacks && flushSyncCallbacks())); + includesLegacySyncCallbacks && flushSyncCallbacks()); return root; } function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { @@ -6451,12 +6438,12 @@ function ensureRootIsScheduled(root, currentTime) { 0 < lanes; ) { - var index$7 = 31 - clz32(lanes), - lane = 1 << index$7, - expirationTime = expirationTimes[index$7]; + var index$6 = 31 - clz32(lanes), + lane = 1 << index$6, + expirationTime = expirationTimes[index$6]; if (-1 === expirationTime) { if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes)) - expirationTimes[index$7] = computeExpirationTime(lane, currentTime); + expirationTimes[index$6] = computeExpirationTime(lane, currentTime); } else expirationTime <= currentTime && (root.expiredLanes |= lane); lanes &= ~lane; } @@ -6596,7 +6583,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 3: markRootSuspended$1(root, lanes); @@ -6613,22 +6600,22 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), didTimeout ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 4: markRootSuspended$1(root, lanes); if ((lanes & 4194240) === lanes) break; didTimeout = root.eventTimes; for (prevExecutionContext = -1; 0 < lanes; ) { - var index$6 = 31 - clz32(lanes); - prevDispatcher = 1 << index$6; - index$6 = didTimeout[index$6]; - index$6 > prevExecutionContext && (prevExecutionContext = index$6); + var index$5 = 31 - clz32(lanes); + prevDispatcher = 1 << index$5; + index$5 = didTimeout[index$5]; + index$5 > prevExecutionContext && (prevExecutionContext = index$5); lanes &= ~prevDispatcher; } lanes = prevExecutionContext; @@ -6649,15 +6636,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), lanes ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 5: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; default: throw Error("Unknown root exit status."); @@ -6672,15 +6659,18 @@ function recoverFromConcurrentError(root, errorRetryLanes) { var prevExecutionContext = executionContext; executionContext |= 8; root.isDehydrated && (root.isDehydrated = !1); - for ( - var exitStatus, i = 0; - 50 > i && - ((exitStatus = renderRootSync(root, errorRetryLanes)), - 2 === exitStatus && 0 !== workInProgressRootRenderPhaseUpdatedLanes); - i++ - ); + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + root = renderRootSync(root, errorRetryLanes); + 2 !== root && + null !== errorsFromFirstAttempt && + (null === workInProgressRootConcurrentErrors + ? (workInProgressRootRecoverableErrors = errorsFromFirstAttempt) + : (workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errorsFromFirstAttempt + ))); executionContext = prevExecutionContext; - return exitStatus; + return root; } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -6722,9 +6712,9 @@ function markRootSuspended$1(root, suspendedLanes) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; for (root = root.expirationTimes; 0 < suspendedLanes; ) { - var index$8 = 31 - clz32(suspendedLanes), - lane = 1 << index$8; - root[index$8] = -1; + var index$7 = 31 - clz32(suspendedLanes), + lane = 1 << index$7; + root[index$7] = -1; suspendedLanes &= ~lane; } } @@ -6749,7 +6739,7 @@ function performSyncWorkOnRoot(root) { exitStatus); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); ensureRootIsScheduled(root, now()); return null; } @@ -6806,7 +6796,8 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootPingedLanes = workInProgressRootRenderPhaseUpdatedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootPingedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors = null; if (null !== interleavedQueues) { for (root = 0; root < interleavedQueues.length; root++) if ( @@ -6960,8 +6951,12 @@ function handleError(root$jscomp$0, thrownValue) { " 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." ); } + root = value; 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [root]) + : workInProgressRootConcurrentErrors.push(root); value = createCapturedValue(value, sourceFiber); root = returnFiber; do { @@ -6993,12 +6988,12 @@ function handleError(root$jscomp$0, thrownValue) { root.flags |= 65536; thrownValue &= -thrownValue; root.lanes |= thrownValue; - var update$34 = createClassErrorUpdate( + var update$33 = createClassErrorUpdate( root, wakeable, thrownValue ); - enqueueCapturedUpdate(root, update$34); + enqueueCapturedUpdate(root, update$33); break a; } } @@ -7093,20 +7088,20 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = 0), (currentUpdatePriority = 1), - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) @@ -7161,6 +7156,15 @@ function commitRootImpl(root, renderPriorityLevel) { 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null); onCommitRoot(finishedWork.stateNode, renderPriorityLevel); ensureRootIsScheduled(root, now()); + if (null !== recoverableErrors) + for ( + renderPriorityLevel = 0; + renderPriorityLevel < recoverableErrors.length; + renderPriorityLevel++ + ) + (finishedWork = recoverableErrors[renderPriorityLevel]), + (lanes = root.onRecoverableError), + null !== lanes && lanes(finishedWork); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -7733,7 +7737,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { newValue.lanes |= renderLanes; dependency = newValue.alternate; null !== dependency && (dependency.lanes |= renderLanes); - scheduleWorkOnParentPath(newValue.return, renderLanes); + scheduleContextWorkOnParentPath( + newValue.return, + renderLanes, + workInProgress + ); list.lanes |= renderLanes; break; } @@ -8031,7 +8039,13 @@ function createFiberFromPortal(portal, mode, lanes) { }; return mode; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; @@ -8045,6 +8059,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; this.entanglements = createLaneMap(0); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; } function createPortal(children, containerInfo, implementation) { var key = @@ -8255,10 +8270,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_967 = { + devToolsConfig$jscomp$inline_968 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-rc.0-51947a14b-20220113", + version: "18.0.0-rc.0-a3bde7974-20220208", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8273,11 +8288,11 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1230 = { - bundleType: devToolsConfig$jscomp$inline_967.bundleType, - version: devToolsConfig$jscomp$inline_967.version, - rendererPackageName: devToolsConfig$jscomp$inline_967.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_967.rendererConfig, +var internals$jscomp$inline_1232 = { + bundleType: devToolsConfig$jscomp$inline_968.bundleType, + version: devToolsConfig$jscomp$inline_968.version, + rendererPackageName: devToolsConfig$jscomp$inline_968.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_968.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8293,29 +8308,26 @@ var internals$jscomp$inline_1230 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_967.findFiberByHostInstance || + devToolsConfig$jscomp$inline_968.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-rc.0-51947a14b-20220113" + reconcilerVersion: "18.0.0-rc.0-a3bde7974-20220208" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1231 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + var hook$jscomp$inline_1233 = __REACT_DEVTOOLS_GLOBAL_HOOK__; if ( - !hook$jscomp$inline_1231.isDisabled && - hook$jscomp$inline_1231.supportsFiber + !hook$jscomp$inline_1233.isDisabled && + hook$jscomp$inline_1233.supportsFiber ) try { - (rendererID = hook$jscomp$inline_1231.inject( - Object.assign({}, internals$jscomp$inline_1230, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }) + (rendererID = hook$jscomp$inline_1233.inject( + internals$jscomp$inline_1232 )), - (injectedHook = hook$jscomp$inline_1231); + (injectedHook = hook$jscomp$inline_1233); } catch (err) {} } exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { @@ -8361,7 +8373,7 @@ exports.findNodeHandle = findNodeHandle; exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { - root = new FiberRootNode(containerTag, 0, !1, ""); + root = new FiberRootNode(containerTag, 0, !1, "", null); var JSCompiler_inline_result = createFiber(3, null, null, 0); root.current = JSCompiler_inline_result; JSCompiler_inline_result.stateNode = root; diff --git a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js index f9734c0a95..ec6c578705 100644 --- a/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +++ b/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js @@ -7,7 +7,7 @@ * @noflow * @nolint * @preventMunge - * @generated SignedSource<> + * @generated SignedSource<<6fb23e3f27b69a5703944d58969d32f4>> */ @@ -2282,19 +2282,16 @@ function popProvider(context) { pop(valueCursor); context._currentValue = currentValue; } -function scheduleWorkOnParentPath(parent, renderLanes) { +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { for (; null !== parent; ) { var alternate = parent.alternate; - 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.childLanes & renderLanes) !== renderLanes + ? ((parent.childLanes |= renderLanes), + null !== alternate && (alternate.childLanes |= renderLanes)) + : null !== alternate && + (alternate.childLanes & renderLanes) !== renderLanes && + (alternate.childLanes |= renderLanes); + if (parent === propagationRoot) break; parent = parent.return; } } @@ -3768,28 +3765,37 @@ function updateMutableSource(source, getSnapshot, subscribe) { var hook = updateWorkInProgressHook(); return useMutableSource(hook, source, getSnapshot, subscribe); } -function mountSyncExternalStore(subscribe, getSnapshot) { +function updateSyncExternalStore(subscribe, getSnapshot) { var fiber = currentlyRenderingFiber$1, - hook = mountWorkInProgressHook(); - var nextSnapshot = getSnapshot(); - var root = workInProgressRoot; - if (null === root) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." + hook = updateWorkInProgressHook(), + nextSnapshot = getSnapshot(), + snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); + snapshotChanged && + ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); + hook = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ + subscribe + ]); + if ( + hook.getSnapshot !== getSnapshot || + snapshotChanged || + (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1) + ) { + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, hook, nextSnapshot, getSnapshot), + void 0, + null ); - includesBlockingLane(root, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - hook.memoizedState = nextSnapshot; - root = { value: nextSnapshot, getSnapshot: getSnapshot }; - hook.queue = root; - mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [subscribe]); - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), - void 0, - null - ); + subscribe = workInProgressRoot; + if (null === subscribe) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(subscribe, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + } return nextSnapshot; } function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { @@ -4179,7 +4185,32 @@ var ContextOnlyDispatcher = { }; return useMutableSource(hook, source, getSnapshot, subscribe); }, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: function(subscribe, getSnapshot) { + var fiber = currentlyRenderingFiber$1, + hook = mountWorkInProgressHook(); + var nextSnapshot = getSnapshot(); + var root = workInProgressRoot; + if (null === root) + throw Error( + "Expected a work-in-progress root. This is a bug in React. Please file an issue." + ); + includesBlockingLane(root, renderLanes) || + pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); + hook.memoizedState = nextSnapshot; + root = { value: nextSnapshot, getSnapshot: getSnapshot }; + hook.queue = root; + mountEffect(subscribeToStore.bind(null, fiber, root, subscribe), [ + subscribe + ]); + fiber.flags |= 2048; + pushEffect( + 9, + updateStoreInstance.bind(null, fiber, root, nextSnapshot, getSnapshot), + void 0, + null + ); + return nextSnapshot; + }, useId: function() { var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix, @@ -4228,46 +4259,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: function(subscribe, getSnapshot) { - var fiber = currentlyRenderingFiber$1, - hook = updateWorkInProgressHook(), - nextSnapshot = getSnapshot(), - snapshotChanged = !objectIs(hook.memoizedState, nextSnapshot); - snapshotChanged && - ((hook.memoizedState = nextSnapshot), (didReceiveUpdate = !0)); - hook = hook.queue; - updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ - subscribe - ]); - if ( - hook.getSnapshot !== getSnapshot || - snapshotChanged || - (null !== workInProgressHook && - workInProgressHook.memoizedState.tag & 1) - ) { - fiber.flags |= 2048; - pushEffect( - 9, - updateStoreInstance.bind( - null, - fiber, - hook, - nextSnapshot, - getSnapshot - ), - void 0, - null - ); - subscribe = workInProgressRoot; - if (null === subscribe) - throw Error( - "Expected a work-in-progress root. This is a bug in React. Please file an issue." - ); - includesBlockingLane(subscribe, renderLanes) || - pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); - } - return nextSnapshot; - }, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -4310,7 +4302,7 @@ var ContextOnlyDispatcher = { return [isPending, start]; }, useMutableSource: updateMutableSource, - useSyncExternalStore: mountSyncExternalStore, + useSyncExternalStore: updateSyncExternalStore, useId: updateId, unstable_isNewReconciler: !1 }, @@ -5577,11 +5569,11 @@ function updateSuspenseFallbackChildren( workInProgress.child = primaryChildren; return fallbackChildren; } -function scheduleWorkOnFiber(fiber, renderLanes) { +function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { fiber.lanes |= renderLanes; var alternate = fiber.alternate; null !== alternate && (alternate.lanes |= renderLanes); - scheduleWorkOnParentPath(fiber.return, renderLanes); + scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); } function initSuspenseListRenderState( workInProgress, @@ -5620,8 +5612,9 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) { a: for (current = workInProgress.child; null !== current; ) { if (13 === current.tag) null !== current.memoizedState && - scheduleWorkOnFiber(current, renderLanes); - else if (19 === current.tag) scheduleWorkOnFiber(current, renderLanes); + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); + else if (19 === current.tag) + scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress); else if (null !== current.child) { current.child.return = current; current = current.child; @@ -6806,8 +6799,9 @@ var ceil = Math.ceil, workInProgressRootFatalError = null, workInProgressRootSkippedLanes = 0, workInProgressRootInterleavedUpdatedLanes = 0, - workInProgressRootRenderPhaseUpdatedLanes = 0, workInProgressRootPingedLanes = 0, + workInProgressRootConcurrentErrors = null, + workInProgressRootRecoverableErrors = null, globalMostRecentFallbackTime = 0, workInProgressRootRenderTargetTime = Infinity, hasUncaughtError = !1, @@ -6854,9 +6848,8 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); if (null === root) return null; markRootUpdated(root, lane, eventTime); - 0 !== (executionContext & 2) && root === workInProgressRoot - ? (workInProgressRootRenderPhaseUpdatedLanes |= lane) - : (isDevToolsPresent && addFiberToLanesMap(root, fiber, lane), + if (0 === (executionContext & 2) || root !== workInProgressRoot) + isDevToolsPresent && addFiberToLanesMap(root, fiber, lane), root === workInProgressRoot && (0 === (executionContext & 2) && (workInProgressRootInterleavedUpdatedLanes |= lane), @@ -6867,7 +6860,7 @@ function scheduleUpdateOnFiber(fiber, lane, eventTime) { 0 === executionContext && 0 === (fiber.mode & 1) && ((workInProgressRootRenderTargetTime = now() + 500), - includesLegacySyncCallbacks && flushSyncCallbacks())); + includesLegacySyncCallbacks && flushSyncCallbacks()); return root; } function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { @@ -7052,7 +7045,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) { case 1: throw Error("Root did not complete. This is a bug in React."); case 2: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 3: markRootSuspended$1(root, lanes); @@ -7069,12 +7062,12 @@ function performConcurrentWorkOnRoot(root, didTimeout) { break; } root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), didTimeout ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 4: markRootSuspended$1(root, lanes); @@ -7105,15 +7098,15 @@ function performConcurrentWorkOnRoot(root, didTimeout) { : 1960 * ceil(lanes / 1960)) - lanes; if (10 < lanes) { root.timeoutHandle = scheduleTimeout( - commitRoot.bind(null, root), + commitRoot.bind(null, root, workInProgressRootRecoverableErrors), lanes ); break; } - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; case 5: - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); break; default: throw Error("Unknown root exit status."); @@ -7128,15 +7121,18 @@ function recoverFromConcurrentError(root, errorRetryLanes) { var prevExecutionContext = executionContext; executionContext |= 8; root.isDehydrated && (root.isDehydrated = !1); - for ( - var exitStatus, i = 0; - 50 > i && - ((exitStatus = renderRootSync(root, errorRetryLanes)), - 2 === exitStatus && 0 !== workInProgressRootRenderPhaseUpdatedLanes); - i++ - ); + var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; + root = renderRootSync(root, errorRetryLanes); + 2 !== root && + null !== errorsFromFirstAttempt && + (null === workInProgressRootConcurrentErrors + ? (workInProgressRootRecoverableErrors = errorsFromFirstAttempt) + : (workInProgressRootConcurrentErrors = workInProgressRootConcurrentErrors.push.apply( + null, + errorsFromFirstAttempt + ))); executionContext = prevExecutionContext; - return exitStatus; + return root; } function isRenderConsistentWithExternalStores(finishedWork) { for (var node = finishedWork; ; ) { @@ -7207,7 +7203,7 @@ function performSyncWorkOnRoot(root) { exitStatus); root.finishedWork = root.current.alternate; root.finishedLanes = lanes; - commitRoot(root); + commitRoot(root, workInProgressRootRecoverableErrors); ensureRootIsScheduled(root, now()); return null; } @@ -7264,7 +7260,8 @@ function prepareFreshStack(root, lanes) { workInProgressRootRenderLanes = subtreeRenderLanes = lanes; workInProgressRootExitStatus = 0; workInProgressRootFatalError = null; - workInProgressRootPingedLanes = workInProgressRootRenderPhaseUpdatedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootPingedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = 0; + workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors = null; if (null !== interleavedQueues) { for (root = 0; root < interleavedQueues.length; root++) if ( @@ -7445,8 +7442,12 @@ function handleError(root, thrownValue) { " 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." ); } + wakeable = value; 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2); + null === workInProgressRootConcurrentErrors + ? (workInProgressRootConcurrentErrors = [wakeable]) + : workInProgressRootConcurrentErrors.push(wakeable); value = createCapturedValue(value, sourceFiber); wakeable = returnFiber; do { @@ -7609,20 +7610,20 @@ function completeUnitOfWork(unitOfWork) { } while (null !== completedWork); 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5); } -function commitRoot(root) { +function commitRoot(root, recoverableErrors) { var previousUpdateLanePriority = currentUpdatePriority, prevTransition = ReactCurrentBatchConfig$2.transition; try { (ReactCurrentBatchConfig$2.transition = 0), (currentUpdatePriority = 1), - commitRootImpl(root, previousUpdateLanePriority); + commitRootImpl(root, recoverableErrors, previousUpdateLanePriority); } finally { (ReactCurrentBatchConfig$2.transition = prevTransition), (currentUpdatePriority = previousUpdateLanePriority); } return null; } -function commitRootImpl(root, renderPriorityLevel) { +function commitRootImpl(root, recoverableErrors, renderPriorityLevel) { do flushPassiveEffects(); while (null !== rootWithPendingPassiveEffects); if (0 !== (executionContext & 6)) @@ -7688,6 +7689,15 @@ function commitRootImpl(root, renderPriorityLevel) { onCommitRoot(finishedWork.stateNode, renderPriorityLevel); isDevToolsPresent && root.memoizedUpdaters.clear(); ensureRootIsScheduled(root, now()); + if (null !== recoverableErrors) + for ( + renderPriorityLevel = 0; + renderPriorityLevel < recoverableErrors.length; + renderPriorityLevel++ + ) + (finishedWork = recoverableErrors[renderPriorityLevel]), + (lanes = root.onRecoverableError), + null !== lanes && lanes(finishedWork); if (hasUncaughtError) throw ((hasUncaughtError = !1), (root = firstUncaughtError), @@ -8342,7 +8352,11 @@ beginWork$1 = function(current, workInProgress, renderLanes) { newValue.lanes |= renderLanes; dependency = newValue.alternate; null !== dependency && (dependency.lanes |= renderLanes); - scheduleWorkOnParentPath(newValue.return, renderLanes); + scheduleContextWorkOnParentPath( + newValue.return, + renderLanes, + workInProgress + ); list.lanes |= renderLanes; break; } @@ -8656,7 +8670,13 @@ function createFiberFromPortal(portal, mode, lanes) { }; return mode; } -function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { +function FiberRootNode( + containerInfo, + tag, + hydrate, + identifierPrefix, + onRecoverableError +) { this.tag = tag; this.containerInfo = containerInfo; this.finishedWork = this.pingCache = this.current = this.pendingChildren = null; @@ -8670,6 +8690,7 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) { this.entangledLanes = this.finishedLanes = this.mutableReadLanes = this.expiredLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; this.entanglements = createLaneMap(0); this.identifierPrefix = identifierPrefix; + this.onRecoverableError = onRecoverableError; this.passiveEffectDuration = this.effectDuration = 0; this.memoizedUpdaters = new Set(); containerInfo = this.pendingUpdatersLaneMap = []; @@ -8887,10 +8908,10 @@ batchedUpdatesImpl = function(fn, a) { } }; var roots = new Map(), - devToolsConfig$jscomp$inline_1043 = { + devToolsConfig$jscomp$inline_1045 = { findFiberByHostInstance: getInstanceFromTag, bundleType: 0, - version: "18.0.0-rc.0-51947a14b-20220113", + version: "18.0.0-rc.0-a3bde7974-20220208", rendererPackageName: "react-native-renderer", rendererConfig: { getInspectorDataForViewTag: function() { @@ -8905,11 +8926,24 @@ var roots = new Map(), }.bind(null, findNodeHandle) } }; -var internals$jscomp$inline_1330 = { - bundleType: devToolsConfig$jscomp$inline_1043.bundleType, - version: devToolsConfig$jscomp$inline_1043.version, - rendererPackageName: devToolsConfig$jscomp$inline_1043.rendererPackageName, - rendererConfig: devToolsConfig$jscomp$inline_1043.rendererConfig, +(function(internals) { + if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) return !1; + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled || !hook.supportsFiber) return !0; + try { + (internals = Object.assign({}, internals, { + getLaneLabelMap: getLaneLabelMap, + injectProfilingHooks: injectProfilingHooks + })), + (rendererID = hook.inject(internals)), + (injectedHook = hook); + } catch (err) {} + return hook.checkDCE ? !0 : !1; +})({ + bundleType: devToolsConfig$jscomp$inline_1045.bundleType, + version: devToolsConfig$jscomp$inline_1045.version, + rendererPackageName: devToolsConfig$jscomp$inline_1045.rendererPackageName, + rendererConfig: devToolsConfig$jscomp$inline_1045.rendererConfig, overrideHookState: null, overrideHookStateDeletePath: null, overrideHookStateRenamePath: null, @@ -8925,31 +8959,15 @@ var internals$jscomp$inline_1330 = { return null === fiber ? null : fiber.stateNode; }, findFiberByHostInstance: - devToolsConfig$jscomp$inline_1043.findFiberByHostInstance || + devToolsConfig$jscomp$inline_1045.findFiberByHostInstance || emptyFindFiberByHostInstance, findHostInstancesForRefresh: null, scheduleRefresh: null, scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.0.0-rc.0-51947a14b-20220113" -}; -if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { - var hook$jscomp$inline_1331 = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if ( - !hook$jscomp$inline_1331.isDisabled && - hook$jscomp$inline_1331.supportsFiber - ) - try { - (rendererID = hook$jscomp$inline_1331.inject( - Object.assign({}, internals$jscomp$inline_1330, { - getLaneLabelMap: getLaneLabelMap, - injectProfilingHooks: injectProfilingHooks - }) - )), - (injectedHook = hook$jscomp$inline_1331); - } catch (err) {} -} + reconcilerVersion: "18.0.0-rc.0-a3bde7974-20220208" +}); exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = { computeComponentStackForErrorReporting: function(reactTag) { return (reactTag = getInstanceFromTag(reactTag)) @@ -8993,7 +9011,7 @@ exports.findNodeHandle = findNodeHandle; exports.render = function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { - root = new FiberRootNode(containerTag, 0, !1, ""); + root = new FiberRootNode(containerTag, 0, !1, "", null); var JSCompiler_inline_result = 0; isDevToolsPresent && (JSCompiler_inline_result |= 2); JSCompiler_inline_result = createFiber( diff --git a/Libraries/StyleSheet/__tests__/normalizeColor-test.js b/Libraries/StyleSheet/__tests__/normalizeColor-test.js index f102511f87..244fff9c38 100644 --- a/Libraries/StyleSheet/__tests__/normalizeColor-test.js +++ b/Libraries/StyleSheet/__tests__/normalizeColor-test.js @@ -37,7 +37,12 @@ describe('iOS', () => { it('should normalize iOS Dynamic colors with named colors', () => { const color = DynamicColorIOS({light: 'black', dark: 'white'}); const normalizedColor = normalizeColor(color); - const expectedColor = {dynamic: {light: 'black', dark: 'white'}}; + const expectedColor = { + dynamic: { + light: normalizeColor('black'), + dark: normalizeColor('white'), + }, + }; expect(normalizedColor).toEqual(expectedColor); }); @@ -51,10 +56,10 @@ describe('iOS', () => { const normalizedColor = normalizeColor(color); const expectedColor = { dynamic: { - light: 'black', - dark: 'white', - highContrastLight: 'red', - highContrastDark: 'blue', + light: normalizeColor('black'), + dark: normalizeColor('white'), + highContrastLight: normalizeColor('red'), + highContrastDark: normalizeColor('blue'), }, }; expect(normalizedColor).toEqual(expectedColor); diff --git a/Libraries/StyleSheet/normalizeColor.js b/Libraries/StyleSheet/normalizeColor.js index 386e41c434..46df7d988c 100755 --- a/Libraries/StyleSheet/normalizeColor.js +++ b/Libraries/StyleSheet/normalizeColor.js @@ -22,7 +22,7 @@ function normalizeColor( const {normalizeColorObject} = require('./PlatformColorValueTypes'); const normalizedColor = normalizeColorObject(color); if (normalizedColor != null) { - return color; + return normalizedColor; } } diff --git a/Libraries/Text/TextInput/Multiline/RCTUITextView.m b/Libraries/Text/TextInput/Multiline/RCTUITextView.m index b9d08ccb65..5a36d95e05 100644 --- a/Libraries/Text/TextInput/Multiline/RCTUITextView.m +++ b/Libraries/Text/TextInput/Multiline/RCTUITextView.m @@ -270,38 +270,13 @@ static RCTUIColor *defaultPlaceholderColor() // [macOS] - (void)setAttributedText:(NSAttributedString *)attributedText { - // Using `setAttributedString:` while user is typing breaks some internal mechanics - // when entering complex input languages such as Chinese, Korean or Japanese. - // see: https://github.com/facebook/react-native/issues/19339 - - // We try to avoid calling this method as much as we can. - // If the text has changed, there is nothing we can do. #if !TARGET_OS_OSX // [macOS] - if (![super.attributedText.string isEqualToString:attributedText.string]) { - [super setAttributedText:attributedText]; - } else { - // But if the text is preserved, we just copying the attributes from the source string. - if (![super.attributedText isEqualToAttributedString:attributedText]) { - [self copyTextAttributesFrom:attributedText]; - } - } + [super setAttributedText:attributedText]; #else // [macOS - if (![self.textStorage isEqualTo:attributedText.string]) { - // Break undo coalescing when the text is changed by JS (e.g. autocomplete). - [self breakUndoCoalescing]; - - if (attributedText != nil) { - [self.textStorage setAttributedString:attributedText]; - } else { - // Avoid Exception thrown while executing UI block: *** -[NSBigMutableString replaceCharactersInRange:withString:]: nil argument - [self.textStorage setAttributedString:[NSAttributedString new]]; - } - } else { - // But if the text is preserved, we just copy the attributes from the source string. - if (![self.textStorage isEqualToAttributedString:attributedText]) { - [self copyTextAttributesFrom:attributedText]; - } - } + // Break undo coalescing when the text is changed by JS (e.g. autocomplete). + [self breakUndoCoalescing]; + // Avoid Exception thrown while executing UI block: *** -[NSBigMutableString replaceCharactersInRange:withString:]: nil argument + [self.textStorage setAttributedString:attributedText ?: [NSAttributedString new]]; #endif // macOS] [self textDidChange]; } @@ -625,18 +600,4 @@ static RCTUIColor *defaultPlaceholderColor() // [macOS] #pragma mark - Utility Methods -- (void)copyTextAttributesFrom:(NSAttributedString *)sourceString -{ - [self.textStorage beginEditing]; - - NSTextStorage *textStorage = self.textStorage; - [sourceString enumerateAttributesInRange:NSMakeRange(0, sourceString.length) - options:NSAttributedStringEnumerationReverse - usingBlock:^(NSDictionary * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) { - [textStorage setAttributes:attrs range:range]; - }]; - - [self.textStorage endEditing]; -} - @end diff --git a/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h b/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h index 6c29a8005d..e5ffa885a0 100644 --- a/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h +++ b/Libraries/Text/TextInput/RCTBackedTextInputViewProtocol.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN #if !TARGET_OS_OSX // [macOS] @protocol RCTBackedTextInputViewProtocol #else // [macOS -@protocol RCTBackedTextInputViewProtocol +@protocol RCTBackedTextInputViewProtocol #endif // macOS] @property (nonatomic, copy, nullable) NSAttributedString *attributedText; @@ -76,7 +76,6 @@ NS_ASSUME_NONNULL_BEGIN #endif // macOS] #if TARGET_OS_OSX // [macOS -- (BOOL)hasMarkedText; // UITextInput method for OSX - (CGSize)sizeThatFits:(CGSize)size; #endif // macOS] diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index e794b151bb..6630f01f4d 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -112,6 +112,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder) // 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. + // Also, updating the attributed text while inputting Korean language will break input mechanism. // 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. @@ -125,12 +126,16 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder) BOOL shouldFallbackToBareTextComparison = #if !TARGET_OS_OSX // [macOS] [self.backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || + [self.backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"ko-KR"] || self.backedTextInputView.markedTextRange || self.backedTextInputView.isSecureTextEntry || - fontHasBeenUpdatedBySystem; #else // [macOS - NO; + // There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead + [[[self.backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] || + [self.backedTextInputView hasMarkedText] || + [self.backedTextInputView isKindOfClass:[NSSecureTextField class]] || #endif // macOS] + fontHasBeenUpdatedBySystem; if (shouldFallbackToBareTextComparison) { return ([newText.string isEqualToString:oldText.string]); @@ -154,12 +159,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder) range:NSMakeRange(0, attributedTextCopy.length)]; textNeedsUpdate = ([self textOf:attributedTextCopy equals:backedTextInputViewTextCopy] == NO); -#if TARGET_OS_OSX // [macOS - // If we are in a language that uses conversion (e.g. Japanese), ignore updates if we have unconverted text. - if ([self.backedTextInputView hasMarkedText]) { - textNeedsUpdate = NO; - } -#endif // macOS] if (eventLag == 0 && textNeedsUpdate) { #if !TARGET_OS_OSX // [macOS] diff --git a/Libraries/Text/TextInput/Singleline/RCTUITextField.m b/Libraries/Text/TextInput/Singleline/RCTUITextField.m index 926108a862..e3dff048f7 100644 --- a/Libraries/Text/TextInput/Singleline/RCTUITextField.m +++ b/Libraries/Text/TextInput/Singleline/RCTUITextField.m @@ -132,6 +132,12 @@ { return ((NSTextView *)self.currentEditor).hasMarkedText; } + +- (NSArray *)validAttributesForMarkedText +{ + return ((NSTextView *)self.currentEditor).validAttributesForMarkedText; +} + #endif // macOS] #pragma mark - Accessibility diff --git a/Libraries/Utilities/verifyComponentAttributeEquivalence.js b/Libraries/Utilities/verifyComponentAttributeEquivalence.js index 684a888e6e..225707fcca 100644 --- a/Libraries/Utilities/verifyComponentAttributeEquivalence.js +++ b/Libraries/Utilities/verifyComponentAttributeEquivalence.js @@ -62,7 +62,7 @@ export default function verifyComponentAttributeEquivalence( // Return the different key-value pairs of the right object, by iterating through the keys in the left object // Note it won't return a difference where a key is missing in the left but exists the right. -export function lefthandObjectDiff(leftObj: Object, rightObj: Object): Object { +function lefthandObjectDiff(leftObj: Object, rightObj: Object): Object { const differentKeys = {}; function compare(leftItem: any, rightItem: any, key: string) { diff --git a/Libraries/vendor/emitter/_EmitterSubscription.js b/Libraries/vendor/emitter/_EmitterSubscription.js index 6e701ec253..99c402a46f 100644 --- a/Libraries/vendor/emitter/_EmitterSubscription.js +++ b/Libraries/vendor/emitter/_EmitterSubscription.js @@ -13,7 +13,7 @@ import type EventEmitter from './EventEmitter'; import _EventSubscription from './_EventSubscription'; import type EventSubscriptionVendor from './_EventSubscriptionVendor'; -import {type EventSubscription} from './EventSubscription'; +import type {EventSubscription} from './EventSubscription'; /** * EmitterSubscription represents a subscription with listener and context data. diff --git a/Libraries/vendor/emitter/_EventEmitter.js b/Libraries/vendor/emitter/_EventEmitter.js index 39c076c538..b5e5a05b75 100644 --- a/Libraries/vendor/emitter/_EventEmitter.js +++ b/Libraries/vendor/emitter/_EventEmitter.js @@ -12,7 +12,7 @@ const invariant = require('invariant'); import EmitterSubscription from './_EmitterSubscription'; -import {type EventSubscription} from './EventSubscription'; +import type {EventSubscription} from './EventSubscription'; import EventSubscriptionVendor from './_EventSubscriptionVendor'; const sparseFilterPredicate = () => true; diff --git a/Libraries/vendor/emitter/_EventSubscription.js b/Libraries/vendor/emitter/_EventSubscription.js index 73331152d5..9dc35c738a 100644 --- a/Libraries/vendor/emitter/_EventSubscription.js +++ b/Libraries/vendor/emitter/_EventSubscription.js @@ -10,7 +10,7 @@ 'use strict'; -import {type EventSubscription} from './EventSubscription'; +import type {EventSubscription} from './EventSubscription'; import type EventSubscriptionVendor from './_EventSubscriptionVendor'; /** diff --git a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 65d5fb8801..0fee049938 100644 --- a/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -647,8 +647,9 @@ using namespace facebook::react; // 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 + // https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange?language=objc for more info. + // Also, updating the attributed text while inputting Korean language will break input mechanism. + // 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; @@ -661,19 +662,23 @@ using namespace facebook::react; } }]; -#if !TARGET_OS_OSX // [macOS] BOOL shouldFallbackToBareTextComparison = [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] || +#if !TARGET_OS_OSX // [macOS] + [_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"ko-KR"] || _backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem; - +#else // [macOS + // There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead + [[[self.backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] || + [self.backedTextInputView hasMarkedText] || + [self.backedTextInputView isKindOfClass:[NSSecureTextField class]] || + fontHasBeenUpdatedBySystem; +#endif // macOS] if (shouldFallbackToBareTextComparison) { return ([newText.string isEqualToString:oldText.string]); } else { -#endif // [macOS] return ([newText isEqualToAttributedString:oldText]); -#if !TARGET_OS_OSX // [macOS] } -#endif // [macOS] } @end diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index f17bc2ab8f..6b77da1874 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -97,6 +97,14 @@ static BackgroundExecutor RCTGetBackgroundExecutor() _mountingManager.delegate = self; _scheduler = [self _createScheduler]; + + auto reactNativeConfig = _contextContainer->at>("ReactNativeConfig"); + if (reactNativeConfig->getBool("react_native_new_architecture:suspend_before_app_termination")) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_applicationWillTerminate) + name:UIApplicationWillTerminateNotification + object:nil]; + } } return self; @@ -281,6 +289,8 @@ static BackgroundExecutor RCTGetBackgroundExecutor() auto weakRuntimeScheduler = _contextContainer->find>("RuntimeScheduler"); auto runtimeScheduler = weakRuntimeScheduler.has_value() ? weakRuntimeScheduler.value().lock() : nullptr; if (runtimeScheduler) { + runtimeScheduler->setEnableYielding( + reactNativeConfig->getBool("react_native_new_architecture:runtimescheduler_enable_yielding_ios")); runtimeExecutor = [runtimeScheduler](std::function &&callback) { runtimeScheduler->scheduleWork(std::move(callback)); }; @@ -335,6 +345,11 @@ static BackgroundExecutor RCTGetBackgroundExecutor() }]; } +- (void)_applicationWillTerminate +{ + [self suspend]; +} + #pragma mark - RCTSchedulerDelegate - (void)schedulerDidFinishTransaction:(MountingCoordinator::Shared const &)mountingCoordinator diff --git a/React/Views/RCTView.m b/React/Views/RCTView.m index 0ec7c66fe9..aeaa068c46 100644 --- a/React/Views/RCTView.m +++ b/React/Views/RCTView.m @@ -1112,33 +1112,49 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) }; } +#if !TARGET_OS_OSX // [macOS] +- (RCTBorderColors)borderColorsWithTraitCollection:(UITraitCollection *)traitCollection +#else // [macOS - (RCTBorderColors)borderColors +#endif // macOS] { const BOOL isRTL = _reactLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft; + RCTUIColor *directionAwareBorderLeftColor = nil; + RCTUIColor *directionAwareBorderRightColor = nil; + if ([[RCTI18nUtil sharedInstance] doLeftAndRightSwapInRTL]) { RCTUIColor *borderStartColor = _borderStartColor ?: _borderLeftColor; // macOS RCTUIColor RCTUIColor *borderEndColor = _borderEndColor ?: _borderRightColor; // macOS RCTUIColor - RCTUIColor *directionAwareBorderLeftColor = isRTL ? borderEndColor : borderStartColor; // macOS RCTUIColor - RCTUIColor *directionAwareBorderRightColor = isRTL ? borderStartColor : borderEndColor; // macOS RCTUIColor - - return (RCTBorderColors){ - (_borderTopColor ?: _borderColor).CGColor, - (directionAwareBorderLeftColor ?: _borderColor).CGColor, - (_borderBottomColor ?: _borderColor).CGColor, - (directionAwareBorderRightColor ?: _borderColor).CGColor, - }; + directionAwareBorderLeftColor = isRTL ? borderEndColor : borderStartColor; + directionAwareBorderRightColor = isRTL ? borderStartColor : borderEndColor; + } else { + directionAwareBorderLeftColor = (isRTL ? _borderEndColor : _borderStartColor) ?: _borderLeftColor; + directionAwareBorderRightColor = (isRTL ? _borderStartColor : _borderEndColor) ?: _borderRightColor; } - RCTUIColor *directionAwareBorderLeftColor = isRTL ? _borderEndColor : _borderStartColor; // macOS RCTUIColor - RCTUIColor *directionAwareBorderRightColor = isRTL ? _borderStartColor : _borderEndColor; // macOS RCTUIColor + RCTUIColor *borderColor = _borderColor; + RCTUIColor *borderTopColor = _borderTopColor; + RCTUIColor *borderBottomColor = _borderBottomColor; + +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, *)) { + borderColor = [borderColor resolvedColorWithTraitCollection:self.traitCollection]; + borderTopColor = [borderTopColor resolvedColorWithTraitCollection:self.traitCollection]; + directionAwareBorderLeftColor = + [directionAwareBorderLeftColor resolvedColorWithTraitCollection:self.traitCollection]; + borderBottomColor = [borderBottomColor resolvedColorWithTraitCollection:self.traitCollection]; + directionAwareBorderRightColor = + [directionAwareBorderRightColor resolvedColorWithTraitCollection:self.traitCollection]; + } +#endif return (RCTBorderColors){ - (_borderTopColor ?: _borderColor).CGColor, - (directionAwareBorderLeftColor ?: _borderLeftColor ?: _borderColor).CGColor, - (_borderBottomColor ?: _borderColor).CGColor, - (directionAwareBorderRightColor ?: _borderRightColor ?: _borderColor).CGColor, + (borderTopColor ?: borderColor).CGColor, + (directionAwareBorderLeftColor ?: borderColor).CGColor, + (borderBottomColor ?: borderColor).CGColor, + (directionAwareBorderRightColor ?: borderColor).CGColor, }; } @@ -1169,8 +1185,11 @@ static CGFloat RCTDefaultIfNegativeTo(CGFloat defaultValue, CGFloat x) const RCTCornerRadii cornerRadii = [self cornerRadii]; const UIEdgeInsets borderInsets = [self bordersAsInsets]; +#if !TARGET_OS_OSX // [macOS] + const RCTBorderColors borderColors = [self borderColorsWithTraitCollection:self.traitCollection]; +#else // [macOS const RCTBorderColors borderColors = [self borderColors]; - +#endif // macOS] BOOL useIOSBorderRendering = RCTCornerRadiiAreEqual(cornerRadii) && RCTBorderInsetsAreEqual(borderInsets) && RCTBorderColorsAreEqual(borderColors) && _borderStyle == RCTBorderStyleSolid && diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index 1f42ad3666..8f276d1297 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -595,4 +595,29 @@ RCT_EXPORT_SHADOW_PROPERTY(onLayout, RCTDirectEventBlock) RCT_EXPORT_SHADOW_PROPERTY(direction, YGDirection) +// The events below define the properties that are not used by native directly, but required in the view config for new +// renderer to function. +// They can be deleted after Static View Configs are rolled out. + +// PanResponder handlers +RCT_CUSTOM_VIEW_PROPERTY(onMoveShouldSetResponder, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onMoveShouldSetResponderCapture, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onStartShouldSetResponder, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onStartShouldSetResponderCapture, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderGrant, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderReject, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderStart, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderEnd, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderRelease, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderMove, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderTerminate, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onResponderTerminationRequest, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onShouldBlockNativeResponder, BOOL, RCTView) {} + +// Touch events +RCT_CUSTOM_VIEW_PROPERTY(onTouchStart, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onTouchMove, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onTouchEnd, BOOL, RCTView) {} +RCT_CUSTOM_VIEW_PROPERTY(onTouchCancel, BOOL, RCTView) {} + @end diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index cae7d90ada..d391da8576 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -351,6 +351,12 @@ android { packagingOptions { exclude("META-INF/NOTICE") exclude("META-INF/LICENSE") + // We intentionally don't want to bundle any JS Runtime inside the Android AAR + // we produce. The reason behind this is that we want to allow users to pick the + // JS engine by specifying a dependency on either `hermes-engine` or `android-jsc` + // that will include the necessary .so files to load. + exclude("**/libhermes.so") + exclude("**/libjsc.so") } configurations { diff --git a/ReactAndroid/proguard-rules.pro b/ReactAndroid/proguard-rules.pro index 2c7c818cee..2161cd7e7d 100644 --- a/ReactAndroid/proguard-rules.pro +++ b/ReactAndroid/proguard-rules.pro @@ -24,17 +24,15 @@ # See http://sourceforge.net/p/proguard/bugs/466/ -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters --keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip --keep,allowobfuscation @interface com.facebook.jni.annotations.DoNotStrip # Do not strip any method/class that is annotated with @DoNotStrip -keep @com.facebook.proguard.annotations.DoNotStrip class * --keep @com.facebook.common.internal.DoNotStrip class * --keep @com.facebook.jni.annotations.DoNotStrip class * -keepclassmembers class * { @com.facebook.proguard.annotations.DoNotStrip *; - @com.facebook.common.internal.DoNotStrip *; - @com.facebook.jni.annotations.DoNotStrip *; +} + +-keep @com.facebook.proguard.annotations.DoNotStripAny class * { + *; } -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 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 55c151958a..304603fd12 100644 --- a/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp +++ b/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/OnLoad.cpp @@ -47,6 +47,7 @@ static ::hermes::vm::RuntimeConfig makeRuntimeConfig(jlong heapSizeMB) { return vm::RuntimeConfig::Builder() .withGCConfig(gcConfigBuilder.build()) + .withEnableSampleProfiling(true) .build(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 918f8b612e..e5743ca5a9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -81,10 +81,10 @@ import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.DevSupportManagerFactory; import com.facebook.react.devsupport.ReactInstanceDevHelper; -import com.facebook.react.devsupport.RedBoxHandler; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.modules.appearance.AppearanceModule; import com.facebook.react.modules.appregistry.AppRegistry; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java index 199e4033cf..d7450a14ce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -26,9 +26,9 @@ import com.facebook.react.common.LifecycleState; import com.facebook.react.common.SurfaceDelegateFactory; import com.facebook.react.devsupport.DefaultDevSupportManagerFactory; import com.facebook.react.devsupport.DevSupportManagerFactory; -import com.facebook.react.devsupport.RedBoxHandler; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.jscexecutor.JSCExecutor; import com.facebook.react.jscexecutor.JSCExecutorFactory; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java index 305af49539..6f965a8d30 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java @@ -18,7 +18,7 @@ import com.facebook.react.common.LifecycleState; import com.facebook.react.common.SurfaceDelegate; import com.facebook.react.common.SurfaceDelegateFactory; import com.facebook.react.devsupport.DevSupportManagerFactory; -import com.facebook.react.devsupport.RedBoxHandler; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.uimanager.UIImplementationProvider; import java.util.List; diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/AnimatedNodeWithUpdateableConfig.java b/ReactAndroid/src/main/java/com/facebook/react/animated/AnimatedNodeWithUpdateableConfig.java new file mode 100644 index 0000000000..59fb7d801c --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/AnimatedNodeWithUpdateableConfig.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.animated; + +import com.facebook.react.bridge.ReadableMap; + +/** Indicates that AnimatedNode is able to receive native config updates. */ +public interface AnimatedNodeWithUpdateableConfig { + void onUpdateConfig(ReadableMap config); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/ColorAnimatedNode.java b/ReactAndroid/src/main/java/com/facebook/react/animated/ColorAnimatedNode.java index 0624a866ab..7c55feb8f3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/ColorAnimatedNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/ColorAnimatedNode.java @@ -7,47 +7,60 @@ package com.facebook.react.animated; +import android.content.Context; +import android.graphics.Color; +import android.view.View; +import com.facebook.react.bridge.ColorPropConverter; +import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.views.view.ColorUtil; /** Animated node that represents a color. */ -/*package*/ class ColorAnimatedNode extends AnimatedNode { +/*package*/ class ColorAnimatedNode extends AnimatedNode + implements AnimatedNodeWithUpdateableConfig { private final NativeAnimatedNodesManager mNativeAnimatedNodesManager; - private final int mRNodeId; - private final int mGNodeId; - private final int mBNodeId; - private final int mANodeId; - private int mColor; + private final ReactApplicationContext mReactApplicationContext; + private int mRNodeId; + private int mGNodeId; + private int mBNodeId; + private int mANodeId; + private ReadableMap mNativeColor; + private boolean mNativeColorApplied; public ColorAnimatedNode( - ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) { + ReadableMap config, + NativeAnimatedNodesManager nativeAnimatedNodesManager, + ReactApplicationContext reactApplicationContext) { mNativeAnimatedNodesManager = nativeAnimatedNodesManager; + mReactApplicationContext = reactApplicationContext; + onUpdateConfig(config); + } + + public int getColor() { + tryApplyNativeColor(); + + ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId); + ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId); + ValueAnimatedNode bNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mBNodeId); + ValueAnimatedNode aNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mANodeId); + + double r = rNode.getValue(); + double g = gNode.getValue(); + double b = bNode.getValue(); + double a = aNode.getValue(); + + return ColorUtil.normalize(r, g, b, a); + } + + public void onUpdateConfig(ReadableMap config) { mRNodeId = config.getInt("r"); mGNodeId = config.getInt("g"); mBNodeId = config.getInt("b"); mANodeId = config.getInt("a"); - - // TODO (T110930421): Support platform color - } - - public int getColor() { - return mColor; - } - - @Override - public void update() { - AnimatedNode rNode = mNativeAnimatedNodesManager.getNodeById(mRNodeId); - AnimatedNode gNode = mNativeAnimatedNodesManager.getNodeById(mGNodeId); - AnimatedNode bNode = mNativeAnimatedNodesManager.getNodeById(mBNodeId); - AnimatedNode aNode = mNativeAnimatedNodesManager.getNodeById(mANodeId); - - double r = ((ValueAnimatedNode) rNode).getValue(); - double g = ((ValueAnimatedNode) gNode).getValue(); - double b = ((ValueAnimatedNode) bNode).getValue(); - double a = ((ValueAnimatedNode) aNode).getValue(); - - mColor = ColorUtil.normalize(r, g, b, a); + mNativeColor = config.getMap("nativeColor"); + mNativeColorApplied = false; + tryApplyNativeColor(); } @Override @@ -63,4 +76,56 @@ import com.facebook.react.views.view.ColorUtil; + " a: " + mANodeId; } + + private void tryApplyNativeColor() { + if (mNativeColor == null || mNativeColorApplied) { + return; + } + + Context context = getContext(); + if (context == null) { + return; + } + + int color = ColorPropConverter.getColor(mNativeColor, context); + + ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId); + ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId); + ValueAnimatedNode bNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mBNodeId); + ValueAnimatedNode aNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mANodeId); + + rNode.mValue = Color.red(color); + gNode.mValue = Color.green(color); + bNode.mValue = Color.blue(color); + aNode.mValue = Color.alpha(color) / 255.0; + + mNativeColorApplied = true; + } + + private Context getContext() { + Context context = mReactApplicationContext.getCurrentActivity(); + if (context != null) { + return context; + } + + // There are cases where the activity may not exist (such as for VRShell panel apps). In this + // case we will search for a view associated with a PropsAnimatedNode to get the context. + return getContextHelper(this); + } + + private static Context getContextHelper(AnimatedNode node) { + // Search children depth-first until we get to a PropsAnimatedNode, from which we can + // get the view and its context + if (node.mChildren != null) { + for (AnimatedNode child : node.mChildren) { + if (child instanceof PropsAnimatedNode) { + View view = ((PropsAnimatedNode) child).getConnectedView(); + return view != null ? view.getContext() : null; + } else { + return getContextHelper(child); + } + } + } + return null; + } } 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 9c370f68a9..887440dea9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -460,6 +460,32 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec }); } + @Override + public void updateAnimatedNodeConfig(final double tagDouble, final ReadableMap config) { + final int tag = (int) tagDouble; + if (ANIMATED_MODULE_DEBUG) { + FLog.d( + NAME, + "queue updateAnimatedNodeConfig: " + tag + " config: " + config.toHashMap().toString()); + } + + addOperation( + new UIThreadOperation() { + @Override + public void execute(NativeAnimatedNodesManager animatedNodesManager) { + if (ANIMATED_MODULE_DEBUG) { + FLog.d( + NAME, + "execute updateAnimatedNodeConfig: " + + tag + + " config: " + + config.toHashMap().toString()); + } + animatedNodesManager.updateAnimatedNodeConfig(tag, config); + } + }); + } + @Override public void startListeningToAnimatedNodeValue(final double tagDouble) { final int tag = (int) tagDouble; 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 10252abfa1..28d611f0b1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java @@ -130,7 +130,7 @@ import java.util.Queue; } else if ("value".equals(type)) { node = new ValueAnimatedNode(config); } else if ("color".equals(type)) { - node = new ColorAnimatedNode(config, this); + node = new ColorAnimatedNode(config, this, mReactApplicationContext); } else if ("props".equals(type)) { node = new PropsAnimatedNode(config, this); } else if ("interpolation".equals(type)) { @@ -159,6 +159,21 @@ import java.util.Queue; mUpdatedNodes.put(tag, node); } + @UiThread + public void updateAnimatedNodeConfig(int tag, ReadableMap config) { + AnimatedNode node = mAnimatedNodes.get(tag); + if (node == null) { + throw new JSApplicationIllegalArgumentException( + "updateAnimatedNode: Animated node [" + tag + "] does not exist"); + } + + if (node instanceof AnimatedNodeWithUpdateableConfig) { + stopAnimationsForNode(node); + ((AnimatedNodeWithUpdateableConfig) node).onUpdateConfig(config); + mUpdatedNodes.put(tag, node); + } + } + @UiThread public void dropAnimatedNode(int tag) { mAnimatedNodes.remove(tag); diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java b/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java index 759675e661..aacf6bf1c3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/PropsAnimatedNode.java @@ -7,12 +7,14 @@ package com.facebook.react.animated; +import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; import com.facebook.react.bridge.UIManager; +import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.ViewUtil; import java.util.HashMap; @@ -116,6 +118,16 @@ import java.util.Map; mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap); } + public View getConnectedView() { + try { + return mUIManager.resolveView(mConnectedViewTag); + } catch (IllegalViewOperationException ex) { + // resolveView throws an {@link IllegalViewOperationException} when the view doesn't exist + // (this can happen if the surface is being deallocated). + return null; + } + } + public String prettyPrint() { return "PropsAnimatedNode[" + mTag diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarker.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarker.java index b6c4357176..ac07aca94c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarker.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarker.java @@ -7,6 +7,7 @@ package com.facebook.react.bridge; +import android.os.SystemClock; import androidx.annotation.Nullable; import com.facebook.proguard.annotations.DoNotStrip; import java.util.List; @@ -91,7 +92,7 @@ public class ReactMarker { @DoNotStrip public static void logFabricMarker( ReactMarkerConstants name, @Nullable String tag, int instanceKey) { - logFabricMarker(name, tag, instanceKey, -1); + logFabricMarker(name, tag, instanceKey, SystemClock.uptimeMillis()); } @DoNotStrip diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java index 821de3f3a3..a6ba792926 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java @@ -37,4 +37,7 @@ public interface SurfaceDelegate { /** Hide the surface containing the React content view */ void hide(); + + /** Check if the surface is currently showing */ + boolean isShowing(); } 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 b4ab457195..bc93addfdd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -101,7 +101,4 @@ public class ReactFeatureFlags { /** TODO: T103427072 Delete ReactFeatureFlags.enableNestedTextOnPressEventFix */ public static boolean enableNestedTextOnPressEventFix = true; - - /** TODO: T107492383 Delete this flag. Enables postprocessor for rounded corners for Image */ - public static boolean enableRoundedCornerPostprocessing = false; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java index 159bf31989..205de052d7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java @@ -27,6 +27,7 @@ import com.facebook.react.common.futures.SimpleSettableFuture; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevOptionHandler; import com.facebook.react.devsupport.interfaces.DevSplitBundleCallback; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.packagerconnection.RequestHandler; import java.io.File; import java.io.IOException; diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java index 6459c219ad..97862539f4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import com.facebook.react.common.SurfaceDelegateFactory; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.packagerconnection.RequestHandler; import java.lang.reflect.Constructor; import java.util.Map; 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 f4d0e82ddd..7b1ba63c52 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java @@ -51,6 +51,7 @@ import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.ErrorCustomizer; import com.facebook.react.devsupport.interfaces.ErrorType; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.devsupport.interfaces.StackFrame; import com.facebook.react.modules.core.RCTNativeAppEventEmitter; import com.facebook.react.packagerconnection.RequestHandler; @@ -96,7 +97,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager { private final DefaultNativeModuleCallExceptionHandler mDefaultNativeModuleCallExceptionHandler; private final DevLoadingViewController mDevLoadingViewController; - private @Nullable RedBoxDialog mRedBoxDialog; + private @Nullable SurfaceDelegate mRedBoxSurfaceDelegate; private @Nullable AlertDialog mDevOptionsDialog; private @Nullable DebugOverlayController mDebugOverlayController; private boolean mDevLoadingViewVisible = false; @@ -197,7 +198,7 @@ public abstract class DevSupportManagerBase implements DevSupportManager { final String bundleFile = subclassTag + "ReactNativeDevBundle.js"; mJSBundleDownloadedFile = new File(applicationContext.getFilesDir(), bundleFile); - final String splitBundlesDir = subclassTag.toLowerCase() + "_dev_js_split_bundles"; + final String splitBundlesDir = subclassTag.toLowerCase(Locale.ROOT) + "_dev_js_split_bundles"; mJSSplitBundlesDir = mApplicationContext.getDir(splitBundlesDir, Context.MODE_PRIVATE); mDefaultNativeModuleCallExceptionHandler = new DefaultNativeModuleCallExceptionHandler(); @@ -272,7 +273,8 @@ public abstract class DevSupportManagerBase implements DevSupportManager { mErrorCustomizers.add(errorCustomizer); } - private Pair processErrorCustomizers(Pair errorInfo) { + @Override + public Pair processErrorCustomizers(Pair errorInfo) { if (mErrorCustomizers == null) { return errorInfo; } else { @@ -296,33 +298,25 @@ public abstract class DevSupportManagerBase implements DevSupportManager { // Since we only show the first JS error in a succession of JS errors, make sure we only // update the error message for that error message. This assumes that updateJSError // belongs to the most recent showNewJSError - if (mRedBoxDialog == null - || !mRedBoxDialog.isShowing() - || errorCookie != mLastErrorCookie) { + if (!mRedBoxSurfaceDelegate.isShowing() || errorCookie != mLastErrorCookie) { return; } - StackFrame[] stack = StackTraceHelper.convertJsStackTrace(details); - Pair errorInfo = - processErrorCustomizers(Pair.create(message, stack)); - mRedBoxDialog.setExceptionDetails(errorInfo.first, errorInfo.second); - updateLastErrorInfo(message, stack, errorCookie, ErrorType.JS); - // JS errors are reported here after source mapping. - if (mRedBoxHandler != null) { - mRedBoxHandler.handleRedbox(message, stack, ErrorType.JS); - mRedBoxDialog.resetReporting(); - } - mRedBoxDialog.show(); + + // The RedBox surface delegate will always show the latest error + updateLastErrorInfo( + message, StackTraceHelper.convertJsStackTrace(details), errorCookie, ErrorType.JS); + mRedBoxSurfaceDelegate.show(); } }); } @Override public void hideRedboxDialog() { - // dismiss redbox if exists - if (mRedBoxDialog != null) { - mRedBoxDialog.dismiss(); - mRedBoxDialog = null; + if (mRedBoxSurfaceDelegate == null) { + return; } + + mRedBoxSurfaceDelegate.hide(); } public @Nullable View createRootView(String appKey) { @@ -349,41 +343,27 @@ public abstract class DevSupportManagerBase implements DevSupportManager { new Runnable() { @Override public void run() { - Activity context = mReactInstanceDevHelper.getCurrentActivity(); - if (context != null && !context.isFinishing() && currentActivity != context) { - currentActivity = context; - // Create a new RedBox when currentActivity get updated - mRedBoxDialog = - new RedBoxDialog(currentActivity, DevSupportManagerBase.this, mRedBoxHandler); + if (mRedBoxSurfaceDelegate == null) { + @Nullable SurfaceDelegate redBoxSurfaceDelegate = createSurfaceDelegate("RedBox"); + if (redBoxSurfaceDelegate != null) { + mRedBoxSurfaceDelegate = redBoxSurfaceDelegate; + } else { + mRedBoxSurfaceDelegate = + new RedBoxDialogSurfaceDelegate(DevSupportManagerBase.this); + } + + mRedBoxSurfaceDelegate.createContentView("RedBox"); } - if (currentActivity == null || currentActivity.isFinishing()) { - FLog.e( - ReactConstants.TAG, - "Unable to launch redbox because react activity " - + "is not available, here is the error that redbox would've displayed: " - + message); - return; - } - if (mRedBoxDialog == null) { - mRedBoxDialog = - new RedBoxDialog(currentActivity, DevSupportManagerBase.this, mRedBoxHandler); - } - if (mRedBoxDialog.isShowing()) { + + if (mRedBoxSurfaceDelegate.isShowing()) { // Sometimes errors cause multiple errors to be thrown in JS in quick succession. Only // show the first and most actionable one. return; } - Pair errorInfo = - processErrorCustomizers(Pair.create(message, stack)); - mRedBoxDialog.setExceptionDetails(errorInfo.first, errorInfo.second); + + // The RedBox surface delegate will always show the latest error updateLastErrorInfo(message, stack, errorCookie, errorType); - // Only report native errors here. JS errors are reported - // inside {@link #updateJSError} after source mapping. - if (mRedBoxHandler != null && errorType == ErrorType.NATIVE) { - mRedBoxHandler.handleRedbox(message, stack, ErrorType.NATIVE); - } - mRedBoxDialog.resetReporting(); - mRedBoxDialog.show(); + mRedBoxSurfaceDelegate.show(); } }); } @@ -622,6 +602,11 @@ public abstract class DevSupportManagerBase implements DevSupportManager { return mDevSettings; } + @Override + public RedBoxHandler getRedBoxHandler() { + return mRedBoxHandler; + } + @Override public void onNewReactContextCreated(ReactContext reactContext) { resetCurrentContext(reactContext); @@ -887,6 +872,11 @@ public abstract class DevSupportManagerBase implements DevSupportManager { return mLastErrorStack; } + @Override + public int getLastErrorCookie() { + return mLastErrorCookie; + } + @Override public @Nullable ErrorType getLastErrorType() { return mLastErrorType; diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java index 131f4462fb..3b1c71dc75 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import com.facebook.react.common.SurfaceDelegateFactory; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.packagerconnection.RequestHandler; import java.util.Map; diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java index c198ac1610..f44cdeb332 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java @@ -8,6 +8,7 @@ package com.facebook.react.devsupport; import android.app.Activity; +import android.util.Pair; import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler; @@ -21,6 +22,7 @@ import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.devsupport.interfaces.ErrorCustomizer; import com.facebook.react.devsupport.interfaces.ErrorType; import com.facebook.react.devsupport.interfaces.PackagerStatusCallback; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; import com.facebook.react.devsupport.interfaces.StackFrame; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import java.io.File; @@ -94,6 +96,11 @@ public class DisabledDevSupportManager implements DevSupportManager { return null; } + @Override + public RedBoxHandler getRedBoxHandler() { + return null; + } + @Override public void onNewReactContextCreated(ReactContext reactContext) {} @@ -166,9 +173,19 @@ public class DisabledDevSupportManager implements DevSupportManager { return null; } + @Override + public int getLastErrorCookie() { + return 0; + } + @Override public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) {} + @Override + public Pair processErrorCustomizers(Pair errorInfo) { + return errorInfo; + } + @Override public void setPackagerLocationCustomizer( DevSupportManager.PackagerLocationCustomizer packagerLocationCustomizer) {} diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DoubleTapReloadRecognizer.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DoubleTapReloadRecognizer.java index b178267dd0..c54335e972 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DoubleTapReloadRecognizer.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DoubleTapReloadRecognizer.java @@ -14,7 +14,7 @@ import android.widget.EditText; /** * A class allows recognizing double key tap of "R", used to reload JS in {@link - * AbstractReactActivity}, {@link RedBoxDialog} and {@link ReactActivity}. + * AbstractReactActivity}, {@link RedBoxDialogSurfaceDelegate} and {@link ReactActivity}. */ public class DoubleTapReloadRecognizer { private boolean mDoRefresh = false; diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java index c9668d29f8..ed465a1838 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java @@ -55,7 +55,7 @@ public class LogBoxDialogSurfaceDelegate implements SurfaceDelegate { @Override public void show() { - if (isSurfaceVisible() || !isContentViewReady()) { + if (isShowing() || !isContentViewReady()) { return; } @@ -74,7 +74,7 @@ public class LogBoxDialogSurfaceDelegate implements SurfaceDelegate { @Override public void hide() { - if (!isSurfaceVisible()) { + if (!isShowing()) { return; } @@ -86,7 +86,8 @@ public class LogBoxDialogSurfaceDelegate implements SurfaceDelegate { mDialog = null; } - private boolean isSurfaceVisible() { - return mDialog != null; + @Override + public boolean isShowing() { + return mDialog != null && mDialog.isShowing(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxContentView.java similarity index 84% rename from ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java rename to ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxContentView.java index ca214e4cac..2232a2bd0b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxContentView.java @@ -7,21 +7,20 @@ package com.facebook.react.devsupport; -import android.app.Dialog; import android.content.Context; import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; import android.text.SpannedString; import android.text.method.LinkMovementMethod; -import android.view.KeyEvent; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; +import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; @@ -31,8 +30,10 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.react.R; import com.facebook.react.common.MapBuilder; import com.facebook.react.common.ReactConstants; -import com.facebook.react.devsupport.RedBoxHandler.ReportCompletedListener; import com.facebook.react.devsupport.interfaces.DevSupportManager; +import com.facebook.react.devsupport.interfaces.ErrorType; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; +import com.facebook.react.devsupport.interfaces.RedBoxHandler.ReportCompletedListener; import com.facebook.react.devsupport.interfaces.StackFrame; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -41,12 +42,10 @@ import okhttp3.RequestBody; import org.json.JSONObject; /** Dialog for displaying JS errors in an eye-catching form (red box). */ -/* package */ class RedBoxDialog extends Dialog implements AdapterView.OnItemClickListener { - - private final DevSupportManager mDevSupportManager; - private final DoubleTapReloadRecognizer mDoubleTapReloadRecognizer; - private final @Nullable RedBoxHandler mRedBoxHandler; +public class RedBoxContentView extends LinearLayout implements AdapterView.OnItemClickListener { + private @Nullable RedBoxHandler mRedBoxHandler; + private DevSupportManager mDevSupportManager; private ListView mStackView; private Button mReloadJsButton; private Button mDismissButton; @@ -235,17 +234,22 @@ import org.json.JSONObject; } } - protected RedBoxDialog( - Context context, DevSupportManager devSupportManager, @Nullable RedBoxHandler redBoxHandler) { - super(context, R.style.Theme_Catalyst_RedBox); - - requestWindowFeature(Window.FEATURE_NO_TITLE); - - setContentView(R.layout.redbox_view); + public RedBoxContentView(Context context) { + super(context); + } + public RedBoxContentView setDevSupportManager(DevSupportManager devSupportManager) { mDevSupportManager = devSupportManager; - mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer(); + return this; + } + + public RedBoxContentView setRedBoxHandler(@Nullable RedBoxHandler redBoxHandler) { mRedBoxHandler = redBoxHandler; + return this; + } + + public void init() { + LayoutInflater.from(getContext()).inflate(R.layout.redbox_view, this); mStackView = (ListView) findViewById(R.id.rn_redbox_stack); mStackView.setOnItemClickListener(this); @@ -255,7 +259,7 @@ import org.json.JSONObject; new View.OnClickListener() { @Override public void onClick(View v) { - mDevSupportManager.handleReloadJS(); + Assertions.assertNotNull(mDevSupportManager).handleReloadJS(); } }); mDismissButton = (Button) findViewById(R.id.rn_redbox_dismiss_button); @@ -263,7 +267,7 @@ import org.json.JSONObject; new View.OnClickListener() { @Override public void onClick(View v) { - dismiss(); + Assertions.assertNotNull(mDevSupportManager).hideRedboxDialog(); } }); @@ -297,20 +301,25 @@ import org.json.JSONObject; @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - new OpenStackFrameTask(mDevSupportManager) + new OpenStackFrameTask(Assertions.assertNotNull(mDevSupportManager)) .executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR, (StackFrame) mStackView.getAdapter().getItem(position)); } - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_MENU) { - mDevSupportManager.showDevOptionsDialog(); - return true; + /** Refresh the content view with latest errors from dev support manager */ + public void refreshContentView() { + @Nullable String message = mDevSupportManager.getLastErrorTitle(); + @Nullable StackFrame[] stack = mDevSupportManager.getLastErrorStack(); + @Nullable ErrorType errorType = mDevSupportManager.getLastErrorType(); + Pair errorInfo = + mDevSupportManager.processErrorCustomizers(Pair.create(message, stack)); + setExceptionDetails(errorInfo.first, errorInfo.second); + + // JS errors are reported here after source mapping. + RedBoxHandler redBoxHandler = mDevSupportManager.getRedBoxHandler(); + if (redBoxHandler != null) { + redBoxHandler.handleRedbox(message, stack, errorType); + resetReporting(); } - if (mDoubleTapReloadRecognizer.didDoubleTapR(keyCode, getCurrentFocus())) { - mDevSupportManager.handleReloadJS(); - } - return super.onKeyUp(keyCode, event); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialogSurfaceDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialogSurfaceDelegate.java new file mode 100644 index 0000000000..97ef306afa --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialogSurfaceDelegate.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.devsupport; + +import android.app.Activity; +import android.app.Dialog; +import android.view.KeyEvent; +import android.view.Window; +import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; +import com.facebook.react.R; +import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.SurfaceDelegate; +import com.facebook.react.devsupport.interfaces.DevSupportManager; +import com.facebook.react.devsupport.interfaces.RedBoxHandler; + +/** + * The implementation of SurfaceDelegate with {@link Activity}. This is the default SurfaceDelegate + * for Mobile. + */ +public class RedBoxDialogSurfaceDelegate implements SurfaceDelegate { + + private final DoubleTapReloadRecognizer mDoubleTapReloadRecognizer; + private final DevSupportManager mDevSupportManager; + + private @Nullable Dialog mDialog; + private @Nullable RedBoxContentView mRedBoxContentView; + + public RedBoxDialogSurfaceDelegate(DevSupportManager devSupportManager) { + mDevSupportManager = devSupportManager; + mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer(); + } + + @Override + public void createContentView(String appKey) { + // The content view is created in android instead of using react app. Hence the appKey is not + // used here. + RedBoxHandler redBoxHandler = mDevSupportManager.getRedBoxHandler(); + Activity context = mDevSupportManager.getCurrentActivity(); + // Create a new RedBox when currentActivity get updated + mRedBoxContentView = new RedBoxContentView(context); + mRedBoxContentView + .setDevSupportManager(mDevSupportManager) + .setRedBoxHandler(redBoxHandler) + .init(); + } + + @Override + public boolean isContentViewReady() { + return mRedBoxContentView != null; + } + + @Override + public void destroyContentView() { + mRedBoxContentView = null; + } + + @Override + public void show() { + @Nullable String message = mDevSupportManager.getLastErrorTitle(); + Activity context = mDevSupportManager.getCurrentActivity(); + if (context == null || context.isFinishing()) { + FLog.e( + ReactConstants.TAG, + "Unable to launch redbox because react activity " + + "is not available, here is the error that redbox would've displayed: " + + (message != null ? message : "N/A")); + return; + } + + if (mRedBoxContentView == null || mRedBoxContentView.getContext() != context) { + // Create a new RedBox when currentActivity get updated + createContentView("RedBox"); + } + + mRedBoxContentView.refreshContentView(); + if (mDialog == null) { + mDialog = + new Dialog(context, R.style.Theme_Catalyst_RedBox) { + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU) { + mDevSupportManager.showDevOptionsDialog(); + return true; + } + if (mDoubleTapReloadRecognizer.didDoubleTapR(keyCode, getCurrentFocus())) { + mDevSupportManager.handleReloadJS(); + } + return super.onKeyUp(keyCode, event); + } + }; + mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + mDialog.setContentView(mRedBoxContentView); + } + mDialog.show(); + } + + @Override + public void hide() { + // dismiss redbox if exists + if (mDialog != null) { + mDialog.dismiss(); + destroyContentView(); + mDialog = null; + } + } + + @Override + public boolean isShowing() { + return mDialog != null && mDialog.isShowing(); + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java index f830561f67..40079b1e55 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java @@ -8,6 +8,7 @@ package com.facebook.react.devsupport.interfaces; import android.app.Activity; +import android.util.Pair; import android.view.View; import androidx.annotation.Nullable; import com.facebook.react.bridge.NativeModuleCallExceptionHandler; @@ -51,6 +52,8 @@ public interface DevSupportManager extends NativeModuleCallExceptionHandler { DeveloperSettings getDevSettings(); + RedBoxHandler getRedBoxHandler(); + void onNewReactContextCreated(ReactContext reactContext); void onReactInstanceDestroyed(ReactContext reactContext); @@ -97,8 +100,12 @@ public interface DevSupportManager extends NativeModuleCallExceptionHandler { @Nullable ErrorType getLastErrorType(); + int getLastErrorCookie(); + void registerErrorCustomizer(ErrorCustomizer errorCustomizer); + Pair processErrorCustomizers(Pair errorInfo); + /** * The PackagerLocationCustomizer allows you to have a dynamic packager location that is * determined right before loading the packager. Your customizer must call |callback|, as loading diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxHandler.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/RedBoxHandler.java similarity index 88% rename from ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxHandler.java rename to ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/RedBoxHandler.java index 597caf2f86..a8f15b5c8b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxHandler.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/RedBoxHandler.java @@ -5,13 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.devsupport; +package com.facebook.react.devsupport.interfaces; import android.content.Context; import android.text.SpannedString; import androidx.annotation.Nullable; -import com.facebook.react.devsupport.interfaces.ErrorType; -import com.facebook.react.devsupport.interfaces.StackFrame; /** * Interface used by {@link BridgeDevSupportManager} to allow interception on any redboxes during diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.cpp similarity index 87% rename from ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp rename to ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.cpp index 3bf94580a2..d6e0e63062 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.cpp @@ -9,11 +9,11 @@ #include #include -#include "AsyncEventBeatV2.h" +#include "AsyncEventBeat.h" namespace facebook::react { -AsyncEventBeatV2::AsyncEventBeatV2( +AsyncEventBeat::AsyncEventBeat( EventBeat::SharedOwnerBox const &ownerBox, EventBeatManager *eventBeatManager, RuntimeExecutor runtimeExecutor, @@ -25,11 +25,11 @@ AsyncEventBeatV2::AsyncEventBeatV2( eventBeatManager->addObserver(*this); } -AsyncEventBeatV2::~AsyncEventBeatV2() { +AsyncEventBeat::~AsyncEventBeat() { eventBeatManager_->removeObserver(*this); } -void AsyncEventBeatV2::tick() const { +void AsyncEventBeat::tick() const { if (!isRequested_ || isBeatCallbackScheduled_) { return; } @@ -50,11 +50,11 @@ void AsyncEventBeatV2::tick() const { }); } -void AsyncEventBeatV2::induce() const { +void AsyncEventBeat::induce() const { tick(); } -void AsyncEventBeatV2::request() const { +void AsyncEventBeat::request() const { bool alreadyRequested = isRequested_; EventBeat::request(); if (!alreadyRequested) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.h index 072de4e255..f0316d5577 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeat.h @@ -7,14 +7,11 @@ #pragma once -#include #include -#include #include "EventBeatManager.h" -namespace facebook { -namespace react { +namespace facebook::react { class AsyncEventBeat final : public EventBeat, public EventBeatManagerObserver { public: @@ -22,50 +19,21 @@ class AsyncEventBeat final : public EventBeat, public EventBeatManagerObserver { EventBeat::SharedOwnerBox const &ownerBox, EventBeatManager *eventBeatManager, RuntimeExecutor runtimeExecutor, - jni::global_ref javaUIManager) - : EventBeat(ownerBox), - eventBeatManager_(eventBeatManager), - runtimeExecutor_(std::move(runtimeExecutor)), - javaUIManager_(std::move(javaUIManager)) { - eventBeatManager->addObserver(*this); - } + jni::global_ref javaUIManager); - ~AsyncEventBeat() { - eventBeatManager_->removeObserver(*this); - } + ~AsyncEventBeat() override; - void tick() const override { - runtimeExecutor_([this, ownerBox = ownerBox_](jsi::Runtime &runtime) { - auto owner = ownerBox->owner.lock(); - if (!owner) { - return; - } + void tick() const override; - this->beat(runtime); - }); - } + void induce() const override; - void induce() const override { - tick(); - } - - void request() const override { - bool alreadyRequested = isRequested_; - EventBeat::request(); - if (!alreadyRequested) { - // Notifies java side that an event will be dispatched (e.g. LayoutEvent) - static auto onRequestEventBeat = - jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") - ->getMethod("onRequestEventBeat"); - onRequestEventBeat(javaUIManager_); - } - } + void request() const override; private: EventBeatManager *eventBeatManager_; RuntimeExecutor runtimeExecutor_; jni::global_ref javaUIManager_; + mutable std::atomic isBeatCallbackScheduled_{false}; }; -} // namespace react -} // namespace facebook +} // namespace facebook::react diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h deleted file mode 100644 index 569af7c96c..0000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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 "EventBeatManager.h" - -namespace facebook::react { - -class AsyncEventBeatV2 final : public EventBeat, - public EventBeatManagerObserver { - public: - AsyncEventBeatV2( - EventBeat::SharedOwnerBox const &ownerBox, - EventBeatManager *eventBeatManager, - RuntimeExecutor runtimeExecutor, - jni::global_ref javaUIManager); - - ~AsyncEventBeatV2() override; - - void tick() const override; - - void induce() const override; - - void request() const override; - - private: - EventBeatManager *eventBeatManager_; - RuntimeExecutor runtimeExecutor_; - jni::global_ref javaUIManager_; - mutable std::atomic isBeatCallbackScheduled_{false}; -}; - -} // namespace facebook::react 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 c8dde14b52..bf6495340e 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 @@ -7,7 +7,6 @@ #include "Binding.h" #include "AsyncEventBeat.h" -#include "AsyncEventBeatV2.h" #include "EventEmitterWrapper.h" #include "ReactNativeConfigHolder.h" #include "StateWrapperImpl.h" @@ -60,9 +59,8 @@ Binding::getInspectorDataForInstance( } EventEmitterWrapper *cEventEmitter = cthis(eventEmitterWrapper); - InspectorData data = scheduler->getInspectorDataForInstance( - enableEventEmitterRawPointer_ ? *cEventEmitter->eventEmitterPointer - : *cEventEmitter->eventEmitter); + InspectorData data = + scheduler->getInspectorDataForInstance(*cEventEmitter->eventEmitter); folly::dynamic result = folly::dynamic::object; result["fileName"] = data.fileName; @@ -266,13 +264,37 @@ void Binding::stopSurface(jint surfaceId) { } void Binding::registerSurface(SurfaceHandlerBinding *surfaceHandlerBinding) { + auto const &surfaceHandler = surfaceHandlerBinding->getSurfaceHandler(); auto scheduler = getScheduler(); - scheduler->registerSurface(surfaceHandlerBinding->getSurfaceHandler()); + if (!scheduler) { + LOG(ERROR) << "Binding::registerSurface: scheduler disappeared"; + return; + } + scheduler->registerSurface(surfaceHandler); + + auto mountingManager = + verifyMountingManager("FabricUIManagerBinding::registerSurface"); + if (!mountingManager) { + return; + } + mountingManager->onSurfaceStart(surfaceHandler.getSurfaceId()); } void Binding::unregisterSurface(SurfaceHandlerBinding *surfaceHandlerBinding) { + auto const &surfaceHandler = surfaceHandlerBinding->getSurfaceHandler(); auto scheduler = getScheduler(); - scheduler->unregisterSurface(surfaceHandlerBinding->getSurfaceHandler()); + if (!scheduler) { + LOG(ERROR) << "Binding::unregisterSurface: scheduler disappeared"; + return; + } + scheduler->unregisterSurface(surfaceHandler); + + auto mountingManager = + verifyMountingManager("FabricUIManagerBinding::unregisterSurface"); + if (!mountingManager) { + return; + } + mountingManager->onSurfaceStop(surfaceHandler.getSurfaceId()); } void Binding::setConstraints( @@ -345,9 +367,6 @@ void Binding::installFabricUIManager( disableRevisionCheckForPreallocation_ = config->getBool("react_fabric:disable_revision_check_for_preallocation"); - enableEventEmitterRawPointer_ = - config->getBool("react_fabric:enable_event_emitter_wrapper_raw_pointer"); - if (enableFabricLogs_) { LOG(WARNING) << "Binding::installFabricUIManager() was called (address: " << this << ")."; @@ -369,46 +388,34 @@ void Binding::installFabricUIManager( if (runtimeSchedulerHolder) { auto runtimeScheduler = runtimeSchedulerHolder->cthis()->get().lock(); if (runtimeScheduler) { + runtimeScheduler->setEnableYielding(config->getBool( + "react_native_new_architecture:runtimescheduler_enable_yielding_android")); runtimeExecutor = [runtimeScheduler]( std::function &&callback) { runtimeScheduler->scheduleWork(std::move(callback)); }; + contextContainer->insert( + "RuntimeScheduler", + std::weak_ptr(runtimeScheduler)); } } - auto enableV2AsynchronousEventBeat = - config->getBool("react_fabric:enable_asynchronous_event_beat_v2_android"); - // TODO: T31905686 Create synchronous Event Beat EventBeat::Factory synchronousBeatFactory = - [eventBeatManager, - runtimeExecutor, - globalJavaUiManager, - enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox) + [eventBeatManager, runtimeExecutor, globalJavaUiManager]( + EventBeat::SharedOwnerBox const &ownerBox) -> std::unique_ptr { - if (enableV2AsynchronousEventBeat) { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); - } else { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); - } + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); }; EventBeat::Factory asynchronousBeatFactory = - [eventBeatManager, - runtimeExecutor, - globalJavaUiManager, - enableV2AsynchronousEventBeat](EventBeat::SharedOwnerBox const &ownerBox) + [eventBeatManager, runtimeExecutor, globalJavaUiManager]( + EventBeat::SharedOwnerBox const &ownerBox) -> std::unique_ptr { - if (enableV2AsynchronousEventBeat) { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); - } else { - return std::make_unique( - ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); - } + return std::make_unique( + ownerBox, eventBeatManager, runtimeExecutor, globalJavaUiManager); }; contextContainer->insert("ReactNativeConfig", config); 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 db537efddb..90099106bb 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 @@ -155,7 +155,6 @@ class Binding : public jni::HybridClass, bool disablePreallocateViews_{false}; bool enableFabricLogs_{false}; bool disableRevisionCheckForPreallocation_{false}; - bool enableEventEmitterRawPointer_{false}; bool dispatchPreallocationInBackground_{false}; }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp index 262ac0d23d..19a003793d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp @@ -22,15 +22,6 @@ void EventEmitterWrapper::invokeEvent( std::string const &eventName, NativeMap *payload, int category) { - if (eventEmitterPointer) { - eventEmitterPointer->dispatchEvent( - eventName, - payload->consume(), - EventPriority::AsynchronousBatched, - static_cast(category)); - return; - } - // It is marginal, but possible for this to be constructed without a valid // EventEmitter. In those cases, make sure we noop/blackhole events instead of // crashing. @@ -47,10 +38,6 @@ void EventEmitterWrapper::invokeUniqueEvent( std::string const &eventName, NativeMap *payload, int customCoalesceKey) { - if (eventEmitterPointer) { - eventEmitterPointer->dispatchUniqueEvent(eventName, payload->consume()); - return; - } // TODO: customCoalesceKey currently unused // It is marginal, but possible for this to be constructed without a valid // EventEmitter. In those cases, make sure we noop/blackhole events instead of diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h index f7a6d6e11f..4f4d68fb5c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h @@ -24,7 +24,6 @@ class EventEmitterWrapper : public jni::HybridClass { static void registerNatives(); SharedEventEmitter eventEmitter; - EventEmitter const *eventEmitterPointer; void invokeEvent(std::string const &eventName, NativeMap *params, int category); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.cpp index e88af4c229..5121593409 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.cpp @@ -545,11 +545,7 @@ void FabricMountingManager::executeMount( mountItem.newChildShadowView.eventEmitter; auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs(); EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter); - if (enableEventEmitterRawPointer_) { - cEventEmitter->eventEmitterPointer = eventEmitter.get(); - } else { - cEventEmitter->eventEmitter = eventEmitter; - } + cEventEmitter->eventEmitter = eventEmitter; temp[0] = mountItem.newChildShadowView.tag; temp[1] = isLayoutable; env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp); @@ -729,11 +725,7 @@ void FabricMountingManager::executeMount( // Do not hold a reference to javaEventEmitter from the C++ side. auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs(); EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter); - if (enableEventEmitterRawPointer_) { - cEventEmitter->eventEmitterPointer = eventEmitter.get(); - } else { - cEventEmitter->eventEmitter = eventEmitter; - } + cEventEmitter->eventEmitter = eventEmitter; (*objBufferArray)[objBufferPosition++] = javaEventEmitter.get(); } @@ -830,11 +822,7 @@ void FabricMountingManager::preallocateShadowView( if (eventEmitter != nullptr) { javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs(); EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter); - if (enableEventEmitterRawPointer_) { - cEventEmitter->eventEmitterPointer = eventEmitter.get(); - } else { - cEventEmitter->eventEmitter = eventEmitter; - } + cEventEmitter->eventEmitter = eventEmitter; } } @@ -947,8 +935,6 @@ FabricMountingManager::FabricMountingManager( : javaUIManager_(javaUIManager) { enableEarlyEventEmitterUpdate_ = config->getBool("react_fabric:enable_early_event_emitter_update"); - enableEventEmitterRawPointer_ = - config->getBool("react_fabric:enable_event_emitter_wrapper_raw_pointer"); disablePreallocateViews_ = config->getBool("react_fabric:disabled_view_preallocation_android"); disableRevisionCheckForPreallocation_ = diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.h index 0ac9ac2e4a..618d24154b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/FabricMountingManager.h @@ -71,7 +71,6 @@ class FabricMountingManager { butter::map> allocatedViewRegistry_{}; std::recursive_mutex allocatedViewsMutex_; - bool enableEventEmitterRawPointer_{false}; bool enableEarlyEventEmitterUpdate_{false}; bool disablePreallocateViews_{false}; bool disableRevisionCheckForPreallocation_{false}; 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 index 7422f18de0..3c7311af3f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -548,7 +548,8 @@ public class SurfaceMountingManager { // generated. // This represents a perf issue only, not a correctness issue. In the future we need to // refactor View preallocation to correct the currently incorrect assumptions. - if (getNullableViewState(reactTag) != null) { + ViewState viewState = getNullableViewState(reactTag); + if (viewState != null && viewState.mView != null) { return; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 55cfb20215..f80b1c6561 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -30,6 +30,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.TimeUnit; import okhttp3.Call; @@ -376,7 +377,9 @@ public final class NetworkingModule extends NativeNetworkingAndroidSpec { } RequestBody requestBody; - if (data == null || method.toLowerCase().equals("get") || method.toLowerCase().equals("head")) { + if (data == null + || method.toLowerCase(Locale.ROOT).equals("get") + || method.toLowerCase(Locale.ROOT).equals("head")) { requestBody = RequestBodyUtil.getEmptyBody(method); } else if (handler != null) { requestBody = handler.toRequestBody(data, contentType); 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 a3beef47e7..8765a23ca4 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 @@ -190,7 +190,7 @@ public class StatusBarModule extends NativeStatusBarManagerAndroidSpec { @TargetApi(Build.VERSION_CODES.R) @Override public void run() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) { WindowInsetsController insetsController = activity.getWindow().getInsetsController(); if ("dark-content".equals(style)) { // dark-content means dark icons on a light status bar diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK index 9979f6dfdd..1d3b290ca3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BUCK @@ -14,10 +14,12 @@ rn_android_library( ], ), autoglob = False, + exported_provided_deps = [ + react_native_dep("third-party/android/androidx:annotation"), + ], is_androidx = True, labels = ["supermodule:xplat/default/public.react_native.infra"], provided_deps = [ - react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/android/androidx:core"), react_native_dep("third-party/android/androidx:fragment"), react_native_dep("third-party/android/androidx:legacy-support-core-ui"), @@ -51,7 +53,6 @@ rn_android_library( ], exported_deps = [ ":DisplayMetrics", - 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"), @@ -76,7 +77,6 @@ rn_android_library( deps = [ react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), react_native_dep("third-party/java/infer-annotations:infer-annotations"), - 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/bridge:bridge"), react_native_target("java/com/facebook/react/common:common"), 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 3c9c1eae3b..b48b272d9c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -486,18 +486,103 @@ public abstract class BaseViewManager postprocessors = new LinkedList<>(); - if (mRoundedCornerPostprocessor != null) { - postprocessors.add(mRoundedCornerPostprocessor); - } if (mIterativeBoxBlurPostProcessor != null) { postprocessors.add(mIterativeBoxBlurPostProcessor); } @@ -647,12 +563,6 @@ public class ReactImageView extends GenericDraweeView { return mTileMode != Shader.TileMode.CLAMP; } - private boolean shouldUseRoundedCornerPostprocessing() { - return mScaleType != ScalingUtils.ScaleType.CENTER_CROP - && mScaleType != ScalingUtils.ScaleType.FOCUS_CROP - && ReactFeatureFlags.enableRoundedCornerPostprocessing; - } - private void setSourceImage() { mImageSource = null; if (mSources.isEmpty()) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.java index 804e9d7b02..8053ece767 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.java @@ -12,6 +12,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import androidx.annotation.Nullable; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import javax.annotation.concurrent.ThreadSafe; @@ -47,7 +48,7 @@ public class ResourceDrawableIdHelper { if (name == null || name.isEmpty()) { return 0; } - name = name.toLowerCase().replace("-", "_"); + name = name.toLowerCase(Locale.ROOT).replace("-", "_"); // name could be a resource id. try { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index ddd60f19ac..6d4bd242dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -8,13 +8,11 @@ package com.facebook.react.views.scroll; import android.graphics.Color; -import android.util.DisplayMetrics; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; @@ -99,8 +97,8 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager offsets = new ArrayList(); for (int i = 0; i < snapToOffsets.size(); i++) { - offsets.add((int) (snapToOffsets.getDouble(i) * screenDisplayMetrics.density)); + offsets.add((int) (snapToOffsets.getDouble(i) * density)); } view.setSnapOffsets(offsets); } 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 e9b99417a4..8624f648dd 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 @@ -254,8 +254,8 @@ public class ReactScrollView extends ScrollView @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // Call with the present values in order to re-layout if necessary - // If a "pending" value has been set, we restore that value. - // That value gets cleared by reactScrollTo. + // If a "pending" content offset value has been set, we restore that value. + // Upon call to scrollTo, the "pending" values will be re-set. int scrollToX = pendingContentOffsetX != UNSET_CONTENT_OFFSET ? pendingContentOffsetX : getScrollX(); int scrollToY = @@ -954,23 +954,21 @@ public class ReactScrollView extends ScrollView } /** - * Calls `reactScrollTo` and updates state. + * Calls `updateFabricScrollState` and updates state. * - *

`reactScrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between - * scroll view and state. Calling raw `reactScrollTo` doesn't update state. - * - *

Note that while we can override scrollTo, we *cannot* override `smoothScrollTo` because it - * is final. See `reactSmoothScrollTo`. + *

`scrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between + * scroll view and state. Calling ScrollView's `scrollTo` doesn't update state. */ @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); - // The final scroll position might be different from (x, y). For example, we may need to scroll - // to the last item in the list, but that item cannot be move to the start position of the view. - final int actualX = getScrollX(); - final int actualY = getScrollY(); - ReactScrollViewHelper.updateFabricScrollState(this, actualX, actualY); - setPendingContentOffsets(actualX, actualY); + ReactScrollViewHelper.updateFabricScrollState(this); + setPendingContentOffsets(x, y); + } + + private boolean isContentReady() { + View child = getChildAt(0); + return child != null && child.getWidth() != 0 && child.getHeight() != 0; } /** @@ -981,8 +979,7 @@ public class ReactScrollView extends ScrollView * @param y */ private void setPendingContentOffsets(int x, int y) { - View child = getChildAt(0); - if (child != null && child.getWidth() != 0 && child.getHeight() != 0) { + if (isContentReady()) { pendingContentOffsetX = UNSET_CONTENT_OFFSET; pendingContentOffsetY = UNSET_CONTENT_OFFSET; } else { 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 4952468458..8a3623444b 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 @@ -8,7 +8,6 @@ package com.facebook.react.views.scroll; import android.graphics.Color; -import android.util.DisplayMetrics; import android.view.View; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; @@ -17,7 +16,6 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.RetryableMountingLayerException; import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; @@ -98,8 +96,8 @@ public class ReactScrollViewManager extends ViewGroupManager @ReactProp(name = "snapToInterval") public void setSnapToInterval(ReactScrollView view, float snapToInterval) { // snapToInterval needs to be exposed as a float because of the Javascript interface. - DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); - view.setSnapInterval((int) (snapToInterval * screenDisplayMetrics.density)); + float density = PixelUtil.getDisplayMetricDensity(); + view.setSnapInterval((int) (snapToInterval * density)); } @ReactProp(name = "snapToOffsets") @@ -109,10 +107,10 @@ public class ReactScrollViewManager extends ViewGroupManager return; } - DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); + float density = PixelUtil.getDisplayMetricDensity(); List offsets = new ArrayList(); for (int i = 0; i < snapToOffsets.size(); i++) { - offsets.add((int) (snapToOffsets.getDouble(i) * screenDisplayMetrics.density)); + offsets.add((int) (snapToOffsets.getDouble(i) * density)); } view.setSnapOffsets(offsets); } 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 f375dee0cc..2a699d0352 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 @@ -75,6 +75,7 @@ import com.facebook.yoga.YogaConstants; import java.lang.reflect.Field; import java.util.HashMap; import java.util.LinkedList; +import java.util.Locale; import java.util.Map; /** Manages instances of TextInput. */ @@ -569,7 +570,7 @@ public class ReactTextInputManager extends BaseViewManagerspinner - - diff --git a/ReactCommon/hermes/inspector/chrome/Connection.cpp b/ReactCommon/hermes/inspector/chrome/Connection.cpp index 7101eb2247..2fa87b5386 100644 --- a/ReactCommon/hermes/inspector/chrome/Connection.cpp +++ b/ReactCommon/hermes/inspector/chrome/Connection.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -100,11 +101,15 @@ class Connection::Impl : public inspector::InspectorObserver, void handle( const m::heapProfiler::GetObjectByHeapObjectIdRequest &req) override; void handle(const m::heapProfiler::GetHeapObjectIdRequest &req) override; + void handle(const m::runtime::CallFunctionOnRequest &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; private: + // The execution context id reported back by the ExecutionContextCreated + // notification. We only ever expect this execution context id. + static constexpr int32_t kHermesExecutionContextId = 1; std::vector makePropsFromScope( std::pair frameAndScopeIndex, const std::string &objectGroup, @@ -291,7 +296,7 @@ void Connection::Impl::onContextCreated(Inspector &inspector) { // Right now, Hermes only has the notion of one JS context per VM instance, // so we just always name the single JS context with id=1 and name=hermes. m::runtime::ExecutionContextCreatedNotification note; - note.context.id = 1; + note.context.id = kHermesExecutionContextId; note.context.name = "hermes"; sendNotificationToClientViaExecutor(note); @@ -370,6 +375,8 @@ void Connection::Impl::onScriptParsed( m::debugger::ScriptParsedNotification note; note.scriptId = folly::to(info.fileId); note.url = info.fileName; + // TODO(jpporto): fix test cases sending invalid context id. + // note.executionContextId = kHermesExecutionContextId; if (!info.sourceMappingUrl.empty()) { note.sourceMapURL = info.sourceMappingUrl; @@ -397,6 +404,8 @@ void Connection::Impl::onMessageAdded( const ConsoleMessageInfo &info) { m::runtime::ConsoleAPICalledNotification apiCalledNote; apiCalledNote.type = info.level; + // TODO(jpporto): fix test cases sending invalid context id. + // apiCalledNote.executionContextId = kHermesExecutionContextId; size_t argsSize = info.args.size(getRuntime()); for (size_t index = 0; index < argsSize; ++index) { @@ -711,6 +720,315 @@ void Connection::Impl::handle( .thenError(sendErrorToClient(req.id)); } +namespace { +/// Runtime.CallArguments can have their values specified "inline", or they can +/// have remote references. The inline values are eval'd together with the +/// Runtime.CallFunctionOn.functionDeclaration (see CallFunctionOnBuilder +/// below), while remote object Ids need to be resolved outside of the VM. +class CallFunctionOnArgument { + public: + explicit CallFunctionOnArgument( + folly::Optional maybeObjectId) + : maybeObjectId_(std::move(maybeObjectId)) {} + + /// Computes the real value for this argument, which can be an object + /// referenced by maybeObjectId_, or the given evaldValue. Throws if + /// maybeObjectId_ is not empty but references an unknown object. + jsi::Value value( + jsi::Runtime &rt, + RemoteObjectsTable &objTable, + jsi::Value evaldValue) const { + if (maybeObjectId_) { + assert(evaldValue.isUndefined() && "expected undefined placeholder"); + return getValueFromId(rt, objTable, *maybeObjectId_); + } + + return evaldValue; + } + + private: + /// Returns the jsi::Object for the given objId. Throws if such object can't + /// be found. + static jsi::Value getValueFromId( + jsi::Runtime &rt, + RemoteObjectsTable &objTable, + m::runtime::RemoteObjectId objId) { + if (const jsi::Value *ptr = objTable.getValue(objId)) { + return jsi::Value(rt, *ptr); + } + + throw std::runtime_error("unknown object id " + objId); + } + + folly::Optional maybeObjectId_; +}; + +/// Functor that should be used to run the result of eval-ing a CallFunctionOn +/// request. +class CallFunctionOnRunner { + public: + static constexpr size_t kJsThisIndex = 0; + static constexpr size_t kFirstArgIndex = 1; + + // N.B.: constexpr char[] broke react-native-oss-android. + static const char *kJsThisArgPlaceholder; + + CallFunctionOnRunner() = default; + CallFunctionOnRunner(CallFunctionOnRunner &&) = default; + CallFunctionOnRunner &operator=(CallFunctionOnRunner &&) = default; + + /// Performs the actual Runtime.CallFunctionOn request. It assumes. + /// \p evalResult is the result of invoking the Inspector's evaluate() method + /// on the expression built by the CallFunctionOnBuilder below. + jsi::Value operator()( + jsi::Runtime &rt, + RemoteObjectsTable &objTable, + const facebook::hermes::debugger::EvalResult &evalResult) { + // The eval result is an array [a0, a1, ..., an, func] (see + // CallFunctionOnBuilder below). + auto argsAndFunc = evalResult.value.getObject(rt).getArray(rt); + assert( + argsAndFunc.length(rt) == thisAndArguments_.size() + 1 && + "Unexpected result size"); + + // now resolve the arguments to the call, including "this". + std::vector arguments(thisAndArguments_.size() - 1); + + jsi::Object jsThis = + getJsThis(rt, objTable, argsAndFunc.getValueAtIndex(rt, kJsThisIndex)); + + int i = kFirstArgIndex; + for (/*i points to the first param*/; i < thisAndArguments_.size(); ++i) { + arguments[i - kFirstArgIndex] = thisAndArguments_[i].value( + rt, objTable, argsAndFunc.getValueAtIndex(rt, i)); + } + + // i is now func's index. + jsi::Function func = + argsAndFunc.getValueAtIndex(rt, i).getObject(rt).getFunction(rt); + + return func.callWithThis( + rt, + std::move(jsThis), + static_cast(arguments.data()), + arguments.size()); + } + + private: + friend class CallFunctionOnBuilder; + + CallFunctionOnRunner(const CallFunctionOnRunner &) = delete; + CallFunctionOnRunner &operator=(const CallFunctionOnRunner &) = delete; + + CallFunctionOnRunner( + std::vector thisAndArguments, + folly::Optional executionContextId) + : thisAndArguments_(std::move(thisAndArguments)), + executionContextId_(std::move(executionContextId)) {} + + /// Resolves the js "this" for the request, which lives in + /// thisAndArguments_[kJsThisIndex]. \p evaldThis should either be undefined, + /// or the placeholder indicating that globalThis should be used. + jsi::Object getJsThis( + jsi::Runtime &rt, + RemoteObjectsTable &objTable, + jsi::Value evaldThis) const { + // In the future we may support multiple execution context ids; for now, + // there's only one. + (void)executionContextId_; + + // Either evaldThis is undefined (because the request had an object id + // specifying "this"), or it should be a string (i.e., the placeholder + // kJsThisArgPlaceholder). + assert( + (evaldThis.isUndefined() || + (evaldThis.isString() && + evaldThis.getString(rt).utf8(rt) == kJsThisArgPlaceholder)) && + "unexpected value for jsThis argument placeholder"); + + // Need to save this information because of the std::move() below. + const bool useGlobalThis = evaldThis.isString(); + jsi::Value value = thisAndArguments_[kJsThisIndex].value( + rt, objTable, std::move(evaldThis)); + + return useGlobalThis ? rt.global() : value.getObject(rt); + } + + std::vector thisAndArguments_; + folly::Optional executionContextId_; +}; + +/*static*/ const char *CallFunctionOnRunner::kJsThisArgPlaceholder = + "jsThis is Execution Context"; + +/// Returns true if \p str is a number-like string value (e.g., Infinity), +/// and false otherwise. +bool unserializableValueLooksLikeNumber(const std::string &str) { + return str == "Infinity" || str == "-Infinity" || str == "NaN"; +} + +/// Helper class that processes a Runtime.CallFunctionOn request, and +/// builds an expression string that, once eval()d, yields an Array with the +/// CallArguments as well as the function to run. The generated array is +/// +/// [JsThis, P0, P1, P2, P3, Pn, F] +/// +/// where: +/// * F is the functionDeclaration in the request +/// * JsThis is either: +/// * undefined (if the request has an object ID); or +/// * the placeholder kJsThisArgPlaceholder +/// * Pi is either: +/// * the string in CallArgument[i].unserializableValue; or +/// * the string in CallArgument[i].value; or +/// * arguments[j] (i.e., the j-th argument passed to the newly built +/// function), j being the j-th CallArgument with an ObjectId. This is +/// needed because there's no easy way to express the objects referred +/// to by object ids by name. +class CallFunctionOnBuilder { + public: + explicit CallFunctionOnBuilder(const m::runtime::CallFunctionOnRequest &req) + : executionContextId_(req.executionContextId) { + out_ << "["; + thisAndArguments_.emplace_back(CallFunctionOnArgument(req.objectId)); + if (req.objectId) { + out_ << "undefined, "; + } else { + out_ << '\'' << CallFunctionOnRunner::kJsThisArgPlaceholder << "', "; + } + + addParams(req.arguments); + out_ << req.functionDeclaration; + out_ << "]"; + }; + + /// Extracts the functions that handles the CallFunctionOn requests, as well + /// as the list of object ids that must be passed when calling it. + std::pair expressionAndRunner() && { + return std::make_pair( + std::move(out_).str(), + CallFunctionOnRunner( + std::move(thisAndArguments_), std::move(executionContextId_))); + } + + private: + void addParams(const folly::Optional> + &maybeArguments) { + if (maybeArguments) { + for (const auto &ca : *maybeArguments) { + addParam(ca); + thisAndArguments_.emplace_back(CallFunctionOnArgument(ca.objectId)); + out_ << ", "; + } + } + } + + void addParam(const m::runtime::CallArgument &ca) { + if (ca.objectId) { + out_ << "undefined"; + } else if (ca.value) { + // TODO: this may throw if ca.value is a CBOR (see RFC 8949), but the + // chrome debugger doesn't seem to send those. + out_ << "(" << folly::toJson(*ca.value) << ")"; + } else if (ca.unserializableValue) { + if (unserializableValueLooksLikeNumber(*ca.unserializableValue)) { + out_ << "+(" << *ca.unserializableValue << ")"; + } else { + out_ << *ca.unserializableValue; + } + } else { + throw std::runtime_error("unknown payload for CallParam"); + } + } + + std::ostringstream out_; + + std::vector thisAndArguments_; + folly::Optional executionContextId_; +}; + +} // namespace + +void Connection::Impl::handle(const m::runtime::CallFunctionOnRequest &req) { + std::string expression; + CallFunctionOnRunner runner; + + auto validateAndParseRequest = + [&expression, &runner](const m::runtime::CallFunctionOnRequest &req) + -> folly::Optional { + if (req.objectId.hasValue() == req.executionContextId.hasValue()) { + return std::string( + "The request must specify either object id or execution context id."); + } + + if (!req.objectId) { + assert( + req.executionContextId && + "should not be here if both object id and execution context id are missing"); + if (*req.executionContextId != kHermesExecutionContextId) { + return "unknown execution context id " + + std::to_string(*req.executionContextId); + } + } + + try { + std::tie(expression, runner) = + CallFunctionOnBuilder(req).expressionAndRunner(); + } catch (const std::exception &e) { + return std::string(e.what()); + } + + return {}; + }; + + if (auto errMsg = validateAndParseRequest(req)) { + sendErrorToClientViaExecutor(req.id, *errMsg); + return; + } + + auto remoteObjPtr = std::make_shared(); + inspector_ + ->evaluate( + 0, // Top of the stackframe + expression, + [this, + remoteObjPtr, + objectGroup = req.objectGroup, + jsThisId = req.objectId, + executionContextId = req.executionContextId, + byValue = req.returnByValue.value_or(false), + runner = + std::move(runner)](const facebook::hermes::debugger::EvalResult + &evalResult) mutable { + if (evalResult.isException) { + return; + } + + *remoteObjPtr = m::runtime::makeRemoteObject( + getRuntime(), + runner(getRuntime(), objTable_, evalResult), + objTable_, + objectGroup.value_or("ConsoleObjectGroup"), + byValue); + }) + .via(executor_.get()) + .thenValue( + [this, id = req.id, remoteObjPtr](debugger::EvalResult result) { + m::debugger::EvaluateOnCallFrameResponse resp; + resp.id = id; + + if (result.isException) { + resp.exceptionDetails = + m::runtime::makeExceptionDetails(result.exceptionDetails); + } else { + resp.result = *remoteObjPtr; + } + + sendResponseToClient(resp); + }) + .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 484719e130..170f90593b 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<<522f29c54f207a4f7b5c33af07cf64d0>> +// @generated <> #include "MessageTypes.h" @@ -60,6 +60,7 @@ std::unique_ptr Request::fromJsonThrowOnError(const std::string &str) { makeUnique}, {"HeapProfiler.takeHeapSnapshot", makeUnique}, + {"Runtime.callFunctionOn", makeUnique}, {"Runtime.evaluate", makeUnique}, {"Runtime.getProperties", makeUnique}, {"Runtime.runIfWaitingForDebugger", @@ -274,6 +275,21 @@ dynamic heapProfiler::SamplingHeapProfile::toDynamic() const { return obj; } +runtime::CallArgument::CallArgument(const dynamic &obj) { + assign(value, obj, "value"); + assign(unserializableValue, obj, "unserializableValue"); + assign(objectId, obj, "objectId"); +} + +dynamic runtime::CallArgument::toDynamic() const { + dynamic obj = dynamic::object; + + put(obj, "value", value); + put(obj, "unserializableValue", unserializableValue); + put(obj, "objectId", objectId); + return obj; +} + runtime::ExecutionContextDescription::ExecutionContextDescription( const dynamic &obj) { assign(id, obj, "id"); @@ -931,6 +947,49 @@ void heapProfiler::TakeHeapSnapshotRequest::accept( handler.handle(*this); } +runtime::CallFunctionOnRequest::CallFunctionOnRequest() + : Request("Runtime.callFunctionOn") {} + +runtime::CallFunctionOnRequest::CallFunctionOnRequest(const dynamic &obj) + : Request("Runtime.callFunctionOn") { + assign(id, obj, "id"); + assign(method, obj, "method"); + + dynamic params = obj.at("params"); + assign(functionDeclaration, params, "functionDeclaration"); + assign(objectId, params, "objectId"); + assign(arguments, params, "arguments"); + assign(silent, params, "silent"); + assign(returnByValue, params, "returnByValue"); + assign(userGesture, params, "userGesture"); + assign(awaitPromise, params, "awaitPromise"); + assign(executionContextId, params, "executionContextId"); + assign(objectGroup, params, "objectGroup"); +} + +dynamic runtime::CallFunctionOnRequest::toDynamic() const { + dynamic params = dynamic::object; + put(params, "functionDeclaration", functionDeclaration); + put(params, "objectId", objectId); + put(params, "arguments", arguments); + put(params, "silent", silent); + put(params, "returnByValue", returnByValue); + put(params, "userGesture", userGesture); + put(params, "awaitPromise", awaitPromise); + put(params, "executionContextId", executionContextId); + put(params, "objectGroup", objectGroup); + + dynamic obj = dynamic::object; + put(obj, "id", id); + put(obj, "method", method); + put(obj, "params", std::move(params)); + return obj; +} + +void runtime::CallFunctionOnRequest::accept(RequestHandler &handler) const { + handler.handle(*this); +} + runtime::EvaluateRequest::EvaluateRequest() : Request("Runtime.evaluate") {} runtime::EvaluateRequest::EvaluateRequest(const dynamic &obj) @@ -1187,6 +1246,25 @@ dynamic heapProfiler::StopSamplingResponse::toDynamic() const { return obj; } +runtime::CallFunctionOnResponse::CallFunctionOnResponse(const dynamic &obj) { + assign(id, obj, "id"); + + dynamic res = obj.at("result"); + assign(result, res, "result"); + assign(exceptionDetails, res, "exceptionDetails"); +} + +dynamic runtime::CallFunctionOnResponse::toDynamic() const { + dynamic res = dynamic::object; + put(res, "result", result); + put(res, "exceptionDetails", exceptionDetails); + + dynamic obj = dynamic::object; + put(obj, "id", id); + put(obj, "result", std::move(res)); + return obj; +} + runtime::EvaluateResponse::EvaluateResponse(const dynamic &obj) { assign(id, obj, "id"); diff --git a/ReactCommon/hermes/inspector/chrome/MessageTypes.h b/ReactCommon/hermes/inspector/chrome/MessageTypes.h index 2184a22358..78468d6fb1 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<> +// @generated <> #pragma once @@ -48,7 +48,10 @@ struct StepOverRequest; } // namespace debugger namespace runtime { +struct CallArgument; struct CallFrame; +struct CallFunctionOnRequest; +struct CallFunctionOnResponse; struct ConsoleAPICalledNotification; struct EvaluateRequest; struct EvaluateResponse; @@ -122,6 +125,7 @@ struct RequestHandler { virtual void handle( const heapProfiler::StopTrackingHeapObjectsRequest &req) = 0; virtual void handle(const heapProfiler::TakeHeapSnapshotRequest &req) = 0; + virtual void handle(const runtime::CallFunctionOnRequest &req) = 0; virtual void handle(const runtime::EvaluateRequest &req) = 0; virtual void handle(const runtime::GetPropertiesRequest &req) = 0; virtual void handle(const runtime::RunIfWaitingForDebuggerRequest &req) = 0; @@ -156,6 +160,7 @@ struct NoopRequestHandler : public RequestHandler { void handle( const heapProfiler::StopTrackingHeapObjectsRequest &req) override {} void handle(const heapProfiler::TakeHeapSnapshotRequest &req) override {} + void handle(const runtime::CallFunctionOnRequest &req) override {} void handle(const runtime::EvaluateRequest &req) override {} void handle(const runtime::GetPropertiesRequest &req) override {} void handle(const runtime::RunIfWaitingForDebuggerRequest &req) override {} @@ -281,6 +286,16 @@ struct heapProfiler::SamplingHeapProfile : public Serializable { std::vector samples; }; +struct runtime::CallArgument : public Serializable { + CallArgument() = default; + explicit CallArgument(const folly::dynamic &obj); + folly::dynamic toDynamic() const override; + + folly::Optional value; + folly::Optional unserializableValue; + folly::Optional objectId; +}; + struct runtime::ExecutionContextDescription : public Serializable { ExecutionContextDescription() = default; explicit ExecutionContextDescription(const folly::dynamic &obj); @@ -546,6 +561,24 @@ struct heapProfiler::TakeHeapSnapshotRequest : public Request { folly::Optional treatGlobalObjectsAsRoots; }; +struct runtime::CallFunctionOnRequest : public Request { + CallFunctionOnRequest(); + explicit CallFunctionOnRequest(const folly::dynamic &obj); + + folly::dynamic toDynamic() const override; + void accept(RequestHandler &handler) const override; + + std::string functionDeclaration; + folly::Optional objectId; + folly::Optional> arguments; + folly::Optional silent; + folly::Optional returnByValue; + folly::Optional userGesture; + folly::Optional awaitPromise; + folly::Optional executionContextId; + folly::Optional objectGroup; +}; + struct runtime::EvaluateRequest : public Request { EvaluateRequest(); explicit EvaluateRequest(const folly::dynamic &obj); @@ -658,6 +691,15 @@ struct heapProfiler::StopSamplingResponse : public Response { heapProfiler::SamplingHeapProfile profile{}; }; +struct runtime::CallFunctionOnResponse : public Response { + CallFunctionOnResponse() = default; + explicit CallFunctionOnResponse(const folly::dynamic &obj); + folly::dynamic toDynamic() const override; + + runtime::RemoteObject result{}; + folly::Optional exceptionDetails; +}; + struct runtime::EvaluateResponse : public Response { EvaluateResponse() = default; explicit EvaluateResponse(const folly::dynamic &obj); diff --git a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp index 1338337779..502b1f10f9 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/ConnectionTests.cpp @@ -407,7 +407,7 @@ std::unordered_map expectProps( m::runtime::PropertyDescriptor &desc = resp.result[i]; auto infoIt = infos.find(desc.name); - EXPECT_FALSE(infoIt == infos.end()); + EXPECT_FALSE(infoIt == infos.end()) << desc.name; if (infoIt != infos.end()) { const PropInfo &info = infoIt->second; @@ -460,6 +460,25 @@ void expectEvalResponse( expectProps(conn, id + 1, resp.result.objectId.value(), infos); } +m::runtime::CallArgument makeValueCallArgument(folly::dynamic val) { + m::runtime::CallArgument ret; + ret.value = val; + return ret; +} + +m::runtime::CallArgument makeUnserializableCallArgument(std::string val) { + m::runtime::CallArgument ret; + ret.unserializableValue = std::move(val); + return ret; +} + +m::runtime::CallArgument makeObjectIdCallArgument( + m::runtime::RemoteObjectId objectId) { + m::runtime::CallArgument ret; + ret.objectId = std::move(objectId); + return ret; +} + } // namespace TEST(ConnectionTests, testRespondsOkToUnknownRequests) { @@ -1981,6 +2000,231 @@ TEST(ConnectionTests, testScopeVariables) { expectNotification(conn); } +TEST(ConnectionTests, testRuntimeCallFunctionOnObject) { + TestContext context; + AsyncHermesRuntime &asyncRuntime = context.runtime(); + SyncConnection &conn = context.conn(); + int msgId = 1; + + asyncRuntime.executeScriptAsync(R"( + debugger; + )"); + + send(conn, msgId++); + expectExecutionContextCreated(conn); + expectNotification(conn); + + // create a new Object() that will be used as "this" below. + m::runtime::RemoteObjectId thisId; + { + sendRuntimeEvalRequest(conn, msgId, "new Object()"); + auto resp = expectResponse(conn, msgId++); + ASSERT_TRUE(resp.result.objectId) << resp.toDynamic(); + thisId = *resp.result.objectId; + } + + // expectedPropInfos are properties that are expected to exist in thisId. It + // is modified by addMember (below). + std::unordered_map expectedPropInfos; + + // Add __proto__ as it always exists. + expectedPropInfos.emplace("__proto__", PropInfo("object")); + + /// addMember sends Runtime.callFunctionOn() requests with a function + /// declaration that simply adds a new property called \p propName with type + /// \p type to the remote object \p id. \p ca is the property's value. + /// The new property must not exist in \p id unless \p allowRedefinition is + /// true. + auto addMember = [&](const m::runtime::RemoteObjectId id, + const char *type, + const char *propName, + const m::runtime::CallArgument &ca, + bool allowRedefinition = false) { + m::runtime::CallFunctionOnRequest req; + req.id = msgId++; + req.functionDeclaration = + std::string("function(e){const r=\"") + propName + "\"; this[r]=e,r}"; + req.arguments = std::vector{ca}; + req.objectId = thisId; + conn.send(req.toJson()); + expectResponse(conn, req.id); + + auto it = expectedPropInfos.emplace(propName, PropInfo(type)); + + EXPECT_TRUE(allowRedefinition || it.second) + << "property \"" << propName << "\" redefined."; + + if (ca.value) { + it.first->second.setValue(*ca.value); + } + + if (ca.unserializableValue) { + it.first->second.setUnserializableValue(*ca.unserializableValue); + } + }; + + addMember(thisId, "boolean", "b", makeValueCallArgument(true)); + addMember(thisId, "number", "num", makeValueCallArgument(12)); + addMember(thisId, "string", "str", makeValueCallArgument("string value")); + addMember(thisId, "object", "self_ref", makeObjectIdCallArgument(thisId)); + addMember( + thisId, "number", "inf", makeUnserializableCallArgument("Infinity")); + addMember( + thisId, "number", "ni", makeUnserializableCallArgument("-Infinity")); + addMember(thisId, "number", "nan", makeUnserializableCallArgument("NaN")); + + /// ensures that \p objId has all of the expected properties; Returns the + /// runtime::RemoteObjectId for the "self_ref" property (which must exist). + auto verifyObjShape = [&](const m::runtime::RemoteObjectId &objId) + -> folly::Optional { + auto objProps = expectProps(conn, msgId++, objId, expectedPropInfos); + EXPECT_TRUE(objProps.count("__proto__")); + auto objPropIt = objProps.find("self_ref"); + if (objPropIt == objProps.end()) { + EXPECT_TRUE(false) << "missing \"self_ref\" property."; + return {}; + } + return objPropIt->second; + }; + + // Verify that thisId has the correct shape. + auto selfRefId = verifyObjShape(thisId); + ASSERT_TRUE(selfRefId); + // Then verify that the self reference has the correct shape. If thisId does + // not have the "self_ref" property the call to verifyObjShape will return an + // empty Optional, as well as report an error. + selfRefId = verifyObjShape(*selfRefId); + ASSERT_TRUE(selfRefId); + + // Now we modify the self reference, which should cause thisId to change + // as well. + const bool kAllowRedefinition = true; + + addMember( + *selfRefId, + "number", + "num", + makeValueCallArgument(42), + kAllowRedefinition); + + addMember( + *selfRefId, "number", "neg_zero", makeUnserializableCallArgument("-0")); + + verifyObjShape(thisId); + + send(conn, msgId++); + expectNotification(conn); +} + +TEST(ConnectionTests, testRuntimeCallFunctionOnExecutionContext) { + TestContext context; + AsyncHermesRuntime &asyncRuntime = context.runtime(); + SyncConnection &conn = context.conn(); + int msgId = 1; + + asyncRuntime.executeScriptAsync(R"( + debugger; + )"); + + /// helper that returns a map with all of \p objId 's members. + auto getProps = [&msgId, &conn](const m::runtime::RemoteObjectId &objId) { + m::runtime::GetPropertiesRequest req; + req.id = msgId++; + req.objectId = objId; + conn.send(req.toJson()); + auto resp = expectResponse(conn, req.id); + std::unordered_map> + properties; + for (auto propertyDescriptor : resp.result) { + properties[propertyDescriptor.name] = propertyDescriptor.value; + } + return properties; + }; + + send(conn, msgId++); + expectExecutionContextCreated(conn); + expectNotification(conn); + + // globalThisId is the inspector's object Id for globalThis. + m::runtime::RemoteObjectId globalThisId; + { + sendRuntimeEvalRequest(conn, msgId, "globalThis"); + auto resp = expectResponse(conn, msgId++); + ASSERT_TRUE(resp.result.objectId) << resp.toDynamic(); + globalThisId = *resp.result.objectId; + } + + // This test table has all of the new fields we want to add to globalThis, + // plus the Runtime.CallArgument to be sent to the inspector. + struct { + const char *propName; + const m::runtime::CallArgument callArg; + } tests[] = { + {"callFunctionOnTestMember1", makeValueCallArgument(10)}, + {"callFunctionOnTestMember2", makeValueCallArgument("string")}, + {"callFunctionOnTestMember3", makeUnserializableCallArgument("NaN")}, + {"callFunctionOnTestMember4", makeUnserializableCallArgument("-0")}, + }; + + // sanity-check that our test fields don't exist in global this. + { + auto currProps = getProps(globalThisId); + for (const auto &test : tests) { + EXPECT_EQ(currProps.count(test.propName), 0) << test.propName; + } + } + + auto addMember = [&msgId, &conn]( + const char *propName, + const m::runtime::CallArgument &ca) { + m::runtime::CallFunctionOnRequest req; + req.id = msgId++; + req.functionDeclaration = + std::string("function(e){const r=\"") + propName + "\"; this[r]=e,r}"; + req.arguments = std::vector{ca}; + req.executionContextId = 1; + conn.send(req.toJson()); + expectResponse(conn, req.id); + }; + + for (const auto &test : tests) { + addMember(test.propName, test.callArg); + } + + { + auto currProps = getProps(globalThisId); + for (const auto &test : tests) { + auto it = currProps.find(test.propName); + + // there should be a property named test.propName in globalThis. + ASSERT_TRUE(it != currProps.end()) << test.propName; + + // and it should have a value. + ASSERT_TRUE(it->second) << test.propName; + + if (it->second->value.hasValue()) { + // the property has a value, so make sure that's what's being expected. + auto actual = it->second->value; + auto expected = test.callArg.value; + ASSERT_TRUE(expected.hasValue()) << test.propName; + EXPECT_EQ(*actual, *expected) << test.propName; + } else if (it->second->unserializableValue.hasValue()) { + // the property has an unserializable value, so make sure that's what's + // being expected. + auto actual = it->second->unserializableValue; + auto expected = test.callArg.unserializableValue; + ASSERT_TRUE(expected.hasValue()) << test.propName; + EXPECT_EQ(*actual, *expected) << test.propName; + } else { + FAIL() << "No value or unserializable value in " << test.propName; + } + } + } + + send(conn, msgId++); + expectNotification(conn); +} + TEST(ConnectionTests, testConsoleLog) { TestContext context; AsyncHermesRuntime &asyncRuntime = context.runtime(); @@ -2489,9 +2733,9 @@ TEST(ConnectionTests, heapProfilerSampling) { req.id = msgId++; // Sample every 256 bytes to ensure there are some samples. The default is // 32768, which is too high for a small example. Note that sampling is a - // random process, so there's no guarantee there will be any samples in any - // finite number of allocations. In practice the likelihood is so high that - // there shouldn't be any issues. + // random process, so there's no guarantee there will be any samples in + // any finite number of allocations. In practice the likelihood is so high + // that there shouldn't be any issues. req.samplingInterval = 256; send(conn, req); } @@ -2582,9 +2826,9 @@ TEST(ConnectionTests, heapSnapshotRemoteObject) { testObject(storedObjID, "object", "Array", "Array(3)", "array"); // Force a collection to move the heap. runtime->instrumentation().collectGarbage("test"); - // A collection should not disturb the unique ID lookup, and it should be the - // same object as before. Note that it won't have the same remote ID, because - // Hermes doesn't do uniquing. + // A collection should not disturb the unique ID lookup, and it should be + // the same object as before. Note that it won't have the same remote ID, + // because Hermes doesn't do uniquing. testObject(globalObjID, "object", "Object", "Object", nullptr); testObject(storedObjID, "object", "Array", "Array(3)", "array"); diff --git a/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp b/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp index 1bd85d669e..2b433f33ae 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp @@ -52,6 +52,7 @@ TEST(MessageTests, testDeserializeSomeFieldsInRequest) { )"); debugger::SetBreakpointByUrlRequest req(message); + EXPECT_EQ(req.toDynamic(), message); EXPECT_EQ(req.id, 10); EXPECT_EQ(req.method, "Debugger.setBreakpointByUrl"); EXPECT_EQ(req.lineNumber, 42); @@ -151,7 +152,7 @@ TEST(MessageTests, testDeserializeResponse) { } })"); debugger::SetBreakpointByUrlResponse resp(message); - + EXPECT_EQ(resp.toDynamic(), message); EXPECT_EQ(resp.id, 1); EXPECT_EQ(resp.breakpointId, "myBreakpointId"); EXPECT_EQ(resp.locations.size(), 1); @@ -455,6 +456,1072 @@ TEST(MessageTests, TestRequestHandler) { EXPECT_EQ(handler.removeReq.breakpointId, "foobar"); } +TEST(MessageTests, testEnableRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.enable" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::EnableRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::EnableRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.enable"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testDisableRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.disable" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::DisableRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::DisableRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.disable"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testEvaluateOnCallFrameRequestMinimal) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.evaluateOnCallFrame", + "params":{ + "callFrameId" : "42", + "expression": "Foo Bar" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::EvaluateOnCallFrameRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::EvaluateOnCallFrameRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.evaluateOnCallFrame"); + EXPECT_EQ(resolvedReq->callFrameId, "42"); + EXPECT_EQ(resolvedReq->expression, "Foo Bar"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->callFrameId, deserializedReq.callFrameId); + EXPECT_EQ(resolvedReq->expression, deserializedReq.expression); + + EXPECT_FALSE(resolvedReq->objectGroup.hasValue()); + EXPECT_FALSE(resolvedReq->includeCommandLineAPI.hasValue()); + EXPECT_FALSE(resolvedReq->silent.hasValue()); + EXPECT_FALSE(resolvedReq->returnByValue.hasValue()); + EXPECT_FALSE(resolvedReq->throwOnSideEffect.hasValue()); +} + +TEST(MessageTests, testEvaluateOnCallFrameRequestFull) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.evaluateOnCallFrame", + "params":{ + "callFrameId" : "42", + "expression": "Foo Bar", + "objectGroup" : "FooBarGroup", + "includeCommandLineAPI" : false, + "silent" : true, + "returnByValue" : false, + "throwOnSideEffect" : true + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::EvaluateOnCallFrameRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::EvaluateOnCallFrameRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics, resolvedReq is correct + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.evaluateOnCallFrame"); + EXPECT_EQ(resolvedReq->callFrameId, "42"); + EXPECT_EQ(resolvedReq->expression, "Foo Bar"); + + EXPECT_TRUE(resolvedReq->objectGroup.hasValue()); + EXPECT_TRUE(resolvedReq->includeCommandLineAPI.hasValue()); + EXPECT_TRUE(resolvedReq->silent.hasValue()); + EXPECT_TRUE(resolvedReq->returnByValue.hasValue()); + EXPECT_TRUE(resolvedReq->throwOnSideEffect.hasValue()); + + EXPECT_TRUE(resolvedReq->objectGroup.value() == "FooBarGroup"); + EXPECT_TRUE(resolvedReq->includeCommandLineAPI.value() == false); + EXPECT_TRUE(resolvedReq->silent.value() == true); + EXPECT_TRUE(resolvedReq->returnByValue.value() == false); + EXPECT_TRUE(resolvedReq->throwOnSideEffect.value() == true); + + // Specifics, resolvedReq and deserialized match + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->callFrameId, deserializedReq.callFrameId); + EXPECT_EQ(resolvedReq->expression, deserializedReq.expression); + EXPECT_EQ( + resolvedReq->objectGroup.value(), deserializedReq.objectGroup.value()); + EXPECT_EQ( + resolvedReq->includeCommandLineAPI.value(), + deserializedReq.includeCommandLineAPI.value()); + EXPECT_EQ(resolvedReq->silent.value(), deserializedReq.silent.value()); + EXPECT_EQ( + resolvedReq->returnByValue.value(), + deserializedReq.returnByValue.value()); + EXPECT_EQ( + resolvedReq->throwOnSideEffect.value(), + deserializedReq.throwOnSideEffect.value()); +} + +TEST(MessageTests, testPauseRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.pause" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::PauseRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::PauseRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.pause"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testRemoveBreakpointRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.removeBreakpoint", + "params":{ + "breakpointId" : "42" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::RemoveBreakpointRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::RemoveBreakpointRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.removeBreakpoint"); + EXPECT_TRUE(resolvedReq->breakpointId == "42"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->breakpointId, deserializedReq.breakpointId); +} + +TEST(MessageTests, testResumeRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.resume" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::ResumeRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::ResumeRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.resume"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testSetBreakpointRequestMinimal) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.setBreakpoint", + "params":{ + "location" : + { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + } + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetBreakpointRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + debugger::Location location; + location.scriptId = "myScriptId"; + location.lineNumber = 2; + location.columnNumber = 3; + + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpoint"); + EXPECT_EQ(resolvedReq->location.scriptId, "myScriptId"); + EXPECT_EQ(resolvedReq->location.lineNumber, 2); + EXPECT_EQ(resolvedReq->location.columnNumber, 3); + + EXPECT_FALSE(resolvedReq->condition.hasValue()); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->location.scriptId, deserializedReq.location.scriptId); + EXPECT_EQ( + resolvedReq->location.lineNumber, deserializedReq.location.lineNumber); + EXPECT_EQ( + resolvedReq->location.columnNumber, + deserializedReq.location.columnNumber); +} + +TEST(MessageTests, testSetBreakpointRequestFull) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.setBreakpoint", + "params":{ + "location" : + { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + }, + "condition": "FooBarCondition" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetBreakpointRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpoint"); + EXPECT_EQ(resolvedReq->location.scriptId, "myScriptId"); + EXPECT_EQ(resolvedReq->location.lineNumber, 2); + EXPECT_EQ(resolvedReq->location.columnNumber, 3); + + EXPECT_TRUE(resolvedReq->condition.hasValue()); + EXPECT_EQ(resolvedReq->condition.value(), "FooBarCondition"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->location.scriptId, deserializedReq.location.scriptId); + EXPECT_EQ( + resolvedReq->location.lineNumber, deserializedReq.location.lineNumber); + EXPECT_EQ( + resolvedReq->location.columnNumber, + deserializedReq.location.columnNumber); + EXPECT_EQ(resolvedReq->condition.value(), deserializedReq.condition.value()); +} + +TEST(MessageTests, testSetBreakpointByUrlRequestMinimal) { + std::string message = R"( + { + "id": 1, + "method": "Debugger.setBreakpointByUrl", + "params": { + "lineNumber": 2 + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetBreakpointByUrlRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointByUrlRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 1); + EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointByUrl"); + EXPECT_EQ(resolvedReq->lineNumber, 2); + + EXPECT_FALSE(resolvedReq->condition.hasValue()); + EXPECT_FALSE(resolvedReq->columnNumber.hasValue()); + EXPECT_FALSE(resolvedReq->url.hasValue()); + EXPECT_FALSE(resolvedReq->urlRegex.hasValue()); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->lineNumber, deserializedReq.lineNumber); +} + +TEST(MessageTests, testSetBreakpointByUrlRequestFull) { + std::string message = R"( + { + "id": 1, + "method": "Debugger.setBreakpointByUrl", + "params": { + "lineNumber": 2, + "columnNumber": 3, + "condition": "foo == 42", + "url": "http://example.com/example.js", + "urlRegex": "http://example.com/.*" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetBreakpointByUrlRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointByUrlRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 1); + EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointByUrl"); + EXPECT_EQ(resolvedReq->lineNumber, 2); + + EXPECT_TRUE(resolvedReq->condition.hasValue()); + EXPECT_EQ(resolvedReq->condition.value(), "foo == 42"); + EXPECT_TRUE(resolvedReq->columnNumber.hasValue()); + EXPECT_EQ(resolvedReq->columnNumber.value(), 3); + EXPECT_TRUE(resolvedReq->url.hasValue()); + EXPECT_EQ(resolvedReq->url.value(), "http://example.com/example.js"); + EXPECT_TRUE(resolvedReq->urlRegex.hasValue()); + EXPECT_EQ(resolvedReq->urlRegex.value(), "http://example.com/.*"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->lineNumber, deserializedReq.lineNumber); + EXPECT_EQ(resolvedReq->condition.value(), deserializedReq.condition.value()); + EXPECT_EQ( + resolvedReq->columnNumber.value(), deserializedReq.columnNumber.value()); + EXPECT_EQ(resolvedReq->url.value(), deserializedReq.url.value()); + EXPECT_EQ(resolvedReq->urlRegex.value(), deserializedReq.urlRegex.value()); +} + +TEST(MessageTests, testSetBreakpointsActiveRequest) { + std::string message = R"( + { + "id": 1, + "method": "Debugger.setBreakpointsActive", + "params": { + "active": true + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetBreakpointsActiveRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointsActiveRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 1); + EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointsActive"); + EXPECT_EQ(resolvedReq->active, true); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->active, deserializedReq.active); +} + +TEST(MessageTests, testSetInstrumentationBreakpointRequest) { + std::string message = R"( + { + "id": 1, + "method": "Debugger.setInstrumentationBreakpoint", + "params": { + "instrumentation": "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetInstrumentationBreakpointRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetInstrumentationBreakpointRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 1); + EXPECT_EQ(resolvedReq->method, "Debugger.setInstrumentationBreakpoint"); + EXPECT_EQ( + resolvedReq->instrumentation, "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->instrumentation, deserializedReq.instrumentation); +} + +TEST(MessageTests, testSetPauseOnExceptionsRequest) { + std::string message = R"( + { + "id": 1, + "method": "Debugger.setPauseOnExceptions", + "params": { + "state": "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM" + } + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::SetPauseOnExceptionsRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetPauseOnExceptionsRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 1); + EXPECT_EQ(resolvedReq->method, "Debugger.setPauseOnExceptions"); + EXPECT_EQ(resolvedReq->state, "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); + EXPECT_EQ(resolvedReq->state, deserializedReq.state); +} + +TEST(MessageTests, testStepIntoRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.stepInto" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::StepIntoRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::StepIntoRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.stepInto"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testStepOutRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.stepOut" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::StepOutRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::StepOutRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.stepOut"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testStepOverRequest) { + std::string message = R"( + { + "id": 10, + "method": "Debugger.stepOver" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::StepOverRequest *resolvedReq = + dynamic_cast(req.get()); + + // Builder returns correct type + EXPECT_FALSE(resolvedReq == nullptr); + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::StepOverRequest deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(resolvedReq->id, 10); + EXPECT_EQ(resolvedReq->method, "Debugger.stepOver"); + + EXPECT_EQ(resolvedReq->id, deserializedReq.id); + EXPECT_EQ(resolvedReq->method, deserializedReq.method); +} + +TEST(MessageTests, testEvaluateOnCallFrameResponseMinimal) { + std::string message = R"( + { + "result": + { + "result":{ + "type": "string" + } + }, + "id":2 + } + )"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::EvaluateOnCallFrameResponse deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + EXPECT_FALSE(deserializedReq.result.subtype.hasValue()); + EXPECT_FALSE(deserializedReq.result.value.hasValue()); + EXPECT_FALSE(deserializedReq.result.unserializableValue.hasValue()); + EXPECT_FALSE(deserializedReq.result.description.hasValue()); + EXPECT_FALSE(deserializedReq.result.objectId.hasValue()); + + // Specifics + EXPECT_EQ(deserializedReq.id, 2); + EXPECT_EQ(deserializedReq.result.type, "string"); +} + +TEST(MessageTests, testEvaluateOnCallFrameResponseFull) { + std::string message = R"( + { + "result": + { + "result":{ + "type": "string", + "subtype": "SuperString", + "value": {"foobarkey": "foobarval"}, + "unserializableValue": "unserializableValueVal", + "description": "A Wonderful desc", + "objectId": "AnObjectID" + } + }, + "id":2 + } + )"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::EvaluateOnCallFrameResponse deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + EXPECT_TRUE(deserializedReq.result.subtype.hasValue()); + EXPECT_TRUE(deserializedReq.result.value.hasValue()); + EXPECT_TRUE(deserializedReq.result.unserializableValue.hasValue()); + EXPECT_TRUE(deserializedReq.result.description.hasValue()); + EXPECT_TRUE(deserializedReq.result.objectId.hasValue()); + + EXPECT_EQ(deserializedReq.result.subtype.value(), "SuperString"); + EXPECT_EQ( + deserializedReq.result.value.value(), + folly::parseJson(R"({"foobarkey": "foobarval"})")); + EXPECT_EQ( + deserializedReq.result.unserializableValue.value(), + "unserializableValueVal"); + EXPECT_EQ(deserializedReq.result.description.value(), "A Wonderful desc"); + EXPECT_EQ(deserializedReq.result.objectId.value(), "AnObjectID"); + + // Specifics + EXPECT_EQ(deserializedReq.id, 2); + EXPECT_EQ(deserializedReq.result.type, "string"); +} + +TEST(MessageTests, testSetBreakpointByUrlResponse) { + std::string message = R"({ + "id": 1, + "result":{ + "breakpointId": "myBreakpointId", + "locations": [ + { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + } + ] + } + })"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointByUrlResponse deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(deserializedReq.id, 1); + EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId"); + EXPECT_EQ(deserializedReq.locations.size(), 1); + EXPECT_EQ(deserializedReq.locations[0].lineNumber, 2); + EXPECT_EQ(deserializedReq.locations[0].columnNumber, 3); + EXPECT_EQ(deserializedReq.locations[0].scriptId, "myScriptId"); +} + +TEST(MessageTests, testSetBreakpointResponse) { + std::string message = R"({ + "id": 1, + "result":{ + "breakpointId": "myBreakpointId", + "actualLocation": + { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + } + } + })"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetBreakpointResponse deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId"); + EXPECT_EQ(deserializedReq.actualLocation.lineNumber, 2); + EXPECT_EQ(deserializedReq.actualLocation.columnNumber, 3); + EXPECT_EQ(deserializedReq.actualLocation.scriptId, "myScriptId"); + EXPECT_EQ(deserializedReq.id, 1); +} + +TEST(MessageTests, testSetInstrumentationBreakpointResponse) { + std::string message = R"({ + "id": 1, + "result":{ + "breakpointId": "myBreakpointId" + } + })"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::SetInstrumentationBreakpointResponse deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId"); + EXPECT_EQ(deserializedReq.id, 1); +} + +TEST(MessageTests, testBreakpointResolvedNotification) { + std::string message = R"( + { + "method": "Debugger.breakpointResolved", + "params":{ + "breakpointId" : "42", + "location": + { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + } + } + } + )"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::BreakpointResolvedNotification deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(deserializedReq.method, "Debugger.breakpointResolved"); + EXPECT_EQ(deserializedReq.breakpointId, "42"); + EXPECT_EQ(deserializedReq.location.lineNumber, 2); + EXPECT_EQ(deserializedReq.location.columnNumber, 3); + EXPECT_EQ(deserializedReq.location.scriptId, "myScriptId"); +} + +TEST(MessageTests, testPauseNotificationMinimal) { + std::string message = R"( + { + "method": "Debugger.paused", + "params":{ + "reason": "Some Valid Reason", + "callFrames":[ + { + "callFrameId": "aCallFrameId", + "functionName": "aFunctionName", + "location":{ + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + }, + "url": "aURL", + "scopeChain": [ + { + "type": "aType", + "object": { + "type": "aRemoteObjectType" + } + } + ], + "this": { + "type": "aType" + } + } + ] + } + } + )"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::PausedNotification deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + EXPECT_FALSE(deserializedReq.callFrames[0].functionLocation.hasValue()); + EXPECT_FALSE(deserializedReq.callFrames[0].returnValue.hasValue()); + EXPECT_FALSE(deserializedReq.asyncStackTrace.hasValue()); + EXPECT_FALSE(deserializedReq.hitBreakpoints.hasValue()); + EXPECT_FALSE(deserializedReq.data.hasValue()); + + // Specifics + EXPECT_EQ(deserializedReq.method, "Debugger.paused"); + EXPECT_EQ(deserializedReq.reason, "Some Valid Reason"); + EXPECT_EQ(deserializedReq.callFrames[0].functionName, "aFunctionName"); + EXPECT_EQ(deserializedReq.callFrames[0].callFrameId, "aCallFrameId"); + EXPECT_EQ(deserializedReq.callFrames[0].url, "aURL"); + EXPECT_EQ(deserializedReq.callFrames[0].location.lineNumber, 2); + EXPECT_EQ(deserializedReq.callFrames[0].location.columnNumber, 3); + EXPECT_EQ(deserializedReq.callFrames[0].location.scriptId, "myScriptId"); + EXPECT_EQ(deserializedReq.callFrames[0].scopeChain[0].type, "aType"); + EXPECT_EQ( + deserializedReq.callFrames[0].scopeChain[0].object.type, + "aRemoteObjectType"); + EXPECT_EQ(deserializedReq.callFrames[0].thisObj.type, "aType"); +} + +TEST(MessageTests, testPauseNotificationFull) { + std::string message = R"( + { + "method": "Debugger.paused", + "params":{ + "reason": "Some Valid Reason", + "callFrames":[ + { + "functionLocation": { + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + }, + "returnValue" : { + "type": "aRemoteObjectType", + "subtype": "subtype", + "className":"className", + "value": "value", + "unserializableValue": "unserializableValue", + "description": "description", + "objectId": "objectId" + }, + "callFrameId": "aCallFrameId", + "functionName": "aFunctionName", + "location":{ + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId" + }, + "url": "aURL", + "scopeChain": [ + { + "type": "aType", + "object": { + "type": "aRemoteObjectType" + } + } + ], + "this": { + "type": "aType" + } + } + ], + "data": {"dataKey": "dataVal"}, + "hitBreakpoints": [ + "foo","bar" + ], + "asyncStackTrace":{ + "description": "an asyncStackTrace Desc", + "callFrames":[ + { + "functionName": "aFunctionName", + "lineNumber": 2, + "columnNumber": 3, + "scriptId": "myScriptId", + "url": "aURL" + } + ] + } + } + } + )"; + + folly::Optional functionLocation; + folly::Optional returnValue; + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::PausedNotification deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Check optionnals + // ---------------- + EXPECT_TRUE(deserializedReq.callFrames[0].functionLocation.hasValue()); + EXPECT_TRUE(deserializedReq.callFrames[0].returnValue.hasValue()); + EXPECT_TRUE(deserializedReq.asyncStackTrace.hasValue()); + EXPECT_TRUE(deserializedReq.hitBreakpoints.hasValue()); + EXPECT_TRUE(deserializedReq.data.hasValue()); + + EXPECT_TRUE( + deserializedReq.callFrames[0].returnValue.value().subtype.hasValue()); + EXPECT_TRUE( + deserializedReq.callFrames[0].returnValue.value().className.hasValue()); + EXPECT_TRUE(deserializedReq.callFrames[0] + .returnValue.value() + .unserializableValue.hasValue()); + EXPECT_TRUE( + deserializedReq.callFrames[0].returnValue.value().value.hasValue()); + EXPECT_TRUE( + deserializedReq.callFrames[0].returnValue.value().description.hasValue()); + EXPECT_TRUE( + deserializedReq.callFrames[0].returnValue.value().objectId.hasValue()); + + // Check optionnals Values + // ----------------------- + EXPECT_EQ( + deserializedReq.callFrames[0].functionLocation.value().lineNumber, 2); + EXPECT_EQ( + deserializedReq.callFrames[0].functionLocation.value().columnNumber, 3); + EXPECT_EQ( + deserializedReq.callFrames[0].functionLocation.value().scriptId, + "myScriptId"); + + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().type, + "aRemoteObjectType"); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().subtype.hasValue(), + true); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().subtype.value(), + "subtype"); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().className.hasValue(), + true); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().className.value(), + "className"); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().value.hasValue(), true); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().value.value(), "value"); + EXPECT_EQ( + deserializedReq.callFrames[0] + .returnValue.value() + .unserializableValue.hasValue(), + true); + EXPECT_EQ( + deserializedReq.callFrames[0] + .returnValue.value() + .unserializableValue.value(), + "unserializableValue"); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().description.hasValue(), + true); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().description.value(), + "description"); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().objectId.hasValue(), + true); + EXPECT_EQ( + deserializedReq.callFrames[0].returnValue.value().objectId.value(), + "objectId"); + + EXPECT_EQ(deserializedReq.hitBreakpoints.value()[0], "foo"); + EXPECT_EQ(deserializedReq.hitBreakpoints.value()[1], "bar"); + + EXPECT_EQ( + deserializedReq.data.value(), + folly::parseJson(R"({"dataKey": "dataVal"})")); + + // Check Compulsory + // ---------------- + EXPECT_EQ(deserializedReq.method, "Debugger.paused"); + EXPECT_EQ(deserializedReq.reason, "Some Valid Reason"); + EXPECT_EQ(deserializedReq.callFrames[0].functionName, "aFunctionName"); + EXPECT_EQ(deserializedReq.callFrames[0].callFrameId, "aCallFrameId"); + EXPECT_EQ(deserializedReq.callFrames[0].url, "aURL"); + EXPECT_EQ(deserializedReq.callFrames[0].location.lineNumber, 2); + EXPECT_EQ(deserializedReq.callFrames[0].location.columnNumber, 3); + EXPECT_EQ(deserializedReq.callFrames[0].location.scriptId, "myScriptId"); + EXPECT_EQ(deserializedReq.callFrames[0].scopeChain[0].type, "aType"); + EXPECT_EQ( + deserializedReq.callFrames[0].scopeChain[0].object.type, + "aRemoteObjectType"); + EXPECT_EQ(deserializedReq.callFrames[0].thisObj.type, "aType"); +} + +TEST(MessageTests, testResumedNotification) { + std::string message = R"( + { + "method": "Debugger.resumed" + } + )"; + + // Serialize and Deserialize are inverse functions + dynamic messageJSON = folly::parseJson(message); + debugger::ResumedNotification deserializedReq(messageJSON); + EXPECT_EQ(deserializedReq.toDynamic(), messageJSON); + + // Specifics + EXPECT_EQ(deserializedReq.method, "Debugger.resumed"); +} + } // namespace message } // namespace chrome } // namespace inspector diff --git a/ReactCommon/hermes/inspector/tools/message_types.txt b/ReactCommon/hermes/inspector/tools/message_types.txt index 6267e82ee0..8921a82925 100644 --- a/ReactCommon/hermes/inspector/tools/message_types.txt +++ b/ReactCommon/hermes/inspector/tools/message_types.txt @@ -28,6 +28,7 @@ HeapProfiler.heapStatsUpdate HeapProfiler.lastSeenObjectId HeapProfiler.getObjectByHeapObjectId HeapProfiler.getHeapObjectId +Runtime.callFunctionOn Runtime.consoleAPICalled Runtime.evaluate Runtime.executionContextCreated diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index 4127a7bc70..a40fe8664d 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -30,6 +30,8 @@ std::string kindToString(const Value& v, Runtime* rt = nullptr) { return "a number"; } else if (v.isString()) { return "a string"; + } else if (v.isSymbol()) { + return "a symbol"; } else { assert(v.isObject() && "Expecting object."); return rt != nullptr && v.getObject(*rt).isFunction(*rt) ? "a function" diff --git a/ReactCommon/jsi/jsi/jsi.h b/ReactCommon/jsi/jsi/jsi.h index 1e8040d05b..52b98f68ef 100644 --- a/ReactCommon/jsi/jsi/jsi.h +++ b/ReactCommon/jsi/jsi/jsi.h @@ -406,6 +406,7 @@ class JSI_EXPORT PropNameID : public Pointer { } /// Create a PropNameID from utf8 values. The data is copied. + /// Results are undefined if \p utf8 contains invalid code points. static PropNameID forUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { return runtime.createPropNameIDFromUtf8(utf8, length); @@ -413,6 +414,7 @@ class JSI_EXPORT PropNameID : public Pointer { /// Create a PropNameID from utf8-encoded octets stored in a /// std::string. The string data is transformed and copied. + /// Results are undefined if \p utf8 contains invalid code points. static PropNameID forUtf8(Runtime& runtime, const std::string& utf8) { return runtime.createPropNameIDFromUtf8( reinterpret_cast(utf8.data()), utf8.size()); @@ -502,14 +504,16 @@ class JSI_EXPORT String : public Pointer { } /// Create a JS string from utf8-encoded octets. The string data is - /// transformed and copied. + /// transformed and copied. Results are undefined if \p utf8 contains invalid + /// code points. static String createFromUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) { return runtime.createStringFromUtf8(utf8, length); } /// Create a JS string from utf8-encoded octets stored in a - /// std::string. The string data is transformed and copied. + /// std::string. The string data is transformed and copied. Results are + /// undefined if \p utf8 contains invalid code points. static String createFromUtf8(Runtime& runtime, const std::string& utf8) { return runtime.createStringFromUtf8( reinterpret_cast(utf8.data()), utf8.length()); diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 30501096ec..4b0f7c76f2 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -827,11 +827,11 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { auto _textAttributes = folly::dynamic::object(); if (textAttributes.foregroundColor) { _textAttributes( - "foregroundColor", toDynamic(textAttributes.foregroundColor)); + "foregroundColor", toAndroidRepr(textAttributes.foregroundColor)); } if (textAttributes.backgroundColor) { _textAttributes( - "backgroundColor", toDynamic(textAttributes.backgroundColor)); + "backgroundColor", toAndroidRepr(textAttributes.backgroundColor)); } if (!std::isnan(textAttributes.opacity)) { _textAttributes("opacity", textAttributes.opacity); @@ -876,7 +876,8 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { // Decoration if (textAttributes.textDecorationColor) { _textAttributes( - "textDecorationColor", toDynamic(textAttributes.textDecorationColor)); + "textDecorationColor", + toAndroidRepr(textAttributes.textDecorationColor)); } if (textAttributes.textDecorationLineType.has_value()) { _textAttributes( @@ -894,7 +895,7 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { } if (textAttributes.textShadowColor) { _textAttributes( - "textShadowColor", toDynamic(textAttributes.textShadowColor)); + "textShadowColor", toAndroidRepr(textAttributes.textShadowColor)); } // Special if (textAttributes.isHighlighted.has_value()) { @@ -1036,11 +1037,11 @@ inline MapBuffer toMapBuffer(const TextAttributes &textAttributes) { auto builder = MapBufferBuilder(); if (textAttributes.foregroundColor) { builder.putInt( - TA_KEY_FOREGROUND_COLOR, toMapBuffer(textAttributes.foregroundColor)); + TA_KEY_FOREGROUND_COLOR, toAndroidRepr(textAttributes.foregroundColor)); } if (textAttributes.backgroundColor) { builder.putInt( - TA_KEY_BACKGROUND_COLOR, toMapBuffer(textAttributes.backgroundColor)); + TA_KEY_BACKGROUND_COLOR, toAndroidRepr(textAttributes.backgroundColor)); } if (!std::isnan(textAttributes.opacity)) { builder.putDouble(TA_KEY_OPACITY, textAttributes.opacity); @@ -1087,7 +1088,7 @@ inline MapBuffer toMapBuffer(const TextAttributes &textAttributes) { if (textAttributes.textDecorationColor) { builder.putInt( TA_KEY_TEXT_DECORATION_COLOR, - toMapBuffer(textAttributes.textDecorationColor)); + toAndroidRepr(textAttributes.textDecorationColor)); } if (textAttributes.textDecorationLineType.has_value()) { builder.putString( @@ -1107,7 +1108,8 @@ inline MapBuffer toMapBuffer(const TextAttributes &textAttributes) { } if (textAttributes.textShadowColor) { builder.putInt( - TA_KEY_TEXT_SHADOW_COLOR, toMapBuffer(textAttributes.textShadowColor)); + TA_KEY_TEXT_SHADOW_COLOR, + toAndroidRepr(textAttributes.textShadowColor)); } // Special if (textAttributes.isHighlighted.has_value()) { diff --git a/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h b/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h index e3e504160a..0ff4d14d9a 100644 --- a/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h +++ b/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h @@ -15,7 +15,7 @@ namespace facebook { namespace react { /* - * Descriptor for component. + * Descriptor for component. */ class ModalHostViewComponentDescriptor final diff --git a/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h b/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h index 054074229b..5558e0ef12 100644 --- a/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h +++ b/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h @@ -18,7 +18,7 @@ namespace react { extern const char ModalHostViewComponentName[]; /* - * `ShadowNode` for component. + * `ShadowNode` for component. */ class ModalHostViewShadowNode final : public ConcreteViewShadowNode< ModalHostViewComponentName, diff --git a/ReactCommon/react/renderer/components/modal/ModalHostViewState.h b/ReactCommon/react/renderer/components/modal/ModalHostViewState.h index de9b9537fe..2afe22358d 100644 --- a/ReactCommon/react/renderer/components/modal/ModalHostViewState.h +++ b/ReactCommon/react/renderer/components/modal/ModalHostViewState.h @@ -21,7 +21,7 @@ namespace facebook { namespace react { /* - * State for component. + * State for component. */ class ModalHostViewState final { public: diff --git a/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h b/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h index 7f7ee33e54..dc3c147477 100644 --- a/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h +++ b/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h @@ -20,7 +20,7 @@ inline folly::dynamic toDynamic(AndroidProgressBarProps const &props) { serializedProps["indeterminate"] = props.indeterminate; serializedProps["progress"] = props.progress; serializedProps["animating"] = props.animating; - serializedProps["color"] = toDynamic(props.color); + serializedProps["color"] = toAndroidRepr(props.color); serializedProps["testID"] = props.testID; return serializedProps; } diff --git a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index 100186165e..1075179f1a 100644 --- a/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -266,7 +266,7 @@ folly::dynamic AndroidTextInputProps::getDynamic() const { props["numberOfLines"] = numberOfLines; props["disableFullscreenUI"] = disableFullscreenUI; props["textBreakStrategy"] = textBreakStrategy; - props["underlineColorAndroid"] = toDynamic(underlineColorAndroid); + props["underlineColorAndroid"] = toAndroidRepr(underlineColorAndroid); props["inlineImageLeft"] = inlineImageLeft; props["inlineImagePadding"] = inlineImagePadding; props["importantForAutofill"] = importantForAutofill; @@ -282,9 +282,9 @@ folly::dynamic AndroidTextInputProps::getDynamic() const { props["maxLength"] = maxLength; props["multiline"] = multiline; props["placeholder"] = placeholder; - props["placeholderTextColor"] = toDynamic(placeholderTextColor); + props["placeholderTextColor"] = toAndroidRepr(placeholderTextColor); props["secureTextEntry"] = secureTextEntry; - props["selectionColor"] = toDynamic(selectionColor); + props["selectionColor"] = toAndroidRepr(selectionColor); props["selection"] = toDynamic(selection); props["value"] = value; props["defaultValue"] = defaultValue; @@ -292,14 +292,14 @@ folly::dynamic AndroidTextInputProps::getDynamic() const { props["blurOnSubmit"] = blurOnSubmit; props["caretHidden"] = caretHidden; props["contextMenuHidden"] = contextMenuHidden; - props["textShadowColor"] = toDynamic(textShadowColor); + props["textShadowColor"] = toAndroidRepr(textShadowColor); props["textShadowRadius"] = textShadowRadius; props["textDecorationLine"] = textDecorationLine; props["fontStyle"] = fontStyle; props["textShadowOffset"] = toDynamic(textShadowOffset); props["lineHeight"] = lineHeight; props["textTransform"] = textTransform; - props["color"] = toDynamic(color); + props["color"] = toAndroidRepr(color); props["letterSpacing"] = letterSpacing; props["fontSize"] = fontSize; props["textAlign"] = textAlign; @@ -307,7 +307,7 @@ folly::dynamic AndroidTextInputProps::getDynamic() const { props["fontWeight"] = fontWeight; props["fontFamily"] = fontFamily; props["textAlignVertical"] = textAlignVertical; - props["cursorColor"] = toDynamic(cursorColor); + props["cursorColor"] = toAndroidRepr(cursorColor); props["mostRecentEventCount"] = mostRecentEventCount; props["text"] = text; diff --git a/ReactCommon/react/renderer/components/view/ViewProps.cpp b/ReactCommon/react/renderer/components/view/ViewProps.cpp index bcc5390770..9c694fd501 100644 --- a/ReactCommon/react/renderer/components/view/ViewProps.cpp +++ b/ReactCommon/react/renderer/components/view/ViewProps.cpp @@ -125,24 +125,7 @@ ViewProps::ViewProps( "onLayout", sourceProps.onLayout, {})), - pointerEnter(convertRawProp( - context, - rawProps, - "pointerenter", - sourceProps.pointerEnter, - {})), - pointerLeave(convertRawProp( - context, - rawProps, - "pointerleave", - sourceProps.pointerLeave, - {})), - pointerMove(convertRawProp( - context, - rawProps, - "pointermove", - sourceProps.pointerMove, - {})), + events(convertRawProp(context, rawProps, sourceProps.events, {})), collapsable(convertRawProp( context, rawProps, diff --git a/ReactCommon/react/renderer/components/view/ViewProps.h b/ReactCommon/react/renderer/components/view/ViewProps.h index 8a1fe7c867..7350465a71 100644 --- a/ReactCommon/react/renderer/components/view/ViewProps.h +++ b/ReactCommon/react/renderer/components/view/ViewProps.h @@ -63,11 +63,7 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps { EdgeInsets hitSlop{}; bool onLayout{}; - bool pointerEnter{}; - - bool pointerLeave{}; - - bool pointerMove{}; + ViewEvents events{}; bool collapsable{true}; diff --git a/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 661858cba1..bbc05ea771 100644 --- a/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -48,8 +48,8 @@ void ViewShadowNode::initialize() noexcept { bool formsView = formsStackingContext || isColorMeaningful(viewProps.backgroundColor) || - isColorMeaningful(viewProps.foregroundColor) || viewProps.pointerEnter || - viewProps.pointerLeave || viewProps.pointerMove || + isColorMeaningful(viewProps.foregroundColor) || + viewProps.events.bits.any() || !(viewProps.yogaStyle.border() == YGStyle::Edges{}) || !viewProps.testId.empty(); diff --git a/ReactCommon/react/renderer/components/view/primitives.h b/ReactCommon/react/renderer/components/view/primitives.h index a72e9210a3..112595e4fc 100644 --- a/ReactCommon/react/renderer/components/view/primitives.h +++ b/ReactCommon/react/renderer/components/view/primitives.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -19,6 +20,46 @@ namespace react { enum class PointerEventsMode { Auto, None, BoxNone, BoxOnly }; +struct ViewEvents { + std::bitset<32> bits{}; + + enum class Offset : std::size_t { + // Pointer events + PointerEnter = 0, + PointerMove = 1, + PointerLeave = 2, + + // PanResponder callbacks + MoveShouldSetResponder = 3, + MoveShouldSetResponderCapture = 4, + StartShouldSetResponder = 5, + StartShouldSetResponderCapture = 6, + ResponderGrant = 7, + ResponderReject = 8, + ResponderStart = 9, + ResponderEnd = 10, + ResponderRelease = 11, + ResponderMove = 12, + ResponderTerminate = 13, + ResponderTerminationRequest = 14, + ShouldBlockNativeResponder = 15, + + // Touch events + TouchStart = 16, + TouchMove = 17, + TouchEnd = 18, + TouchCancel = 19, + }; + + constexpr bool operator[](const Offset offset) const { + return bits[static_cast(offset)]; + } + + std::bitset<32>::reference operator[](const Offset offset) { + return bits[static_cast(offset)]; + } +}; + enum class BackfaceVisibility { Auto, Visible, Hidden }; enum class BorderStyle { Solid, Dotted, Dashed }; diff --git a/ReactCommon/react/renderer/components/view/propsConversions.h b/ReactCommon/react/renderer/components/view/propsConversions.h index 6de017d376..9db511c8dc 100644 --- a/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/ReactCommon/react/renderer/components/view/propsConversions.h @@ -465,5 +465,141 @@ static inline CascadedRectangleEdges convertRawProp( return result; } +static inline ViewEvents convertRawProp( + const PropsParserContext &context, + RawProps const &rawProps, + ViewEvents const &sourceValue, + ViewEvents const &defaultValue) { + ViewEvents result{}; + using Offset = ViewEvents::Offset; + + result[Offset::PointerEnter] = convertRawProp( + context, + rawProps, + "onPointerEnter", + sourceValue[Offset::PointerEnter], + defaultValue[Offset::PointerEnter]); + result[Offset::PointerMove] = convertRawProp( + context, + rawProps, + "onPointerMove", + sourceValue[Offset::PointerMove], + defaultValue[Offset::PointerMove]); + result[Offset::PointerLeave] = convertRawProp( + context, + rawProps, + "onPointerLeave", + sourceValue[Offset::PointerLeave], + defaultValue[Offset::PointerLeave]); + + // PanResponder callbacks + result[Offset::MoveShouldSetResponder] = convertRawProp( + context, + rawProps, + "onMoveShouldSetResponder", + sourceValue[Offset::MoveShouldSetResponder], + defaultValue[Offset::MoveShouldSetResponder]); + result[Offset::MoveShouldSetResponderCapture] = convertRawProp( + context, + rawProps, + "onMoveShouldSetResponderCapture", + sourceValue[Offset::MoveShouldSetResponderCapture], + defaultValue[Offset::MoveShouldSetResponderCapture]); + result[Offset::StartShouldSetResponder] = convertRawProp( + context, + rawProps, + "onStartShouldSetResponder", + sourceValue[Offset::StartShouldSetResponder], + defaultValue[Offset::StartShouldSetResponder]); + result[Offset::StartShouldSetResponderCapture] = convertRawProp( + context, + rawProps, + "onStartShouldSetResponderCapture", + sourceValue[Offset::StartShouldSetResponderCapture], + defaultValue[Offset::StartShouldSetResponderCapture]); + result[Offset::ResponderGrant] = convertRawProp( + context, + rawProps, + "onResponderGrant", + sourceValue[Offset::ResponderGrant], + defaultValue[Offset::ResponderGrant]); + result[Offset::ResponderReject] = convertRawProp( + context, + rawProps, + "onResponderReject", + sourceValue[Offset::ResponderReject], + defaultValue[Offset::ResponderReject]); + result[Offset::ResponderStart] = convertRawProp( + context, + rawProps, + "onResponderStart", + sourceValue[Offset::ResponderStart], + defaultValue[Offset::ResponderStart]); + result[Offset::ResponderEnd] = convertRawProp( + context, + rawProps, + "onResponderEnd", + sourceValue[Offset::ResponderEnd], + defaultValue[Offset::ResponderEnd]); + result[Offset::ResponderRelease] = convertRawProp( + context, + rawProps, + "onResponderRelease", + sourceValue[Offset::ResponderRelease], + defaultValue[Offset::ResponderRelease]); + result[Offset::ResponderMove] = convertRawProp( + context, + rawProps, + "onResponderMove", + sourceValue[Offset::ResponderMove], + defaultValue[Offset::ResponderMove]); + result[Offset::ResponderTerminate] = convertRawProp( + context, + rawProps, + "onResponderTerminate", + sourceValue[Offset::ResponderTerminate], + defaultValue[Offset::ResponderTerminate]); + result[Offset::ResponderTerminationRequest] = convertRawProp( + context, + rawProps, + "onResponderTerminationRequest", + sourceValue[Offset::ResponderTerminationRequest], + defaultValue[Offset::ResponderTerminationRequest]); + result[Offset::ShouldBlockNativeResponder] = convertRawProp( + context, + rawProps, + "onShouldBlockNativeResponder", + sourceValue[Offset::ShouldBlockNativeResponder], + defaultValue[Offset::ShouldBlockNativeResponder]); + + // Touch events + result[Offset::TouchStart] = convertRawProp( + context, + rawProps, + "onTouchStart", + sourceValue[Offset::TouchStart], + defaultValue[Offset::TouchStart]); + result[Offset::TouchMove] = convertRawProp( + context, + rawProps, + "onTouchMove", + sourceValue[Offset::TouchMove], + defaultValue[Offset::TouchMove]); + result[Offset::TouchEnd] = convertRawProp( + context, + rawProps, + "onTouchEnd", + sourceValue[Offset::TouchEnd], + defaultValue[Offset::TouchEnd]); + result[Offset::TouchCancel] = convertRawProp( + context, + rawProps, + "onTouchCancel", + sourceValue[Offset::TouchCancel], + defaultValue[Offset::TouchCancel]); + + return result; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 7be574ed07..baeb790a72 100644 --- a/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -179,6 +179,18 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { } protected: + /* + * Called immediatelly after `ShadowNode` is created or cloned. + * + * Override this method to pass information from custom `ComponentDescriptor` + * to new instance of `ShadowNode`. + * + * Example usages: + * - Inject image manager to `ImageShadowNode` in + * `ImageComponentDescriptor`. + * - Set `ShadowNode`'s size from state in + * `ModalHostViewComponentDescriptor`. + */ virtual void adopt(ShadowNode::Unshared const &shadowNode) const { // Default implementation does nothing. react_native_assert( diff --git a/ReactCommon/react/renderer/graphics/conversions.h b/ReactCommon/react/renderer/graphics/conversions.h index fba02b74d2..8e28bdcb4d 100644 --- a/ReactCommon/react/renderer/graphics/conversions.h +++ b/ReactCommon/react/renderer/graphics/conversions.h @@ -51,17 +51,7 @@ inline void fromRawValue( #ifdef ANDROID -inline folly::dynamic toDynamic(const SharedColor &color) { - ColorComponents components = colorComponentsFromColor(color); - auto ratio = 255.f; - return ( - ((int)round(components.alpha * ratio) & 0xff) << 24 | - ((int)round(components.red * ratio) & 0xff) << 16 | - ((int)round(components.green * ratio) & 0xff) << 8 | - ((int)round(components.blue * ratio) & 0xff)); -} - -inline int toMapBuffer(const SharedColor &color) { +inline int toAndroidRepr(const SharedColor &color) { ColorComponents components = colorComponentsFromColor(color); auto ratio = 255.f; return ( diff --git a/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp b/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp index 3f3a6de852..94d8c87bd3 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp +++ b/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp @@ -33,11 +33,11 @@ MapBuffer::MapBuffer(std::vector data) : bytes_(std::move(data)) { } } -uint32_t MapBuffer::getKeyBucket(Key key) const { - uint32_t lo = 0; - uint32_t hi = count_ - 1; +int32_t MapBuffer::getKeyBucket(Key key) const { + int32_t lo = 0; + int32_t hi = count_ - 1; while (lo <= hi) { - uint32_t mid = (lo + hi) >> 1; + int32_t mid = (lo + hi) >> 1; Key midVal = *reinterpret_cast(bytes_.data() + bucketOffset(mid)); @@ -112,7 +112,7 @@ MapBuffer MapBuffer::getMapBuffer(Key key) const { return MapBuffer(std::move(value)); } -uint32_t MapBuffer::size() const { +size_t MapBuffer::size() const { return bytes_.size(); } diff --git a/ReactCommon/react/renderer/mapbuffer/MapBuffer.h b/ReactCommon/react/renderer/mapbuffer/MapBuffer.h index 037e3e8ae3..fe68305851 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBuffer.h +++ b/ReactCommon/react/renderer/mapbuffer/MapBuffer.h @@ -80,7 +80,8 @@ class MapBuffer { uint32_t bufferSize; // Amount of bytes used to store the map in memory }; - struct __attribute__((__packed__)) Bucket { +#pragma pack(push, 1) + struct Bucket { Key key; uint16_t type; uint64_t data; @@ -88,6 +89,7 @@ class MapBuffer { Bucket(Key key, uint16_t type, uint64_t data) : key(key), type(type), data(data) {} }; +#pragma pack(pop) static_assert(sizeof(Header) == 8, "MapBuffer header size is incorrect."); static_assert(sizeof(Bucket) == 12, "MapBuffer bucket size is incorrect."); @@ -124,7 +126,7 @@ class MapBuffer { // TODO T83483191: review this declaration MapBuffer getMapBuffer(MapBuffer::Key key) const; - uint32_t size() const; + size_t size() const; uint8_t const *data() const; @@ -140,7 +142,7 @@ class MapBuffer { // returns the relative offset of the first byte of dynamic data int32_t getDynamicDataOffset() const; - uint32_t getKeyBucket(MapBuffer::Key key) const; + int32_t getKeyBucket(MapBuffer::Key key) const; friend ReadableMapBuffer; }; diff --git a/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp b/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp index 3d06fba880..9388343701 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp +++ b/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp @@ -14,7 +14,7 @@ namespace facebook { namespace react { constexpr uint32_t INT_SIZE = sizeof(uint32_t); -constexpr double DOUBLE_SIZE = sizeof(double); +constexpr uint32_t DOUBLE_SIZE = sizeof(double); constexpr uint32_t MAX_BUCKET_VALUE_SIZE = sizeof(uint64_t); MapBuffer MapBufferBuilder::EMPTY() { @@ -23,6 +23,8 @@ MapBuffer MapBufferBuilder::EMPTY() { MapBufferBuilder::MapBufferBuilder(uint32_t initialSize) { buckets_.reserve(initialSize); + header_.count = 0; + header_.bufferSize = 0; } void MapBufferBuilder::storeKeyValue( @@ -76,7 +78,7 @@ void MapBufferBuilder::putInt(MapBuffer::Key key, int32_t value) { } void MapBufferBuilder::putString(MapBuffer::Key key, std::string const &value) { - int32_t strSize = value.size(); + auto strSize = value.size(); const char *strData = value.data(); // format [length of string (int)] + [Array of Characters in the string] @@ -94,7 +96,7 @@ void MapBufferBuilder::putString(MapBuffer::Key key, std::string const &value) { } void MapBufferBuilder::putMapBuffer(MapBuffer::Key key, MapBuffer const &map) { - int32_t mapBufferSize = map.size(); + auto mapBufferSize = map.size(); auto offset = dynamicData_.size(); @@ -122,9 +124,9 @@ MapBuffer MapBufferBuilder::build() { // Create buffer: [header] + [key, values] + [dynamic data] auto bucketSize = buckets_.size() * sizeof(MapBuffer::Bucket); auto headerSize = sizeof(MapBuffer::Header); - uint32_t bufferSize = headerSize + bucketSize + dynamicData_.size(); + auto bufferSize = headerSize + bucketSize + dynamicData_.size(); - header_.bufferSize = bufferSize; + header_.bufferSize = static_cast(bufferSize); if (needsSort_) { std::sort(buckets_.begin(), buckets_.end(), compareBuckets); diff --git a/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h b/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h index 154c5daa63..aa8ae87940 100644 --- a/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h +++ b/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h @@ -38,7 +38,7 @@ class MapBufferBuilder { MapBuffer build(); private: - MapBuffer::Header header_ = {.count = 0, .bufferSize = 0}; + MapBuffer::Header header_; std::vector buckets_{}; diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp index ed9822ce87..4e63dc68ea 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp @@ -46,7 +46,7 @@ std::shared_ptr RuntimeScheduler::scheduleTask( } bool RuntimeScheduler::getShouldYield() const noexcept { - return shouldYield_; + return runtimeAccessRequests_ > 0; } bool RuntimeScheduler::getIsSynchronous() const noexcept { @@ -65,13 +65,17 @@ RuntimeSchedulerTimePoint RuntimeScheduler::now() const noexcept { return now_(); } +void RuntimeScheduler::setEnableYielding(bool enableYielding) { + enableYielding_ = enableYielding; +} + void RuntimeScheduler::executeNowOnTheSameThread( std::function callback) { - shouldYield_ = true; + runtimeAccessRequests_ += 1; executeSynchronouslyOnSameThread_CAN_DEADLOCK( runtimeExecutor_, [this, callback = std::move(callback)](jsi::Runtime &runtime) { - shouldYield_ = false; + runtimeAccessRequests_ -= 1; isSynchronous_ = true; callback(runtime); isSynchronous_ = false; @@ -83,7 +87,7 @@ void RuntimeScheduler::executeNowOnTheSameThread( scheduleWorkLoopIfNecessary(); } -void RuntimeScheduler::callImmediates(jsi::Runtime &runtime) { +void RuntimeScheduler::callExpiredTasks(jsi::Runtime &runtime) { auto previousPriority = currentPriority_; try { while (!taskQueue_.empty()) { diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h index 339654584a..35a503644c 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h @@ -97,15 +97,14 @@ class RuntimeScheduler final { RuntimeSchedulerTimePoint now() const noexcept; /* - * Immediate is a task that is expired and should have been already executed - * or has priority set to Immediate. Designed to be called in the event - * pipeline after an event is dispatched to React. React may schedule events - * with immediate priority which need to be handled before the next event is - * sent to React. + * Expired task is a task that should have been already executed. Designed to + * be called in the event pipeline after an event is dispatched to React. + * React may schedule events with immediate priority which need to be handled + * before the next event is sent to React. * * Thread synchronization must be enforced externally. */ - void callImmediates(jsi::Runtime &runtime); + void callExpiredTasks(jsi::Runtime &runtime); private: mutable std::priority_queue< @@ -116,7 +115,6 @@ class RuntimeScheduler final { RuntimeExecutor const runtimeExecutor_; mutable SchedulerPriority currentPriority_{SchedulerPriority::NormalPriority}; - mutable std::atomic_bool shouldYield_{false}; /* * Counter indicating how many access to the runtime have been requested. @@ -145,6 +143,15 @@ class RuntimeScheduler final { */ mutable std::atomic_bool isWorkLoopScheduled_{false}; + /* + * Flag indicating if yielding is enabled. + * + * If set to true and Concurrent Mode is enabled on the surface, + * React Native will ask React to yield in case any work has been scheduled. + * Default value is false + */ + bool enableYielding_{false}; + /* * This flag is set while performing work, to prevent re-entrancy. */ diff --git a/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp b/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp index ad7c33a1e9..cc1603c06f 100644 --- a/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp @@ -43,6 +43,7 @@ class RuntimeSchedulerTest : public testing::Test { runtimeScheduler_ = std::make_unique(runtimeExecutor, stubNow); + runtimeScheduler_->setEnableYielding(true); } jsi::Function createHostFunctionFromLambda( @@ -317,13 +318,14 @@ TEST_F(RuntimeSchedulerTest, getCurrentPriorityLevel) { } TEST_F(RuntimeSchedulerTest, scheduleWork) { + runtimeScheduler_->setEnableYielding(false); bool wasCalled = false; runtimeScheduler_->scheduleWork( [&](jsi::Runtime const &) { wasCalled = true; }); EXPECT_FALSE(wasCalled); - EXPECT_TRUE(runtimeScheduler_->getShouldYield()); + EXPECT_FALSE(runtimeScheduler_->getShouldYield()); EXPECT_EQ(stubQueue_->size(), 1); @@ -530,7 +532,7 @@ TEST_F(RuntimeSchedulerTest, sameThreadTaskCreatesImmediatePriorityTask) { runtimeScheduler_->scheduleTask( SchedulerPriority::ImmediatePriority, std::move(callback)); - runtimeScheduler_->callImmediates(runtime); + runtimeScheduler_->callExpiredTasks(runtime); }); }); @@ -567,7 +569,7 @@ TEST_F(RuntimeSchedulerTest, sameThreadTaskCreatesLowPriorityTask) { runtimeScheduler_->scheduleTask( SchedulerPriority::LowPriority, std::move(callback)); - runtimeScheduler_->callImmediates(runtime); + runtimeScheduler_->callExpiredTasks(runtime); EXPECT_FALSE(didRunSubsequentTask); }); @@ -596,4 +598,42 @@ TEST_F(RuntimeSchedulerTest, sameThreadTaskCreatesLowPriorityTask) { EXPECT_EQ(stubQueue_->size(), 0); } +TEST_F(RuntimeSchedulerTest, twoThreadsRequestAccessToTheRuntime) { + bool didRunSynchronousTask = false; + bool didRunWork = false; + + runtimeScheduler_->scheduleWork( + [&didRunWork](jsi::Runtime &) { didRunWork = true; }); + + std::thread t1([this, &didRunSynchronousTask]() { + runtimeScheduler_->executeNowOnTheSameThread( + [&didRunSynchronousTask](jsi::Runtime &runtime) { + didRunSynchronousTask = true; + }); + }); + + auto hasTask = stubQueue_->waitForTasks(2, 1ms); + + EXPECT_TRUE(hasTask); + EXPECT_FALSE(didRunWork); + EXPECT_FALSE(didRunSynchronousTask); + EXPECT_TRUE(runtimeScheduler_->getShouldYield()); + EXPECT_EQ(stubQueue_->size(), 2); + + stubQueue_->tick(); + + EXPECT_TRUE(didRunWork); + EXPECT_FALSE(didRunSynchronousTask); + EXPECT_TRUE(runtimeScheduler_->getShouldYield()); + EXPECT_EQ(stubQueue_->size(), 1); + + stubQueue_->tick(); + + t1.join(); + + EXPECT_TRUE(didRunWork); + EXPECT_TRUE(didRunSynchronousTask); + EXPECT_FALSE(runtimeScheduler_->getShouldYield()); +} + } // namespace facebook::react diff --git a/ReactCommon/react/renderer/runtimescheduler/tests/StubQueue.h b/ReactCommon/react/renderer/runtimescheduler/tests/StubQueue.h index e81fb065c9..c7a7c634ce 100644 --- a/ReactCommon/react/renderer/runtimescheduler/tests/StubQueue.h +++ b/ReactCommon/react/renderer/runtimescheduler/tests/StubQueue.h @@ -53,6 +53,15 @@ class StubQueue { lock, timeout, [this]() { return !callbackQueue_.empty(); }); } + bool waitForTasks( + std::size_t numberOfTasks, + std::chrono::duration timeout) const { + std::unique_lock lock(mutex_); + return signal_.wait_for(lock, timeout, [this, numberOfTasks]() { + return numberOfTasks == callbackQueue_.size(); + }); + } + private: mutable std::condition_variable signal_; mutable std::mutex mutex_; diff --git a/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 57f40dcb16..918af53913 100644 --- a/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -78,7 +78,7 @@ Scheduler::Scheduler( }, runtime); if (runtimeScheduler) { - runtimeScheduler->callImmediates(runtime); + runtimeScheduler->callExpiredTasks(runtime); } }; diff --git a/ReactCommon/react/renderer/uimanager/UIManager.cpp b/ReactCommon/react/renderer/uimanager/UIManager.cpp index 8455efb45e..0d2857b494 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -94,28 +94,27 @@ SharedShadowNode UIManager::createNode( } SharedShadowNode UIManager::cloneNode( - const ShadowNode::Shared &shadowNode, - const SharedShadowNodeSharedList &children, - const RawProps *rawProps) const { + ShadowNode const &shadowNode, + SharedShadowNodeSharedList const &children, + RawProps const *rawProps) const { SystraceSection s("UIManager::cloneNode"); PropsParserContext propsParserContext{ - shadowNode->getFamily().getSurfaceId(), *contextContainer_.get()}; + shadowNode.getFamily().getSurfaceId(), *contextContainer_.get()}; - auto &componentDescriptor = shadowNode->getComponentDescriptor(); + auto &componentDescriptor = shadowNode.getComponentDescriptor(); auto clonedShadowNode = componentDescriptor.cloneShadowNode( - *shadowNode, + shadowNode, { /* .props = */ rawProps ? componentDescriptor.cloneProps( - propsParserContext, shadowNode->getProps(), *rawProps) + propsParserContext, shadowNode.getProps(), *rawProps) : ShadowNodeFragment::propsPlaceholder(), /* .children = */ children, }); if (delegate_) { - delegate_->uiManagerDidCloneShadowNode( - *shadowNode.get(), *clonedShadowNode); + delegate_->uiManagerDidCloneShadowNode(shadowNode, *clonedShadowNode); } return clonedShadowNode; diff --git a/ReactCommon/react/renderer/uimanager/UIManager.h b/ReactCommon/react/renderer/uimanager/UIManager.h index 16553adea4..93cd8994c2 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/ReactCommon/react/renderer/uimanager/UIManager.h @@ -127,9 +127,9 @@ class UIManager final : public ShadowTreeDelegate { SharedEventTarget eventTarget) const; ShadowNode::Shared cloneNode( - const ShadowNode::Shared &shadowNode, - const SharedShadowNodeSharedList &children = nullptr, - const RawProps *rawProps = nullptr) const; + ShadowNode const &shadowNode, + SharedShadowNodeSharedList const &children = nullptr, + RawProps const *rawProps = nullptr) const; void appendChild( const ShadowNode::Shared &parentShadowNode, diff --git a/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index da6eeb68ff..c201c7fe00 100644 --- a/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -220,7 +220,8 @@ jsi::Value UIManagerBinding::get( size_t count) noexcept -> jsi::Value { return valueFromShadowNode( runtime, - uiManager->cloneNode(shadowNodeFromValue(runtime, arguments[0]))); + uiManager->cloneNode( + *shadowNodeFromValue(runtime, arguments[0]))); }); } @@ -287,7 +288,7 @@ jsi::Value UIManagerBinding::get( return valueFromShadowNode( runtime, uiManager->cloneNode( - shadowNodeFromValue(runtime, arguments[0]), + *shadowNodeFromValue(runtime, arguments[0]), ShadowNode::emptySharedShadowNodeSharedList())); }); } @@ -307,7 +308,7 @@ jsi::Value UIManagerBinding::get( return valueFromShadowNode( runtime, uiManager->cloneNode( - shadowNodeFromValue(runtime, arguments[0]), + *shadowNodeFromValue(runtime, arguments[0]), nullptr, &rawProps)); }); @@ -328,7 +329,7 @@ jsi::Value UIManagerBinding::get( return valueFromShadowNode( runtime, uiManager->cloneNode( - shadowNodeFromValue(runtime, arguments[0]), + *shadowNodeFromValue(runtime, arguments[0]), ShadowNode::emptySharedShadowNodeSharedList(), &rawProps)); }); diff --git a/bots/yarn.lock b/bots/yarn.lock index a28269eb5d..14335e1cfa 100644 --- a/bots/yarn.lock +++ b/bots/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@babel/polyfill@^7.2.5": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" + integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + "@firebase/analytics-compat@0.1.11": version "0.1.11" resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.1.11.tgz#0dd12c628e063bba2851b4da57fe67024c52ae2d" @@ -426,6 +434,11 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" +"@octokit/openapi-types@^11.2.0": + version "11.2.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" + integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== + "@octokit/openapi-types@^12.1.0": version "12.1.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.1.0.tgz#a68b60e969f26dee0eb7d127c65a84967f2d3a6e" @@ -460,7 +473,19 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": +"@octokit/request@^5.6.0": + version "5.6.2" + resolved "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz" + integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.16.1" + is-plain-object "^5.0.0" + node-fetch "^2.6.1" + universal-user-agent "^6.0.0" + +"@octokit/request@^5.6.3": version "5.6.3" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== @@ -482,7 +507,14 @@ "@octokit/plugin-request-log" "^1.0.4" "@octokit/plugin-rest-endpoint-methods" "^5.12.0" -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.35.0": +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1": + version "6.34.0" + resolved "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz" + integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== + dependencies: + "@octokit/openapi-types" "^11.2.0" + +"@octokit/types@^6.35.0": version "6.35.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.35.0.tgz#11cd9a679c32b4a6c36459ae2ec3ac4de0104f71" integrity sha512-DhLfdUuv3H37u6jBDfkwamypx3HflHg29b26nbA6iVFYkAlZ5cMEtu/9pQoihGnQE5M7jJFnNo25Rr1UwQNF8Q== @@ -548,9 +580,9 @@ integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== "@types/node@>=12.12.47", "@types/node@>=13.7.0": - version "18.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" - integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== + version "16.9.1" + resolved "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz" + integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== abort-controller@^3.0.0: version "3.0.0" @@ -566,7 +598,7 @@ agent-base@4, agent-base@^4.3.0: dependencies: es6-promisify "^5.0.0" -ansi-regex@^5.0.1: +ansi-regex@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -595,7 +627,7 @@ async-retry@1.2.3: asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= balanced-match@^1.0.0: version "1.0.2" @@ -615,7 +647,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +braces@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -625,7 +657,7 @@ braces@^3.0.2: buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= chalk@^2.3.0: version "2.4.2" @@ -662,7 +694,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@~1.1.4: version "1.1.4" @@ -688,29 +720,34 @@ commander@^2.18.0: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= core-js@3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== +core-js@^2.6.5: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + core-js@^3.8.2: version "3.23.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.23.1.tgz#9f9a9255115f62c512db56d567f636da32ca0b78" integrity sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w== danger@^11.0.2: - version "11.0.7" - resolved "https://registry.yarnpkg.com/danger/-/danger-11.0.7.tgz#1d801f0b2e1ef89a74a9b1f2776cd8e5c1ce8e5e" - integrity sha512-4jdZ5xqQO03EDmoYf29EMvHluNFMXOi5u8msxKE/pAe4UlfvQ6yOpQC5jHF73f724OLP2x9paqVd+vumoC3lug== + version "11.0.2" + resolved "https://registry.yarnpkg.com/danger/-/danger-11.0.2.tgz#245b65aaf26c9b5eb3d0c65fcd403b5c31782138" + integrity sha512-TKE5E1Zrb0uV7Ft3mhbTA3bwVf4hZs7DVx6Mo8weVdIcaXJIIle3+aCjn259GX9/pF4ewoYuof7eLRPJligOgA== dependencies: + "@babel/polyfill" "^7.2.5" "@octokit/rest" "^18.12.0" async-retry "1.2.3" chalk "^2.3.0" commander "^2.18.0" - core-js "^3.8.2" debug "^4.1.1" fast-json-patch "^3.0.0-1" get-stdin "^6.0.0" @@ -740,7 +777,6 @@ danger@^11.0.2: pinpoint "^1.1.0" prettyjson "^1.2.1" readline-sync "^1.4.9" - regenerator-runtime "^0.13.9" require-from-string "^2.0.2" supports-hyperlinks "^1.0.1" @@ -759,21 +795,21 @@ debug@^3.1.0: ms "^2.1.1" debug@^4.1.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" @@ -800,7 +836,7 @@ es6-promise@^4.0.3: es6-promisify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= dependencies: es6-promise "^4.0.3" @@ -812,7 +848,7 @@ escalade@^3.1.1: escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= event-target-shim@^5.0.0: version "5.0.1" @@ -822,21 +858,21 @@ event-target-shim@^5.0.0: expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" fast-json-patch@^3.0.0-1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947" - integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.0.tgz#ec8cd9b9c4c564250ec8b9140ef7a55f70acaee6" + integrity sha512-IhpytlsVTRndz0hU5t0/MGzS/etxLlfrpG5V5M9mVbuj9TrJLWaMfsox9REM5rkuGX0T+5qjpe8XA1o0gZ42nA== faye-websocket@0.11.4: version "0.11.4" @@ -855,7 +891,7 @@ fill-range@^7.0.1: filter-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= firebase@^9.6.5: version "9.8.3" @@ -901,12 +937,12 @@ form-data@^2.5.0: fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - integrity sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg== + integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= get-caller-file@^2.0.5: version "2.0.5" @@ -921,7 +957,7 @@ get-stdin@^6.0.0: git-config-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/git-config-path/-/git-config-path-1.0.1.tgz#6d33f7ed63db0d0e118131503bab3aca47d54664" - integrity sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg== + integrity sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ= dependencies: extend-shallow "^2.0.1" fs-exists-sync "^0.1.0" @@ -955,12 +991,12 @@ glob@^7.1.3: has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng== + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= hasurl@^1.0.0: version "1.0.0" @@ -998,7 +1034,7 @@ https-proxy-agent@^2.2.1: humps@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa" - integrity sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g== + integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao= hyperlinker@^1.0.0: version "1.0.0" @@ -1036,7 +1072,7 @@ ini@^1.3.5: is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -1054,9 +1090,11 @@ is-plain-object@^5.0.0: integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== json5@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" jsonpointer@^5.0.0: version "5.0.0" @@ -1122,7 +1160,7 @@ ky@^0.12.0: li@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/li/-/li-1.3.0.tgz#22c59bcaefaa9a8ef359cf759784e4bf106aea1b" - integrity sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw== + integrity sha1-IsWbyu+qmo7zWc91l4TkvxBq6hs= lie@~3.3.0: version "3.3.0" @@ -1139,7 +1177,7 @@ lodash.camelcase@^4.3.0: lodash.find@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" - integrity sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg== + integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E= lodash.includes@^4.3.0: version "4.3.0" @@ -1149,57 +1187,57 @@ lodash.includes@^4.3.0: lodash.isboolean@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= lodash.isnumber@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= lodash.isobject@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" - integrity sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA== + integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0= lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= lodash.isstring@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= lodash.keys@^4.0.8: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" - integrity sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ== + integrity sha1-oIYCrBLk+4P5H8H7ejYKTZujUgU= lodash.mapvalues@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" - integrity sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ== + integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= long@^4.0.0: version "4.0.0" @@ -1214,41 +1252,48 @@ memfs-or-file-map-to-github-branch@^1.2.1: "@octokit/rest" "^16.43.0 || ^17.11.0 || ^18.12.0" micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== dependencies: - braces "^3.0.2" - picomatch "^2.3.1" + braces "^3.0.1" + picomatch "^2.2.3" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== dependencies: - mime-db "1.52.0" + mime-db "1.51.0" -minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.2: version "2.1.2" @@ -1263,7 +1308,7 @@ ms@^2.1.1: node-cleanup@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" - integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== + integrity sha1-esGavSl+Caf3KnFUXZUbUX5N3iw= node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.7: version "2.6.7" @@ -1275,14 +1320,14 @@ node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.7: once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" override-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/override-require/-/override-require-1.1.1.tgz#6ae22fadeb1f850ffb0cf4c20ff7b87e5eb650df" - integrity sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg== + integrity sha1-auIvresfhQ/7DPTCD/e4fl62UN8= p-limit@^2.1.0: version "2.3.0" @@ -1330,14 +1375,14 @@ parse-link-header@^2.0.0: parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -picomatch@^2.3.1: +picomatch@^2.2.3: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -1345,7 +1390,7 @@ picomatch@^2.3.1: pinpoint@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" - integrity sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg== + integrity sha1-DPd1eml38b9/ajIge3CeN3OI6HQ= prettyjson@^1.2.1: version "1.2.5" @@ -1406,7 +1451,7 @@ readline-sync@^1.4.9: resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== -regenerator-runtime@^0.13.9: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== @@ -1414,7 +1459,7 @@ regenerator-runtime@^0.13.9: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.2: version "2.0.2" @@ -1424,7 +1469,7 @@ require-from-string@^2.0.2: retry@0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= rimraf@^3.0.0: version "3.0.2" @@ -1438,6 +1483,11 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.0: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + selenium-webdriver@4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.1.2.tgz#d463b4335632d2ea41a9e988e435a55dc41f5314" @@ -1465,7 +1515,7 @@ split-on-first@^1.0.0: strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" @@ -1476,7 +1526,14 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -1515,14 +1572,14 @@ to-regex-range@^5.0.1: tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= dependencies: punycode "^2.1.0" tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= tslib@^2.1.0: version "2.4.0" @@ -1545,7 +1602,7 @@ universal-user-agent@^6.0.0: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= webidl-conversions@^4.0.2: version "4.0.2" @@ -1574,7 +1631,7 @@ whatwg-fetch@2.0.4: whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -1600,7 +1657,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= ws@>=7.4.6: version "8.8.0" diff --git a/build.gradle.kts b/build.gradle.kts index 7c71d62883..5d38d5a7af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ buildscript { dependencies { val kotlin_version: String by project classpath("com.android.tools.build:gradle:7.0.4") - classpath("de.undercouch:gradle-download-task:4.1.2") + classpath("de.undercouch:gradle-download-task:5.0.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle.properties b/gradle.properties index 900a6e110b..d8559b0b86 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # This is causing issue with dependencies task: https://github.com/gradle/gradle/issues/9645#issuecomment-530746758 # org.gradle.configureondemand=true org.gradle.daemon=true -org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8 org.gradle.parallel=true android.useAndroidX=true diff --git a/index.js b/index.js index 579c26abb0..c711de0c53 100644 --- a/index.js +++ b/index.js @@ -469,32 +469,32 @@ module.exports = { }, // Deprecated Prop Types get ColorPropType(): $FlowFixMe { - console.warn( - 'ColorPropType will be removed from React Native. Migrate to ' + + invariant( + false, + 'ColorPropType has been removed from React Native. Migrate to ' + "ColorPropType exported from 'deprecated-react-native-prop-types'.", ); - return require('deprecated-react-native-prop-types').ColorPropType; }, get EdgeInsetsPropType(): $FlowFixMe { - console.warn( - 'EdgeInsetsPropType will be removed from React Native. Migrate to ' + + invariant( + false, + 'EdgeInsetsPropType has been removed from React Native. Migrate to ' + "EdgeInsetsPropType exported from 'deprecated-react-native-prop-types'.", ); - return require('deprecated-react-native-prop-types').EdgeInsetsPropType; }, get PointPropType(): $FlowFixMe { - console.warn( - 'PointPropType will be removed from React Native. Migrate to ' + + invariant( + false, + 'PointPropType has been removed from React Native. Migrate to ' + "PointPropType exported from 'deprecated-react-native-prop-types'.", ); - return require('deprecated-react-native-prop-types').PointPropType; }, get ViewPropTypes(): $FlowFixMe { - console.warn( - 'ViewPropTypes will be removed from React Native. Migrate to ' + + invariant( + false, + 'ViewPropTypes has been removed from React Native. Migrate to ' + "ViewPropTypes exported from 'deprecated-react-native-prop-types'.", ); - return require('deprecated-react-native-prop-types').ViewPropTypes; }, // macOS] }; diff --git a/package.json b/package.json index b4a2ce9046..eb5816e7bc 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ }, "dependencies": { "@jest/create-cache-key-function": "^27.0.1", - "@react-native-community/cli": "^7.0.3", + "@react-native-community/cli": "^7.0.1", "@react-native-community/cli-platform-android": "^7.0.1", "@react-native-community/cli-platform-ios": "^7.0.1", "@react-native-community/cli-tools": "^7.0.1", @@ -107,7 +107,6 @@ "abort-controller": "^3.0.0", "anser": "^1.4.9", "base64-js": "^1.1.2", - "deprecated-react-native-prop-types": "^2.3.0", "event-target-shim": "^5.0.1", "hermes-engine": "~0.11.0", "invariant": "^2.2.4", @@ -119,7 +118,7 @@ "pretty-format": "^26.5.2", "promise": "^8.0.3", "react-devtools-core": "^4.23.0", - "react-native-gradle-plugin": "^0.0.6", + "react-native-gradle-plugin": "^0.0.4", "react-refresh": "^0.4.0", "react-shallow-renderer": "16.14.1", "regenerator-runtime": "^0.13.2", @@ -131,44 +130,8 @@ "react-native-codegen": "^0.0.17" }, "devDependencies": { - "flow-bin": "^0.170.0", - "react": "17.0.2", - "@babel/core": "^7.14.0", - "@babel/generator": "^7.14.0", - "@react-native-community/eslint-plugin": "*", - "@react-native/eslint-plugin-specs": ">0.0.2", - "@reactions/component": "^2.0.2", - "async": "^3.2.2", - "babel-eslint": "^10.1.0", - "clang-format": "^1.2.4", - "connect": "^3.6.5", - "coveralls": "^3.0.2", - "eslint": "^7.32.0", - "eslint-config-fb-strict": "^26.0.0", - "eslint-config-fbjs": "^3.1.1", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-babel": "^5.3.1", - "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-flowtype": "^7.0.0", - "eslint-plugin-jest": "^25.2.4", - "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.26.1", - "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-react-native": "^3.11.0", - "eslint-plugin-relay": "^1.8.2", - "inquirer": "^7.1.0", - "jest": "^26.6.3", - "jest-junit": "^10.0.0", - "jscodeshift": "^0.13.1", - "metro-babel-register": "0.67.0", - "mkdirp": "^0.5.1", - "prettier": "^2.4.1", - "react-test-renderer": "17.0.2", - "shelljs": "^0.8.4", - "signedsource": "^1.0.0", - "ws": "^6.1.4", - "yargs": "^15.3.1" + "flow-bin": "^0.171.0", + "react": "17.0.2" }, "beachball": { "shouldPublish": false @@ -205,4 +168,4 @@ } ] } -} +} \ No newline at end of file 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 cc95c05740..474b387833 100644 --- a/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap +++ b/packages/babel-plugin-codegen/__tests__/__snapshots__/index-test.js.snap @@ -24,6 +24,10 @@ interface NativeCommands { const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const { + ConditionallyIgnoredEventHandlers +} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); + const { dispatchCommand } = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); @@ -45,7 +49,11 @@ export const __INTERNAL_VIEW_CONFIG = { } }, validAttributes: { - boolean_default_true_optional_both: true + boolean_default_true_optional_both: true, + ...ConditionallyIgnoredEventHandlers({ + onDirectEventDefinedInlineNull: true, + onBubblingEventDefinedInlineNull: true + }) } }; export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG); @@ -85,6 +93,10 @@ interface NativeCommands { const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const { + ConditionallyIgnoredEventHandlers +} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); + const { dispatchCommand } = require(\\"react-native/Libraries/Renderer/shims/ReactNative\\"); @@ -106,7 +118,11 @@ export const __INTERNAL_VIEW_CONFIG = { } }, validAttributes: { - boolean_default_true_optional_both: true + boolean_default_true_optional_both: true, + ...ConditionallyIgnoredEventHandlers({ + onDirectEventDefinedInlineNull: true, + onBubblingEventDefinedInlineNull: true + }) } }; export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG); diff --git a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap index 9f50be6680..12fa79b3d4 100644 --- a/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/components/__snapshots__/GenerateViewConfigJs-test.js.snap @@ -200,6 +200,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'EventNestedObjectPropsNativeComponentView'; @@ -218,6 +219,10 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { disabled: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + }), }, }; @@ -243,6 +248,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'EventPropsNativeComponentView'; @@ -289,6 +295,15 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { disabled: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + onEventDirect: true, + onEventDirectWithPaperName: true, + onOrientationChange: true, + onEnd: true, + onEventBubblingWithPaperName: true, + }), }, }; @@ -426,6 +441,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'RCTInterfaceOnlyComponent'; @@ -444,6 +460,10 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { title: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + }), }, }; diff --git a/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js b/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js index b1872a9176..3a4bda260c 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js +++ b/packages/react-native-codegen/src/generators/components/GenerateViewConfigJs.js @@ -171,6 +171,23 @@ function normalizeInputEventName(name) { return name; } +// Replicates the behavior of viewConfig in RCTComponentData.m +function getValidAttributesForEvents(events, imports) { + imports.add( + "const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore');", + ); + + const validAttributes = j.objectExpression( + events.map(eventType => { + return j.property('init', j.identifier(eventType.name), j.literal(true)); + }), + ); + + return j.callExpression(j.identifier('ConditionallyIgnoredEventHandlers'), [ + validAttributes, + ]); +} + function generateBubblingEventInfo(event, nameOveride) { return j.property( 'init', @@ -243,6 +260,13 @@ function buildViewConfig( getReactDiffProcessValue(schemaProp.typeAnnotation), ); }), + ...(componentEvents.length > 0 + ? [ + j.spreadProperty( + getValidAttributesForEvents(componentEvents, imports), + ), + ] + : []), ]); const bubblingEventNames = component.events 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 757ee7a65f..49f9a83c09 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 @@ -295,6 +295,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'EventsNestedObjectNativeComponent'; @@ -313,6 +314,10 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { disabled: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + }), }, }; @@ -338,6 +343,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'EventsNativeComponent'; @@ -373,6 +379,13 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { disabled: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + onEventDirect: true, + onOrientationChange: true, + onEnd: true, + }), }, }; @@ -398,6 +411,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'RCTInterfaceOnlyComponent'; @@ -420,7 +434,12 @@ export const __INTERNAL_VIEW_CONFIG = { }, }, - validAttributes: {}, + validAttributes: { + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + onDire tChange: true, + }), + }, }; export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG); @@ -688,6 +707,7 @@ Map { 'use strict'; const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry'); +const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore'); let nativeComponentName = 'RCTInterfaceOnlyComponent'; @@ -706,6 +726,10 @@ export const __INTERNAL_VIEW_CONFIG = { validAttributes: { accessibilityHint: true, + + ...ConditionallyIgnoredEventHandlers({ + onChange: true, + }), }, }; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 5b35d8c414..0c90cee8e4 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -80,7 +80,19 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/${libraryName} -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni \ + libfolly_json \ + libglog \ + libjsi \ + libreact_codegen_rncore \ + libreact_debug \ + libreact_nativemodule_core \ + libreact_render_core \ + libreact_render_debug \ + libreact_render_graphics \ + librrc_view \ + libturbomodulejsijni \ + libyoga LOCAL_CFLAGS := \\ -DLOG_TAG=\\"ReactNative\\" 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 81e5237b29..c9ddf301a4 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 @@ -52,7 +52,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/SampleWithUppercaseName -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -116,7 +116,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/complex_objects -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -180,7 +180,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/empty_native_modules -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -244,7 +244,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/native_modules_with_type_aliases -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -316,7 +316,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/real_module_example -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -380,7 +380,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/simple_native_modules -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" @@ -452,7 +452,7 @@ LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/reac LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/two_modules_different_files -LOCAL_SHARED_LIBRARIES := libjsi libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libfbjni libturbomodulejsijni libreact_codegen_rncore libreact_debug libreact_render_debug +LOCAL_SHARED_LIBRARIES := libfbjni libfolly_json libglog libjsi libreact_codegen_rncore libreact_debug libreact_nativemodule_core libreact_render_core libreact_render_debug libreact_render_graphics librrc_view libturbomodulejsijni libyoga LOCAL_CFLAGS := \\\\ -DLOG_TAG=\\\\\\"ReactNative\\\\\\" 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 24e08b4493..1c7982da78 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/props.js +++ b/packages/react-native-codegen/src/parsers/flow/components/props.js @@ -319,6 +319,10 @@ function getTypeAnnotation( `Unsupported union type for "${name}", received "${unionType}"`, ); } + case 'ObjectTypeAnnotation': + throw new Error( + `Cannot use "${type}" type annotation for "${name}": object types must be declared using $ReadOnly<>`, + ); case 'NumberTypeAnnotation': throw new Error( `Cannot use "${type}" type annotation for "${name}": must use a specific numeric type like Int32, Double, or Float`, diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/react-native-gradle-plugin/build.gradle.kts index 3b824bc655..c457a5791e 100644 --- a/packages/react-native-gradle-plugin/build.gradle.kts +++ b/packages/react-native-gradle-plugin/build.gradle.kts @@ -46,8 +46,8 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } tasks.withType { diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt index 061a56bdc3..9f8759f0db 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt @@ -15,17 +15,37 @@ import com.facebook.react.tasks.BuildCodegenCLITask import com.facebook.react.tasks.GenerateCodegenArtifactsTask import com.facebook.react.tasks.GenerateCodegenSchemaTask import java.io.File +import kotlin.system.exitProcess import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.internal.jvm.Jvm class ReactPlugin : Plugin { override fun apply(project: Project) { + checkJvmVersion() val extension = project.extensions.create("react", ReactExtension::class.java, project) applyAppPlugin(project, extension) applyCodegenPlugin(project, extension) } + private fun checkJvmVersion() { + val jvmVersion = Jvm.current()?.javaVersion?.majorVersion + if ((jvmVersion?.toIntOrNull() ?: 0) <= 8) { + println("\n\n\n") + println( + "**************************************************************************************************************") + println("\n\n") + println("ERROR: requires JDK11 or higher.") + println("Incompatible major version detected: '" + jvmVersion + "'") + println("\n\n") + println( + "**************************************************************************************************************") + println("\n\n\n") + exitProcess(1) + } + } + private fun applyAppPlugin(project: Project, config: ReactExtension) { project.afterEvaluate { if (config.applyAppPlugin.getOrElse(false)) { diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 42fa186c27..419ae04c7f 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -563,8 +563,8 @@ SPEC CHECKSUMS: boost: 613e39eac4239cc72b15421247b5ab05361266a2 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: ed15e075aa758ac0e4c1f8b830bd4e4d40d669e8 - FBLazyVector: 4f7dec9b06e2161bdc7451b81285b955e44120f2 - FBReactNativeSpec: 884fc2c1ae9aac805b5b1683556539017f128e30 + FBLazyVector: 384527e08219663bcf4929e2d266ae2a7ee355c9 + FBReactNativeSpec: 3ab1f6402e4c0cb609a2dd69ee5388553665a4ce Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c @@ -580,39 +580,39 @@ SPEC CHECKSUMS: OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 24c6da766832002a4a2aac5f79ee0ca50fbe8507 - RCTRequired: 9b3b3dd4bec7ff068b05da2f77a4ce87b79056ce - RCTTypeSafety: 0a550fe20009fbdb80b750bd92d8476b4fbcfd4b - React: a7ba329278133e1d7b0d57eac0f455cb53c484ef - React-callinvoker: a7973d14f10e7bfa72fe0cf97264dba48d49cc5c + RCTRequired: c227d1cbf4257746e1984626e164dd070135ab51 + RCTTypeSafety: cda767ff31bb0dcdeac45b4a1a2d04689a7a8e5a + React: fdeb98299a820dbec6cbb1e4c004fa3799dd376f + React-callinvoker: 8f64ce3fa5d782daa2fbee4cd4821698aaf673f1 React-Codegen: 61a79489c164568e1575cc662fa7c9a167215dcc - React-Core: 83f76a9e553370910f7dd036c227ae3728514e4c - React-CoreModules: 956c5003b1f393ecdf01cac81b9abd61c53cb897 - React-cxxreact: 0d26fe3e743964ec28be7480781b33669d7edcb2 - React-jsi: 0fe864a1e1ab4089ae7361cb768bda8f20350ad8 - React-jsiexecutor: 80621468529516b8f1164685d8e62d72c78f7551 - React-jsinspector: f1d9ed916336a72ec377fb8c0a1d784a7a0085ae - React-logger: 7dfa0e98931f90b501143d2cf5fbbd3fbb03a5c1 - React-perflogger: 6470780013040448a52bdab0e668573ad6da047c - React-RCTActionSheet: 7a120b18673235b7bec8c6b7f45ffe6103a80c45 - React-RCTAnimation: e380831ab78e2e6e41fb21d99c2515b61ded67b2 - React-RCTBlob: ef1b52b27841714d8e77e65a3f46ae37ab5c0286 - React-RCTImage: 73f3c9efc611c90eb57fa8ffd8390f748cd12163 - React-RCTLinking: 862a74f8b690f080fbbb071d6c9ee9f918d85abf - React-RCTNetwork: 0ad181f3eccebc98acd5aae88668ec8b977ada4f - React-RCTPushNotification: 2f6d6c013536e7381517a89854b2e0dec3ccaea0 - React-RCTSettings: 69dc88fa59c154c0f020de20af286e1f18ecaf08 - React-RCTTest: c4409159d6602fac7ea0c77dd78edbfd87451003 - React-RCTText: e76719accaa721a86ef10fd26418c632364865cc - React-RCTVibration: b13450dceee3922928d5f2ba626f13a8c8a41592 - React-runtimeexecutor: efede3b2374f6eea50a485f042f7f8c13e3b4d80 + React-Core: d26ae99463cddeadc5639612ca30616561415789 + React-CoreModules: cfce02ad8ea53a2295e1dac937eba5a90622a2bb + React-cxxreact: 12fd22c456355c71e5c5081dcffea1f32cae5773 + React-jsi: ae9bc2bfc04c6ff51b2cb72f57d0ae3ceed45ade + React-jsiexecutor: d58c93c836f125efe1dd5a6a4e67e91e22e879d2 + React-jsinspector: d42e72bb4097e204fb58e0dfa6a73064d5110350 + React-logger: 582ddca30294da58d26d7722038868e016907212 + React-perflogger: 3a2074e543aec103be610bac726ce08d7bca0a73 + React-RCTActionSheet: 2bd2272f1da5984e560ee2ff21385b252faea787 + React-RCTAnimation: 91bb2eef31ddb8254b440e9e270a379b724d42e7 + React-RCTBlob: 80f2a58eb43ed52347c74862396d5f782a43f1a7 + React-RCTImage: 072355172731a4e98969d8edc3429b34c66145d3 + React-RCTLinking: a453010e6eed69a6040466df1d027568f2614682 + React-RCTNetwork: 359c5d7fcab48d6ce482e1d41d18b41aef1c88ed + React-RCTPushNotification: 10ce9158a757b7b421e1ec859075c2b62a660c8c + React-RCTSettings: 814b8cd77826d9f701f5a405615af447f2cdb2cf + React-RCTTest: acb0c4b891472b017d6ad5b467677e09cc04fbcc + React-RCTText: 738955a75c0377dfca55de5c5f5197fb7ea2de46 + React-RCTVibration: 8ddcc5d106204b03a2b6cb7312dfb266c411c6f0 + React-runtimeexecutor: 406c4f19aaad1b5c000cb035b32b6abea250775d React-TurboModuleCxx-RNW: 881411415eafe818f9cc3c4016167cc3d219402b - React-TurboModuleCxx-WinRTPort: 07e0f59bfaa337933c7b114d374d0e2a93b4b5e8 - ReactCommon: 3199785c30e1efcce92ca7da5038c7a248124aa3 - ScreenshotManager: b378292226c78474e70b139ba2e19f584836c520 + React-TurboModuleCxx-WinRTPort: 9183595ebeacb9692054a21fe62f675a0a255e8a + ReactCommon: fe52e3136583b019573d6d91521fc9c65bb8a64d + ScreenshotManager: f08c5d98fb598cd3cb2c2b28bca6862564fbed22 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 - Yoga: 9899fd558a01665e4acf7e28f02f2090942e829c + Yoga: 3b4464e1119acaf12514b1bfd1c9c874d216fe5f YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: cbf4f9be33910397d5f84dd4fcbe56d3d61d42fa +PODFILE CHECKSUM: b596acab1b1d65648cc41a960b7fac224c9d1905 COCOAPODS: 1.11.3 diff --git a/packages/rn-tester/js/examples/Linking/LinkingExample.js b/packages/rn-tester/js/examples/Linking/LinkingExample.js index a33a5b20be..2f84d7c5e0 100644 --- a/packages/rn-tester/js/examples/Linking/LinkingExample.js +++ b/packages/rn-tester/js/examples/Linking/LinkingExample.js @@ -33,7 +33,13 @@ class OpenURLButton extends React.Component { if (supported) { Linking.openURL(this.props.url); } else { - console.log("Don't know how to open URI: " + this.props.url); + console.log( + `Don't know how to open URI: ${ + this.props.url + }, ensure you have an app installed that handles the "${ + this.props.url.split(':')?.[0] + }" scheme`, + ); } }); }; @@ -134,6 +140,8 @@ exports.description = 'Shows how to use Linking to open URLs.'; exports.examples = [ { title: 'Open external URLs', + description: + 'Custom schemes may require specific apps to be installed on the device. Note: Phone app is not supported in the simulator.', render: function (): React.Element { return ; }, diff --git a/react.gradle b/react.gradle index 0ace9be826..4c6a515134 100644 --- a/react.gradle +++ b/react.gradle @@ -6,6 +6,7 @@ */ import org.apache.tools.ant.taskdefs.condition.Os +import org.gradle.internal.jvm.Jvm def config = project.hasProperty("react") ? project.react : [:]; @@ -129,6 +130,19 @@ android { } } +def jvmVersion = Jvm.current().javaVersion.majorVersion +if (jvmVersion.toInteger() <= 8) { + println "\n\n\n" + println "**************************************************************************************************************" + println "\n\n" + println "ERROR: requires JDK11 or higher." + println "Incompatible major version detected: '" + jvmVersion + "'" + println "\n\n" + println "**************************************************************************************************************" + println "\n\n\n" + System.exit(1) +} + afterEvaluate { def isAndroidLibrary = plugins.hasPlugin("com.android.library") def variants = isAndroidLibrary ? android.libraryVariants : android.applicationVariants diff --git a/repo-config/package.json b/repo-config/package.json index a46675bfd3..4f4257b91d 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -35,7 +35,7 @@ "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-native": "^3.11.0", "eslint-plugin-relay": "^1.8.2", - "flow-bin": "^0.170.0", + "flow-bin": "^0.171.0", "inquirer": "^7.1.0", "jest": "^26.6.3", "jest-junit": "^10.0.0", @@ -46,7 +46,7 @@ "react": "17.0.2", "react-native-codegen": "^0.0.17", "react-test-renderer": "17.0.2", - "shelljs": "^0.8.4", + "shelljs": "^0.8.5", "signedsource": "^1.0.0", "typescript": "4.4.2", "ws": "^6.1.4", diff --git a/scripts/test-manual-e2e.sh b/scripts/test-manual-e2e.sh index 80b66b4ecd..302628bd43 100755 --- a/scripts/test-manual-e2e.sh +++ b/scripts/test-manual-e2e.sh @@ -11,6 +11,7 @@ ENDCOLOR="\033[0m" error() { echo -e "$RED""$*""$ENDCOLOR" + popd >/dev/null || exit exit 1 } @@ -22,6 +23,10 @@ info() { echo -e "$BLUE""$*""$ENDCOLOR" } +# Ensures commands are executed from the repo root folder +dir_absolute_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P ) +pushd "$dir_absolute_path/../" >/dev/null || exit + repo_root=$(pwd) selected_platform="" selected_vm="" @@ -126,7 +131,7 @@ init_template_app(){ project_name="RNTestProject" - cd /tmp/ || exit + pushd /tmp/ >/dev/null || exit rm -rf "$project_name" node "$repo_root/cli.js" init "$project_name" --template "$repo_root" @@ -135,6 +140,7 @@ init_template_app(){ grep -E "com.facebook.react:react-native:\\+" "${project_name}/android/app/build.gradle" || error "Dependency in /tmp/${project_name}/android/app/build.gradle must be com.facebook.react:react-native:+" success "New sample project generated at /tmp/${project_name}" + popd >/dev/null || exit } test_template_app(){ @@ -142,6 +148,7 @@ test_template_app(){ init_template_app fi + pushd "/tmp/${project_name}" >/dev/null || exit if [ "$selected_platform" == "1" ]; then info "Test the following on Android:" info " - Disable Fast Refresh. It might be enabled from last time (the setting is stored on the device)" @@ -150,7 +157,7 @@ test_template_app(){ info "Press any key to run the sample in Android emulator/device" info "" read -r -n 1 - cd "/tmp/${project_name}" && npx react-native run-android + npx react-native run-android elif [ "$selected_platform" == "2" ]; then info "Test the following on iOS:" info " - Disable Fast Refresh. It might be enabled from last time (the setting is stored on the device)" @@ -163,9 +170,9 @@ test_template_app(){ info "Press any key to open the project in Xcode" info "" read -r -n 1 - open "/tmp/${project_name}/ios/${project_name}.xcworkspace" + open "ios/${project_name}.xcworkspace" fi - cd "$repo_root" || exit + popd >/dev/null || exit } @@ -209,6 +216,7 @@ handle_menu_input(){ if [ "$confirm" == "${confirm#[Yy]}" ]; then info "Next steps:" info "https://github.com/facebook/react-native/wiki/Release-Process" + popd >/dev/null || exit exit 1 else show_menu diff --git a/template/_flowconfig b/template/_flowconfig index 9eb48b885f..fa77db3591 100644 --- a/template/_flowconfig +++ b/template/_flowconfig @@ -65,4 +65,4 @@ untyped-import untyped-type-import [version] -^0.170.0 +^0.171.0 diff --git a/template/android/app/build.gradle b/template/android/app/build.gradle index 850578b51d..506dca1211 100644 --- a/template/android/app/build.gradle +++ b/template/android/app/build.gradle @@ -233,11 +233,6 @@ android { } } - - packagingOptions { - pickFirst '**/libhermes.so' - pickFirst '**/libjsc.so' - } } dependencies { diff --git a/template/android/app/src/main/java/com/helloworld/MainActivity.java b/template/android/app/src/main/java/com/helloworld/MainActivity.java index 24f412851f..eae5dada6e 100644 --- a/template/android/app/src/main/java/com/helloworld/MainActivity.java +++ b/template/android/app/src/main/java/com/helloworld/MainActivity.java @@ -17,7 +17,8 @@ public class MainActivity extends ReactActivity { /** * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and - * you can specify the rendered you wish to use (Fabric or the older renderer). + * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer + * (Paper). */ @Override protected ReactActivityDelegate createReactActivityDelegate() { diff --git a/template/android/build.gradle b/template/android/build.gradle index 8a1d68f9c5..3300863fdc 100644 --- a/template/android/build.gradle +++ b/template/android/build.gradle @@ -15,7 +15,7 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:7.0.4") classpath("com.facebook.react:react-native-gradle-plugin") - classpath("de.undercouch:gradle-download-task:4.1.2") + classpath("de.undercouch:gradle-download-task:5.0.1") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/template/android/gradle.properties b/template/android/gradle.properties index 6e1a46f01b..fa4feae5f1 100644 --- a/template/android/gradle.properties +++ b/template/android/gradle.properties @@ -9,8 +9,8 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx1024m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/template/package.json b/template/package.json index c0c047219c..145f5d24cc 100644 --- a/template/package.json +++ b/template/package.json @@ -22,7 +22,6 @@ "eslint": "^7.32.0", "jest": "^26.6.3", "metro-react-native-babel-preset": "^0.67.0", - "react-native-gradle-plugin": "^0.0.4", "react-test-renderer": "17.0.2" }, "jest": { diff --git a/yarn.lock b/yarn.lock index 5fc3008b4f..6c1a936a70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1021,6 +1021,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jest/types@^27.4.2": + version "27.4.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" + integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@jest/types@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" @@ -1093,40 +1104,56 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@react-native-community/cli-debugger-ui@^7.0.3": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-7.0.3.tgz#3eeeacc5a43513cbcae56e5e965d77726361bcb4" - integrity sha512-G4SA6jFI0j22o+j+kYP8/7sxzbCDqSp2QiHA/X5E0lsGEd2o9qN2zbIjiFr8b8k+VVAYSUONhoC0+uKuINvmkA== +"@react-native-community/cli-config@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-7.0.1.tgz#81bf88a5c0eb21c9b0fc1f825372699c375a45a0" + integrity sha512-HGBnytnZzcT+24qAshksGpmPAXFPsKL6g9FNU7TIM9s23Hl4SXqNVEf6wj6XHXKgg8pfjXK3Lwf9IBEnZzqA/g== + dependencies: + "@react-native-community/cli-tools" "^7.0.1" + cosmiconfig "^5.1.0" + deepmerge "^3.2.0" + glob "^7.1.3" + joi "^17.2.1" + +"@react-native-community/cli-debugger-ui@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-7.0.1.tgz#2834617ee57802559c20a0a75ad7eeeef73ff422" + integrity sha512-N4ASQY5VbRiiyhfAWhvURavANtFd7JPJFpXd59hsZxvaFEDB2L2HhVkwbw6BSbVUrYDuAWFQGx3S10L+MCHAjQ== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-hermes@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-6.3.1.tgz#a4c3b4b07a1775f7012baf6d5a0b059da2ffac00" - integrity sha512-+tMJsEsVX0WyylnoFE7uPoMu1aTAChaA62Y32dwWgAa1Fx6YrpPkC9d6wvYSBe9md/4mTtRher+ooBcuov6JHw== +"@react-native-community/cli-doctor@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-7.0.1.tgz#36ba3da91a358b0c38fd199782db2d857fee16d0" + integrity sha512-y5RBAuBiOwiiFfj9N/iuj6PZ3c5j68LE8XTQdhZJE+qTuSxWXQrdpFwL9Nc9KIk3bBxC72uBfRFGxa/mLZGYMw== dependencies: - "@react-native-community/cli-platform-android" "^6.3.1" - "@react-native-community/cli-tools" "^6.2.1" + "@react-native-community/cli-config" "^7.0.1" + "@react-native-community/cli-tools" "^7.0.1" + chalk "^3.0.0" + command-exists "^1.2.8" + envinfo "^7.7.2" + execa "^1.0.0" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + node-stream-zip "^1.9.1" + ora "^5.4.1" + prompts "^2.4.0" + semver "^6.3.0" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" + +"@react-native-community/cli-hermes@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-7.0.1.tgz#d6229bfc6da9ee2fd71a5e4ef86e92a4690bde79" + integrity sha512-NzKxW8LzNr3ttD5E479HCpSLfcpdv0SwpsIBsDCWhuDmGW5NXo8Qdu5/plVWZJ1CVBWkVFeVHIlKs0pov7GlOw== + dependencies: + "@react-native-community/cli-platform-android" "^7.0.1" + "@react-native-community/cli-tools" "^7.0.1" chalk "^4.1.2" hermes-profile-transformer "^0.0.6" ip "^1.1.5" -"@react-native-community/cli-platform-android@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-6.3.1.tgz#8d35c809ddaf3b6c5d4ef9ff9c814a25a55259aa" - integrity sha512-n5A64RI1ty4ScZCel/3JYY9Anl857dPsUZ86Dwc1GxrbflSB5/+hcCMg5DCNcnJRa4Hdv95SAR5pMmtAjOXApA== - dependencies: - "@react-native-community/cli-tools" "^6.2.1" - chalk "^4.1.2" - execa "^1.0.0" - fs-extra "^8.1.0" - glob "^7.1.3" - jetifier "^1.6.2" - lodash "^4.17.15" - logkitty "^0.7.1" - slash "^3.0.0" - xmldoc "^1.1.2" - "@react-native-community/cli-platform-android@^7.0.1": version "7.0.1" resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-7.0.1.tgz#d165897edf401f9bceff1f361ef446528133cb52" @@ -1158,13 +1185,13 @@ plist "^3.0.2" xcode "^3.0.0" -"@react-native-community/cli-plugin-metro@^7.0.4": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-7.0.4.tgz#cd3010f6b9f955df2630ceea9fc8816a12843dde" - integrity sha512-DEV9WwJ6mB8zWFvNe/Z/eGmtmQmsZcu9VIqjxT7e9xZr2csB9ZlOZiweAMFO5cuVWZZgfL+NYIaQiFi0E0DFXw== +"@react-native-community/cli-plugin-metro@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-7.0.1.tgz#c7a04651fe96dbb4d0534cd9efef1b044d899dfa" + integrity sha512-kM6vN5/38e9ldl30fUSVEB1sdB3a9W11N/HdU+7I3ujWsPdqu6DRiAaUV/L6y6az/QFBHKwAK0EZvROhY7G0vA== dependencies: - "@react-native-community/cli-server-api" "^7.0.4" - "@react-native-community/cli-tools" "^6.2.1" + "@react-native-community/cli-server-api" "^7.0.1" + "@react-native-community/cli-tools" "^7.0.1" chalk "^4.1.2" metro "^0.67.0" metro-config "^0.67.0" @@ -1174,34 +1201,20 @@ metro-runtime "^0.67.0" readline "^1.3.0" -"@react-native-community/cli-server-api@^7.0.4": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-7.0.4.tgz#b71e3413d4188b1bb3110267674ff31ce434b163" - integrity sha512-NzwLKgshx1aFJad5b972rFowEx8ueHRFFXQFnBbvEuE3KsivDOTIwO0zn7cAO1zpxlFRxUFfcI1Pe4Aymi3xZw== +"@react-native-community/cli-server-api@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-7.0.1.tgz#8fde9d615cf2cb296d0bed2933cf38d36af6f539" + integrity sha512-kquJcQ2PcrwYmbHakOxFsNIylM1tZM/+n7Wgy65dXMafA0cpEPDsOEdRHx2wfsqIavoxNLMliCu3NX5HM9DP2Q== dependencies: - "@react-native-community/cli-debugger-ui" "^7.0.3" - "@react-native-community/cli-tools" "^6.2.1" + "@react-native-community/cli-debugger-ui" "^7.0.1" + "@react-native-community/cli-tools" "^7.0.1" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.0" - nocache "^2.1.0" + nocache "^3.0.1" pretty-format "^26.6.2" serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-tools@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-6.2.1.tgz#6f7ada6559846b49fb9fcfed522399b232976ada" - integrity sha512-7RbOkZLT/3YG8CAYYM70ajRKIOgVxK/b4t9KNsPq+2uen99MGezfeglC8s1cs3vBNVVxCo0a2JbXg18bUd8eqA== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - lodash "^4.17.15" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - semver "^6.3.0" - shell-quote "^1.7.3" + ws "^1.1.0" "@react-native-community/cli-tools@^7.0.1": version "7.0.1" @@ -1218,49 +1231,35 @@ semver "^6.3.0" shell-quote "^1.7.3" -"@react-native-community/cli-types@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-6.0.0.tgz#90269fbdc7229d5e3b8f2f3e029a94083551040d" - integrity sha512-K493Fk2DMJC0ZM8s8gnfseKxGasIhuDaCUDeLZcoCSFlrjKEuEs1BKKEJiev0CARhKEXKOyyp/uqYM9nWhisNw== - dependencies: - ora "^3.4.0" +"@react-native-community/cli-types@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-7.0.1.tgz#c3de43d45866804c5c15251a014402da5853b7b1" + integrity sha512-8QedX5vagXoKFLzoyAEGeg2aOzNghjoXFP0Tm6LszdnFuNee03DLkGP7cKCEY+gtuhXLhdfd6XmK+ROgWqBEMQ== -"@react-native-community/cli@^7.0.3": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-7.0.4.tgz#cb4898bf9e3340ea812fa2bf194abd2429832752" - integrity sha512-W9nACtHWaLJZIP48cQmhQOnl5/7maoWE1Aji67MrLeIoB+ScNTJxaHfV4fMcklD6B6XEhaKokPACRZWm36zAog== +"@react-native-community/cli@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-7.0.1.tgz#6ece01540b855e0c5f1d24db43cb4c48854301c7" + integrity sha512-FjF+jszHNcmfzKvZ6Y9cp6jAuigc+JvyKmgtB5syj2nkjKNUMLY7gFkFV6ULAzLrg+IasMIImVSkN39+L1Pa9g== dependencies: - "@react-native-community/cli-debugger-ui" "^7.0.3" - "@react-native-community/cli-hermes" "^6.3.1" - "@react-native-community/cli-plugin-metro" "^7.0.4" - "@react-native-community/cli-server-api" "^7.0.4" - "@react-native-community/cli-tools" "^6.2.1" - "@react-native-community/cli-types" "^6.0.0" - appdirsjs "^1.2.4" + "@react-native-community/cli-config" "^7.0.1" + "@react-native-community/cli-debugger-ui" "^7.0.1" + "@react-native-community/cli-doctor" "^7.0.1" + "@react-native-community/cli-hermes" "^7.0.1" + "@react-native-community/cli-plugin-metro" "^7.0.1" + "@react-native-community/cli-server-api" "^7.0.1" + "@react-native-community/cli-tools" "^7.0.1" + "@react-native-community/cli-types" "^7.0.1" chalk "^4.1.2" - command-exists "^1.2.8" commander "^2.19.0" - cosmiconfig "^5.1.0" - deepmerge "^3.2.0" - envinfo "^7.7.2" execa "^1.0.0" find-up "^4.1.0" fs-extra "^8.1.0" - glob "^7.1.3" graceful-fs "^4.1.3" - joi "^17.2.1" leven "^3.1.0" lodash "^4.17.15" minimist "^1.2.0" - node-stream-zip "^1.9.1" - ora "^3.4.0" - pretty-format "^26.6.2" prompts "^2.4.0" semver "^6.3.0" - serve-static "^1.13.1" - strip-ansi "^5.2.0" - sudo-prompt "^9.0.0" - wcwidth "^1.0.1" "@reactions/component@^2.0.2": version "2.0.2" @@ -2188,10 +2187,10 @@ bplist-creator@0.1.0: dependencies: stream-buffers "2.2.x" -bplist-parser@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" - integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== +bplist-parser@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.0.tgz#ba50666370f61bbf94881636cd9f7d23c5286090" + integrity sha512-zgmaRvT6AN1JpPPV+S0a1/FAtoxSreYDccZGIqEMSvZl9DMe70mJ7MFzpxa1X+gHVdkToE2haRUHHMiW1OdejA== dependencies: big-integer "1.6.x" @@ -2323,7 +2322,7 @@ chalk@*: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2332,7 +2331,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^3: +chalk@^3, 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== @@ -2384,9 +2383,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" - integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== cjs-module-lexer@^0.6.0: version "0.6.0" @@ -2402,13 +2401,6 @@ clang-format@^1.2.4: glob "^7.0.0" resolve "^1.1.6" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2416,16 +2408,11 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.0.0: +cli-spinners@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== -cli-spinners@^2.5.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" - integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== - cli-table3@^0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" @@ -2832,15 +2819,6 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -deprecated-react-native-prop-types@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz#c10c6ee75ff2b6de94bb127f142b814e6e08d9ab" - integrity sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA== - dependencies: - "@react-native/normalize-color" "*" - invariant "*" - prop-types "*" - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -3615,10 +3593,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -flow-bin@^0.170.0: - version "0.170.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.170.0.tgz#1da264de9868cc20a338f801bedc370e3e06f5cc" - integrity sha512-h4qy4f5loKdeLhj7TRM6XQWhmPpnfjDcOg6GPDuJnLAQuB60LJIHZ8QL3hxMf0oA++NkiYx62Vr8oHu+UZ2bGQ== +flow-bin@^0.171.0: + version "0.171.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.171.0.tgz#43902cf3ab10704a9c8a96bd16f789d92490ba1c" + integrity sha512-2HEiXAyE60ztGs+loFk6XSskL69THL6tSjzopUcbwgfrdbuZ5Jhv23qh1jUKP5AZJh0NNwxaFZ6To2p6xR+GEA== flow-parser@0.*: version "0.180.0" @@ -3896,7 +3874,7 @@ globby@^11.0.0, globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -4160,7 +4138,7 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@*, invariant@^2.2.4: +invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -4580,20 +4558,20 @@ jest-haste-map@^26.6.2: fsevents "^2.1.2" jest-haste-map@^27.3.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" - integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.4.6.tgz#c60b5233a34ca0520f325b7e2cc0a0140ad0862a" + integrity sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^27.5.1" - jest-serializer "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" + graceful-fs "^4.2.4" + jest-regex-util "^27.4.0" + jest-serializer "^27.4.0" + jest-util "^27.4.2" + jest-worker "^27.4.6" micromatch "^4.0.4" walker "^1.0.7" optionalDependencies: @@ -4685,10 +4663,10 @@ jest-regex-util@^26.0.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-regex-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== +jest-regex-util@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" + integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== jest-resolve-dependencies@^26.6.3: version "26.6.3" @@ -4780,13 +4758,13 @@ jest-serializer@^26.6.2: "@types/node" "*" graceful-fs "^4.2.4" -jest-serializer@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" - integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== +jest-serializer@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.4.0.tgz#34866586e1cae2388b7d12ffa2c7819edef5958a" + integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== dependencies: "@types/node" "*" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" jest-snapshot@^26.6.2: version "26.6.2" @@ -4822,16 +4800,16 @@ jest-util@^26.6.2: is-ci "^2.0.0" micromatch "^4.0.2" -jest-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== +jest-util@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.4.2.tgz#ed95b05b1adfd761e2cda47e0144c6a58e05a621" + integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== dependencies: - "@jest/types" "^27.5.1" + "@jest/types" "^27.4.2" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" - graceful-fs "^4.2.9" + graceful-fs "^4.2.4" picomatch "^2.2.3" jest-validate@^24.9.0: @@ -4880,10 +4858,10 @@ jest-worker@^26.0.0, jest-worker@^26.6.2: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== +jest-worker@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" + integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== dependencies: "@types/node" "*" merge-stream "^2.0.0" @@ -5303,13 +5281,6 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -5712,11 +5683,6 @@ mime@^2.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5806,10 +5772,10 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nocache@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" - integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== +nocache@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.1.tgz#54d8b53a7e0a0aa1a288cfceab8a3cefbcde67d4" + integrity sha512-Gh39xwJwBKy0OvFmWfBs/vDO4Nl7JhnJtkqNP76OUinQz7BiMoszHYrIDHHAaqVl/QKVxCEy4ZxC/XZninu7nQ== node-dir@^0.1.17: version "0.1.17" @@ -6037,14 +6003,14 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== +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 "^1.0.0" + mimic-fn "^2.1.0" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -6082,17 +6048,10 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" - integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== - dependencies: - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-spinners "^2.0.0" - log-symbols "^2.2.0" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== ora@^5.4.1: version "5.4.1" @@ -6287,10 +6246,10 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -plist@^3.0.2, plist@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987" - integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA== +plist@^3.0.2, plist@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.4.tgz#a62df837e3aed2bb3b735899d510c4f186019cbe" + integrity sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg== dependencies: base64-js "^1.5.1" xmlbuilder "^9.0.7" @@ -6369,7 +6328,7 @@ prompts@^2.0.1, prompts@^2.1.0, prompts@^2.3.0, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@*, prop-types@^15.8.1: +prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -6449,11 +6408,6 @@ react-native-codegen@^0.0.17: jscodeshift "^0.13.1" nullthrows "^1.1.1" -react-native-gradle-plugin@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.6.tgz#b61a9234ad2f61430937911003cddd7e15c72b45" - integrity sha512-eIlgtsmDp1jLC24dRn43hB3kEcZVqx6DUQbR0N1ABXGnMEafm9I3V3dUUeD1vh+Dy5WqijSoEwLNUPLgu5zDMg== - react-refresh@^0.4.0: version "0.4.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" @@ -6537,7 +6491,7 @@ readdirp@~3.6.0: readline@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== + integrity sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw= recast@^0.20.4: version "0.20.5" @@ -6717,14 +6671,6 @@ resolve@~1.17.0: dependencies: path-parse "^1.0.6" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -6952,7 +6898,7 @@ shell-quote@^1.6.1, shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== -shelljs@^0.8.4: +shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== @@ -6986,13 +6932,13 @@ signedsource@^1.0.0: integrity sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww== simple-plist@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" - integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== + version "1.3.0" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.0.tgz#f451997663eafd8ea6bad353a01caf49ef186d43" + integrity sha512-uYWpeGFtZtVt2NhG4AHgpwx323zxD85x42heMJBan1qAiqqozIlaGrwrEt6kRjXWRWIXsuV1VLCvVmZan2B5dg== dependencies: bplist-creator "0.1.0" - bplist-parser "0.3.1" - plist "^3.0.5" + bplist-parser "0.3.0" + plist "^3.0.4" sisteransi@^1.0.5: version "1.0.5" @@ -7251,7 +7197,15 @@ supports-color@^8.0.0, supports-color@^8.1.0: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.1.0: +supports-hyperlinks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" + integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-hyperlinks@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== @@ -7528,6 +7482,11 @@ uglify-es@^3.1.9: commander "~2.13.0" source-map "~0.6.1" +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + integrity sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -7626,7 +7585,12 @@ uuid@^7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.3.0, uuid@^8.3.1: +uuid@^8.3.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" + integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== + +uuid@^8.3.1: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -7862,6 +7826,14 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== + dependencies: + options ">=0.0.5" + ultron "1.0.x" + ws@^6.1.4: version "6.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" @@ -7869,16 +7841,16 @@ ws@^6.1.4: dependencies: async-limiter "~1.0.0" -ws@^7, ws@^7.4.6: +ws@^7, ws@^7.5.1: + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== + +ws@^7.4.6: version "7.5.8" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a" integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== -ws@^7.5.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== - xcode@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" @@ -7914,11 +7886,16 @@ xmldoc@^1.1.2: dependencies: sax "^1.2.1" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + y18n@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"