From 793ebb8ba8260ced7df87f8f3e90a46b04ee2bf6 Mon Sep 17 00:00:00 2001 From: HeyImChris <48299693+HeyImChris@users.noreply.github.com> Date: Fri, 14 Jan 2022 13:11:09 -0800 Subject: [PATCH] Merge 0.66 into master (#951) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename immediate to ReactNativeMicrotask in Bridge Summary: Changelog: [Internal] This diff replaced all the internal occurrences of "Immediate" with "ReactNativeMicrotask" in the legacy bridge and then polyfilled the original immediate APIs during the timer setup phases as aliases of them. Note that this diff is part of a larger refactoring. Reviewed By: RSNara Differential Revision: D29785430 fbshipit-source-id: 7325d2a7358a6c9baa3e9abb8acf90414de5072f * Implement View.removeClippedSubviews prop Summary: Changelog: [internal] Fabric didn't have prop [removeClippedSubviews](https://reactnative.dev/docs/view#removeclippedsubviews) implemented. This diff adds it. It is Reviewed By: JoshuaGross Differential Revision: D29906458 fbshipit-source-id: 5851fa41d7facea9aab73ca131b4a0d23a2411ea * Add "Use Native Driver" control to RNTester Animated Composing example Summary: Changelog: [Internal] Reviewed By: yungsters Differential Revision: D29832704 fbshipit-source-id: dfd37d08d0f25fe86716a21682648894e8adad8b * docs: Fix dead links in README for rn-tester (#31901) Summary: Part of https://github.com/facebook/react-native/issues/31788 ~Updated link in README that was pointing to master branch to main branch~ Realized that link in rn-tester README and ReactAndroid README leads to a dead link, so I've fixed the links ## Changelog [INTERNAL] [FIXED] - Fix dead links in README Pull Request resolved: https://github.com/facebook/react-native/pull/31901 Test Plan: - [ ] Updated link directs you to appropriate page Reviewed By: PeteTheHeat Differential Revision: D29933044 Pulled By: GijsWeterings fbshipit-source-id: c1f301626acbb2995d74f78d8bc19214c70e9319 * docs: update links to forwarded page (#31903) Summary: Some of the links in `CONTRIBUTING.md` redirects you to a different page. I've fixed the links so each link would directly send users to the appropriate page. ## Changelog [INTERNAL] [Changed] - update links in CONTRIBUTING.md Pull Request resolved: https://github.com/facebook/react-native/pull/31903 Test Plan: - [ ] Change links shows the appropriate content Reviewed By: lunaleaps Differential Revision: D29933105 Pulled By: GijsWeterings fbshipit-source-id: b5be74181f8a8e88d8f43e44c469337b7393dedf * Remove redundant warnings for RCTMountingManager Summary: Changelog: [internal] The warnings are in-actionable for product engineers. Reviewed By: JoshuaGross Differential Revision: D29911438 fbshipit-source-id: f0f81588e8cbe88059e531c8be302ab19b8eb83f * Ignore when a text string or number is supplied as a child. Summary: Currently, React Native throws an invariant violation error when a text string or number is supplied as a child. This is undesirable because core library components should be fault-tolerant and degrade gracefully (with soft errors, if relevant). This change will work when a change in the host configs are landed (https://github.com/facebook/react/pull/21953). Changelog: [internal] Reviewed By: yungsters, sammy-SC Differential Revision: D29894182 fbshipit-source-id: 827ff299991a476b57981382d196c7ee1396ec28 * React Native sync for revisions cae6350...419cc9c Summary: This sync includes the following changes: - **[419cc9c37](https://github.com/facebook/react/commit/419cc9c37 )**: Fix: Hide new/updated nodes in already hidden tree ([#21929](https://github.com/facebook/react/pull/21929)) //// - **[4758e4533](https://github.com/facebook/react/commit/4758e4533 )**: React Native: Export getInspectorDataForInstance API ([#21572](https://github.com/facebook/react/pull/21572)) //// - **[ae5d26154](https://github.com/facebook/react/commit/ae5d26154 )**: Fix: LegacyHidden should not toggle effects ([#21928](https://github.com/facebook/react/pull/21928)) //// - **[9ab90de60](https://github.com/facebook/react/commit/9ab90de60 )**: Clean-up: Move Offscreen logic from Suspense fiber ([#21925](https://github.com/facebook/react/pull/21925)) //// - **[3f62dec84](https://github.com/facebook/react/commit/3f62dec84 )**: Typo fix ([#21729](https://github.com/facebook/react/pull/21729)) //// - **[5579f1dc8](https://github.com/facebook/react/commit/5579f1dc8 )**: Update test comments with explanations ([#21857](https://github.com/facebook/react/pull/21857)) //// - **[262ff7ad2](https://github.com/facebook/react/commit/262ff7ad2 )**: Refactor "disappear" logic into its own traversal ([#21901](https://github.com/facebook/react/pull/21901)) //// - **[34600f4fa](https://github.com/facebook/react/commit/34600f4fa )**: Refactor "reappear" logic into its own traversal ([#21898](https://github.com/facebook/react/pull/21898)) //// - **[310187264](https://github.com/facebook/react/commit/310187264 )**: Clean up flushSync flow types ([#21887](https://github.com/facebook/react/pull/21887)) //// - **[a97b5ac07](https://github.com/facebook/react/commit/a97b5ac07 )**: [Bugfix] Don't hide/unhide unless visibility changes ([#21875](https://github.com/facebook/react/pull/21875)) //// - **[81346764b](https://github.com/facebook/react/commit/81346764b )**: Run persistent tests in more configurations in CI ([#21880](https://github.com/facebook/react/pull/21880)) //// - **[9090257e6](https://github.com/facebook/react/commit/9090257e6 )**: fix: restore execution context after RetryAfterError completed ([#21766](https://github.com/facebook/react/pull/21766)) //// - **[14bac6193](https://github.com/facebook/react/commit/14bac6193 )**: Allow components to render undefined ([#21869](https://github.com/facebook/react/pull/21869)) //// - **[87b67d319](https://github.com/facebook/react/commit/87b67d319 )**: Enable scheduling profiler flag for react-dom profiling builds ([#21867](https://github.com/facebook/react/pull/21867)) //// - **[464f27572](https://github.com/facebook/react/commit/464f27572 )**: Update link to flow ([#21862](https://github.com/facebook/react/pull/21862)) //// - **[9f5224a9c](https://github.com/facebook/react/commit/9f5224a9c )**: Restore DevTools console message ([#21864](https://github.com/facebook/react/pull/21864)) //// - **[a4ecd85e8](https://github.com/facebook/react/commit/a4ecd85e8 )**: act: Batch updates, even in legacy roots ([#21797](https://github.com/facebook/react/pull/21797)) //// - **[c2c6ea1fd](https://github.com/facebook/react/commit/c2c6ea1fd )**: Capture suspense boundaries with undefined fallbacks ([#21854](https://github.com/facebook/react/pull/21854)) //// - **[0f09f14ae](https://github.com/facebook/react/commit/0f09f14ae )**: Check if already rendering before flushing //// - **[54e88ed12](https://github.com/facebook/react/commit/54e88ed12 )**: Bugfix: Flush legacy sync passive effects at beginning of event ([#21846](https://github.com/facebook/react/pull/21846)) //// - **[cb8afda18](https://github.com/facebook/react/commit/cb8afda18 )**: Add test for #21837 ([#21842](https://github.com/facebook/react/pull/21842)) //// - **[f85f429d5](https://github.com/facebook/react/commit/f85f429d5 )**: Use `act()` in ReactFabric tests ([#21839](https://github.com/facebook/react/pull/21839)) ([#21841](https://github.com/facebook/react/pull/21841)) //// - **[84639ab53](https://github.com/facebook/react/commit/84639ab53 )**: Guard against reused fibers in React Native commands ([#21837](https://github.com/facebook/react/pull/21837)) //// - **[c549bc491](https://github.com/facebook/react/commit/c549bc491 )**: Revert "Use `act()` in ReactFabric tests ([#21839](https://github.com/facebook/react/pull/21839))" ([#21840](https://github.com/facebook/react/pull/21840)) //// - **[59d3aca68](https://github.com/facebook/react/commit/59d3aca68 )**: Use `act()` in ReactFabric tests ([#21839](https://github.com/facebook/react/pull/21839)) //// - **[9ccc25a0e](https://github.com/facebook/react/commit/9ccc25a0e )**: Reverting recent flushSync changes ([#21816](https://github.com/facebook/react/pull/21816)) //// - **[ed6c091fe](https://github.com/facebook/react/commit/ed6c091fe )**: Replace unbatchedUpdates with flushSync ([#21776](https://github.com/facebook/react/pull/21776)) //// - **[32eefcb3c](https://github.com/facebook/react/commit/32eefcb3c )**: Replace flushDiscreteUpdates with flushSync ([#21775](https://github.com/facebook/react/pull/21775)) //// - **[ab390c65e](https://github.com/facebook/react/commit/ab390c65e )**: ReactDebugHooks optionally includes fileName, and line/column numbers ([#21781](https://github.com/facebook/react/pull/21781)) //// - **[c96761c7b](https://github.com/facebook/react/commit/c96761c7b )**: Delete batchedEventUpdates ([#21774](https://github.com/facebook/react/pull/21774)) //// - **[3e8c86c1c](https://github.com/facebook/react/commit/3e8c86c1c )**: fix: maxYieldInterval should not compare with currentTime directly in Scheduler-shouldYieldToHost //<郭帅彬>// - **[d483463bc](https://github.com/facebook/react/commit/d483463bc )**: Updated scripts and config to replace "master" with "main" branch ([#21768](https://github.com/facebook/react/pull/21768)) //// Changelog: [General][Changed] - React Native sync for revisions cae6350...419cc9c jest_e2e[run_all_tests] Reviewed By: JoshuaGross Differential Revision: D29913856 fbshipit-source-id: 58e4903766a312a64a17cfba0b0f684cf4bcacb0 * Remove option to make measure calls asynchronous Summary: Changelog: [internal] Making measure calls asynchronous in Fabric regresses core metrics, let's remove the option. Reviewed By: JoshuaGross Differential Revision: D29909385 fbshipit-source-id: eea3fefc8da757c8db82cb0af340650e2ce6a947 * Fix android view dimensions Summary: This diff fixes the Android View dimensions in VR PixelUtil.toSPFromPixel and PixelUtil.getDisplayMetricDensity() are both using getScreenDisplayMetrics() to perform conversion of dimensions. This is not correct because we should take into consideration the density of the Context / Activity instead of the Screen. This problem didn't raise before in Fabric Android because it seems that android OS on phones usually share the scale between the screen and the Activity? These two methods are only used in Fabric and they were introduced by D9583972 (https://github.com/facebook/react-native/commit/5c0da011cbaa788c52519f8091157ca6d87d8abb) and D9173758 (https://github.com/facebook/react-native/commit/8b5e3fc16b1e58441318b6ada629dcff572dd120) As part of this diff I'm also deleting the method toSPFromPixel in favor of toDIPFromPixel because I noticed the usages of these methods are meant to use toDIPFromPixel() changelog: [Internal] internal Reviewed By: JoshuaGross Differential Revision: D29864944 fbshipit-source-id: a0a093c120bde21a6cf9e1043a83c31e870d4368 * Refactor DevServerHelper to separate checking if packager running Summary: Changelog: [Internal] Separate the functionality of the isPackagerRunning() function into a new class PackagerStatusCheck with the intention of being able to use this without needing a DevServerHelper Reviewed By: makovkastar, ShikaSD Differential Revision: D29933318 fbshipit-source-id: d708bb987b08634015d6ee6b6c8989faba416c5a * Introduce queueMicrotask API Summary: Changelog: [General][Added] - Add global.queueMicrotask `queueMicrotask` is a relatively recent API defined in the WHATWG HTML spec and it's been widely adopted by all web browsers and Node.js. This diff introduced it to React Native by polyfilling it via a lazily-allocated resolved Promise, or calling directly into a fast path provided by Hermes. Reviewed By: RSNara Differential Revision: D29838852 fbshipit-source-id: 8c4378b1b713fb8b0da5e67f92ba2ea9838766f7 * Shim Immediate APIs when Promise is queueing to JSVM Summary: Changelog: [Internal] Historically, Immediate API is implemented upon the React Native's internal microtask-y queue (known as "immediate queue"), which is the same queue Promise polyfill is operating on. To make React Native suitable of using the built-in Promises from JSVMs, which usually enqueues to the JSVM internal microtask queue and has no access to React Native microtask-y queue, we need to migrate the Immediate API to use the JSVM microtask queue as well to preserve the semantics of code relies on the interleaving of promises and immediates. To do that, this diff implement a shim layer for immediate APIs via the new `global.queueMicrotask` API (which enqueues to JSVM) in JS, by wrapping the immediate callback into a "microtask callback", which validate the `immediate ID` against `clearedImmediate` Set before invoking it. Reviewed By: RSNara Differential Revision: D29845305 fbshipit-source-id: c2ed3fed426a5316b1e0dfbfaad51706d1765d4d * Attempt to fix undefined instance handle in EventTarget Summary: changelog: [internal] Completion block can retain `_eventEmitter` beyond existence of the component. To fix this, do not retain `_eventEmitter` by block but try to acquire it inside it. Reviewed By: JoshuaGross Differential Revision: D29969189 fbshipit-source-id: 456c42f816acc160f9d6bbd3f9c8c55d611940b2 * Makes "force" property available to Apple Pencil based events. (#31780) Summary: Fixes https://github.com/facebook/react-native/issues/31779 For more detailed explanation, see issue https://github.com/facebook/react-native/issues/31779 React Native touch handler events (onTouchStart, onTouchMoved, etc..) are intended to have "force" properties when used on devices which support pressure input (3D Touch & Apple Pencil events). However, due to a check in RCTForceTouchAvailable() function which checks for UITraitCollection's "forceTouchCapability" to be equal to UIForceTouchCapabilityAvailable, the check returns NO on iPad-based devices, due to iPad devices returning UIForceTouchCapabilityUnavailable at all times. This causes "force" values of Apple Pencils to never be passed on to React Native. Since simply passing 0 as a value for force across the RN bridge for every touch event seemed like a change that might seem jarring to some, I decided that a simple additional boolean check if the touch event's type is UITouchTypePencil (this is the same as UITouchTypeStylus) should also suffice. ## Changelog [iOS] [Fixed] - Fixed "force" property of touch events for Apple Pencil/Stylus devices. [iOS] [Feature] - Added "altitudeAngle" property to touch events from Apple Pencil/Stylus devices. Pull Request resolved: https://github.com/facebook/react-native/pull/31780 Test Plan: The code compiles and runs, and trying a simple handler for a View like ```` touchMove = (e: GestureResponderEvent) => { console.log(`pressure, altitude (${e.nativeEvent.force}, ${e.nativeEvent.altitudeAngle})`); ```` results in Screen Shot 2564-06-28 at 17 13 22 and when pencil is oriented perpendicular to the screen and pressed with full force shows Screen Shot 2564-06-28 at 17 13 58 Reviewed By: sammy-SC Differential Revision: D29964102 Pulled By: sota000 fbshipit-source-id: 5a1f41d64c6fe325afbd2b9579eaf20a522e92dc * Fix typo in VirtualizedList-test.js (#31756) Summary: occured -> occurred ## Changelog [Internal] [Fixed] - Fixed typo in VirtualizedList-test.js Pull Request resolved: https://github.com/facebook/react-native/pull/31756 Test Plan: NONE Reviewed By: lunaleaps Differential Revision: D29975153 Pulled By: charlesbdudley fbshipit-source-id: 966d90df0bf015b4a6a2e3b1bf88c66b61161a7a * Pass context through to all prop parser (core changes) Summary: Unfortunately, parsing some props requires stateful context - namely, PlatformColor on Android. We explored several different options but they all seemed inferior to the approach of using ContextContainer, and most would require using global state. By introducing this change everywhere as early as possible, we can avoid later pain. It is likely that some prop, on some platform, will require this mechanism. We'll be ready for it! Because we can pass a constref of the ContextContainer through to all props and because the context and context data is never retained by prop parsers, perf and memory hit should be ~0. This diff contains core changes only. Leaf changes to all props structs and conversions files will be in next diff(s). Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D29838789 fbshipit-source-id: f5090e7f02eb6e8fbe0ef4dd201e7d12104a3e3c * Pass context through to all prop parser (props structs changes) Summary: See previous diffs for context. This updates all of the relevant props structs. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D29855426 fbshipit-source-id: 30177c3380ef82ecf8f2a4321f128cfbe8a576e0 * Pass context through to all prop parser (conversions.h) Summary: See previous diffs for context. This updates all conversions.h files. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D29855425 fbshipit-source-id: d5751ddfc2724392e3a35f5e22bb68574e95e737 * Pass PropsParserContext to prop parsing layer Summary: Changelog: [internal] Reviewed By: mdvacca Differential Revision: D29921232 fbshipit-source-id: ba045f545b564aedf1b287045a0e75428de30a0f * Fix typo in Constants.h (#31049) Summary: controling -> controlling ## Changelog [Internal] [Fixed] - Fixed typo in comment Pull Request resolved: https://github.com/facebook/react-native/pull/31049 Test Plan: NONE Reviewed By: lunaleaps Differential Revision: D29980007 Pulled By: charlesbdudley fbshipit-source-id: 419f28f08d74faa07db18a07ab41b62c41776344 * Daily `arc lint --take CLANGFORMAT` Reviewed By: zertosh Differential Revision: D29983521 fbshipit-source-id: bebd38e79180c544c8c1986605cc1af4b1f4df98 * Update Dimension.js typo (#29858) Summary: preferred instead of preffered ## Changelog [CATEGORY] [TYPE] - Message Pull Request resolved: https://github.com/facebook/react-native/pull/29858 Reviewed By: charlesbdudley Differential Revision: D29998754 Pulled By: sota000 fbshipit-source-id: f13fef58e9154ddf8087944d53e022fb9afa6b1b * Make existential type an error in xplat Summary: This diff updates the xplat flowconfigs to make existential types an error. Changelog: [Internal] Reviewed By: pieterv Differential Revision: D29967838 fbshipit-source-id: f08bbafe2a0269adb2c9afa4572b7a34fd254a4d * Remove unused import (#30544) Summary: Remove unused import ## Changelog [iOS] [performance] - Remove unused import Pull Request resolved: https://github.com/facebook/react-native/pull/30544 Test Plan: Should build on CI Reviewed By: lunaleaps Differential Revision: D30000901 Pulled By: charlesbdudley fbshipit-source-id: 3d3310917823b7af57564ca1ea397cd32cd0c4d5 * Updated TextInput autoCompleteType prop to autoComplete 1/2 (#26010) Summary: Fix for bug https://github.com/facebook/react-native/issues/26003 Rename TextInput prop "autoCompleteType" to "autoComplete". ## Changelog [Android] [Changed] - Updated `autoCompleteType` prop of `TextInput` to `autoComplete` Pull Request resolved: https://github.com/facebook/react-native/pull/26010 Test Plan: Test Pass PR for [Doc Update](https://github.com/facebook/react-native-website/pull/1184) Reviewed By: mdvacca Differential Revision: D29980220 Pulled By: lunaleaps fbshipit-source-id: 3c9e7d3250b5f95b0dbd523fdb0d917a039cd6a9 * Implement PlatformColor in Fabric Android Summary: This diff implements PlatformColor in Fabric Android changelog: [internal] internal Reviewed By: JoshuaGross Differential Revision: D29841461 fbshipit-source-id: 63a523626b021c634bc399e749b639b55730391a * Allows to set individual (left,top,right,bottom) dotted/dashed borders (#29099) Summary: This issue: fixes https://github.com/facebook/react-native/issues/24224 fixes https://github.com/facebook/react-native/issues/28695 fixes https://github.com/facebook/react-native/issues/23651 fixes https://github.com/facebook/react-native/issues/23475 fixes https://github.com/facebook/react-native/issues/22256 fixes https://github.com/facebook/react-native/issues/22226 fixes https://github.com/facebook/react-native/issues/19234 fixes https://github.com/facebook/react-native/issues/18285 fixes https://github.com/facebook/react-native/issues/17344 fixes https://github.com/facebook/react-native/issues/17343 fixes https://github.com/facebook/react-native/issues/17251 fixes https://github.com/facebook/react-native/issues/12817 fixes https://github.com/facebook/react-native/issues/12403 fixes https://github.com/facebook/react-native/issues/11042 fixes https://github.com/facebook/react-native/issues/9343 fixes https://github.com/facebook/react-native/issues/8236 fixes https://github.com/facebook/react-native/issues/8105 fixes https://github.com/facebook/react-native/issues/7838 fixes https://github.com/facebook/react-native/issues/6721 fixes https://github.com/facebook/react-native/issues/5411 fixes https://github.com/facebook/react-native/issues/3159 fixes https://github.com/facebook/react-native/issues/2335 fixes https://github.com/facebook/react-native/issues/840 fixes https://github.com/facebook/react-native/issues/27133 fixes https://github.com/facebook/react-native/issues/28695 Allows to set individual (left,top,right,bottom) dotted/dashed borders. If a single border is specified and the borderStyle is dotted or dashed, each border will be drawn with moveTo and lineTo taking in consideration of the border style and thickness. ## Changelog [Android] [Fixed] - Quickfix individual border style dotted or dashed rendering as solid Pull Request resolved: https://github.com/facebook/react-native/pull/29099 Test Plan: **
CLICK TO OPEN TESTS RESULTS**

| **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | | | **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | | | **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | | | **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | | | **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | | | **AFTER** | **AFTER** | |:-------------------------:|:-------------------------:| | | |

Reviewed By: mdvacca Differential Revision: D28688914 Pulled By: RSNara fbshipit-source-id: 34781d63265dcf55e30f11c014e6b4a35d67dcbd * Correct error message in getViewState method Summary: Changelog: [internal] Here, getting `viewState` has failed, not its view property. Reviewed By: mdvacca Differential Revision: D30042652 fbshipit-source-id: 42831b577f17db1f64860e68be33870f5be27207 * Clean up RAIICallbackManager experiment Summary: This experiment was shipped in D27436402 (https://github.com/facebook/react-native/commit/3d1afbbda301d48a75e45f73b96cd51ae5105dd8). Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30023039 fbshipit-source-id: 5f7335f2ddaf6f4e2d876a917aaff2cf3d906b5c * Stop sharing LongLivedObjectCollection with the bridge Summary: ## Context Previously, when you'd call TurboModule methods with JavaScript callbacks, we'd [store the callbacks](https://www.internalfb.com/code/fbsource/[c503ff1b38621aebca87b2bbebeae088b01886c4]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm?lines=173%2C248-249) into [this global LongLivedObjectCollection collection](https://www.internalfb.com/code/fbsource/[c503ff1b38621aebca87b2bbebeae088b01886c4]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h?lines=65). Then, when React Native's JavaScript VM got torn down, we'd [clear the global collection](https://www.internalfb.com/code/fbsource/[e26f476ce208c578f05b1edb7639d1dad5612c7d]/xplat/js/react-native-github/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp?lines=49), which would ensure that we deleted all held jsi::Functions, before deleting the jsi::Runtime. ## Problem With bridgeless mode enabled, there can be two TurboModule systems. Further, it is possible to tear down bridgeless mode, or the bridge, without tearing down the other initialization infra. In this scenario, the jsi::Function for the other initialization infra would also get deleted, which could lead to mysterious problems. ## Fix In this diff, I refactored the jsi::Function cleanup in the TurboModule system. Now, there are 3 modes: - kGlobalScope: Everything works as it did before - kRCTGlobalScopeUsingRetainJSCallback: We still use the global LongLivedObjectCollection, but we do it through invoking a block passed to every ObjCTurboModule by the TurboModuleManager. This group exists to assess the impact of having each TurboModule retain/use the block. I suspect this will be negligible, but it'd be good to have actual data to back this claim. - kRCTTurboModuleManagerScope: Every TurboModule uses a LongLivedObjectCollection that is owned by its TurboModuleManager. This should effectively fix the problem I outlined above. Changelog: [Internal] Reviewed By: p-sun Differential Revision: D30019833 fbshipit-source-id: da50d884c7e37190107f570d8ed70eeda7d9ae83 * Stop sharing LongLivedObjectCollection with the bridge Summary: This is the Android analogue to D30019833. Changelog: [Internal] Reviewed By: p-sun Differential Revision: D30029295 fbshipit-source-id: 13df0dfb915697eeedcc527dcdb6c246e89afb0c * setup fragment based tab bar navigation Summary: `Changelog: [Android] [Changed] - Make ReactFragment variables protected instead of private, create getter for ReactDelegate` Reviewed By: keoskate Differential Revision: D29981436 fbshipit-source-id: 3e5df811cd07edccf37f72c9f917f9ea0882be0b * Remove 'using namespace facebook::jni' Summary: Ez diff to remove 'using namespace facebook::jni' changelog: [internal] internal Reviewed By: sshic Differential Revision: D30046080 fbshipit-source-id: 52100970a408d772854cc0783fa13edd0cc39235 * Add TODO to fix and enable 'generated_tests-codegen_testsAndroid' Summary: Add TODO to fix and enable 'generated_tests-codegen_testsAndroid' changelog: [internal] internal Reviewed By: JoshuaGross Differential Revision: D30046143 fbshipit-source-id: dbeba6f1d51b32c069bda8bb9ca976014d299dae * Move RNTester Buck library to GitHub (#31435) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31435 Moves the Facebook-internal Buck target definition for RNTester closer to the actual source files. This does not affect how RNTester is built in open source. Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D27942209 fbshipit-source-id: 66c970a5464a9329597d155ceeca78fb7f4834e8 * Move react-native Buck library to GitHub Summary: Moves the Facebook-internal Buck target definition for React Native closer to the actual JS source files. This does not affect how React Native is built in open source. Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D27942687 fbshipit-source-id: 328febb661ed6597feafdfd8efb2a95365325348 * Extract feature detection as an utilitiy module Summary: Changelog: [Internal] This diff only extracted the `isNativeFunction` used in `setUpTimers` into the `FeatureDetection` utility, but later we will add more functions in it and reuse them in other places. Reviewed By: RSNara Differential Revision: D29986750 fbshipit-source-id: 6e48e38d92ceccb35eead3c52e00e1eecb81b5b0 * Conditionalize the Regenerator Setup Summary: Changelog: [Internal] If generators are provided natively, that should suggest that the JS source code did not go through the regenerator-transform (e.g. in Metro Hermes profile), then there is no need to set up the regenerator runtime. This should save some work during the Core initialization. Reviewed By: motiz88 Differential Revision: D29986751 fbshipit-source-id: 129f5122e8e4c05535ee2aa5da6970a66843e8cd * Protect against crashes when over-releasing a TouchEvent Summary: It seems that, possibly due to optimizations and refactoring elsewhere in the event system, some TouchEvents are being over-disposed. This doesn't really pose a problem besides performance; and could even indicate that an Event was in a pool but never properly initialized. In these cases it seems perfectly reasonable to silently continue, and to log a soft exception. This WILL still crash in debug mode, so we can gather more information if we find a good repro; otherwise we will continue to get production data from this soft exception if it's an issue and we can investigate further. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D30061178 fbshipit-source-id: 05d1f60afc382ce0a202ac8f3de34770cf9a760d * Co-locate Buck targets for JS polyfills with their sources Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30032230 fbshipit-source-id: 0d714b4e0a79a9c5c1c21e79f782635d8bd9c5f1 * chore: update Dimensions API Flow types (#31898) Summary: This small PR updates the Flow types used in Dimensions. The following changes has been made: * generic types has been replaced with types from `NativeDeviceInfo` (which already were used in event subscription update) * ~simplification of `DisplayMetricsAndroid` by spreading via intersection with `DisplayMetrics` type and removing shared properties~ > I have tried both notations, but according to the lint, it looks like a Native Modules typing limitation which requires redundancy / code duplication in cases like this. ## Changelog [Internal] [Changed] - update Dimensions API Flow types Pull Request resolved: https://github.com/facebook/react-native/pull/31898 Test Plan: Running `yarn flow` in the workspace yields no errors. Reviewed By: yungsters Differential Revision: D29932940 Pulled By: GijsWeterings fbshipit-source-id: bf97bb972964c585207e2450ccf71d932555e291 * Fix order of calls for Native Animated Module Summary: Changelog: [internal] Make sure the order of call is preserved for `NativeAnimatedModule`. The order of calls to NativeAnimatedModule needs to be preserved because its internals depend on it. For example, if you `getValue` is called before `createAnimatedNode`, it causes a crash. To resolve it, we need to enqueue `getValue` onto operationQueue. Reviewed By: JoshuaGross Differential Revision: D30035911 fbshipit-source-id: bbd698a96cada5d2b1312a1a689ca99b04a07cdc * Merge BUCK file at Libraries/ into root Summary: Merges the Facebook-internal Buck target definitions in `Libraries/` into the BUCK file at the root of the repo (which is currently not synced to GitHub at all). This does not affect how React Native is built in open source. Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D27967499 fbshipit-source-id: 39c51a544b3868242598072d24cb6cfb5a6e2d8c * Fix Buck package boundary violation in core components schema Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D29996246 fbshipit-source-id: e560c7261c4274da5219dc1e2d59d46b60e7549e * Allow resolving view from FabricUIManager Summary: Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30043188 fbshipit-source-id: d8675754b29fb58a28a06777f602098da6dbc27f * Flush operations queue when animation starts Summary: changelog: [internal] If nodesManager has the information if animated node is managed by Fabric, we can't decide if the operation queue should be flushed before it is flushed. Therefore, keep the information about animated nodes inside a set instead of nodesManager. For simplicity, I will refer to class `RCTNativeAnimatedTurboModule` as *NativeAnimated* and to `RCTNativeAnimatedNodesManager` as *NodesManager* Notice that each call to *NativeAnimated* is queued up in `_operations` or `_preOperations`. When the queues are flushed, only then methods are called on `RCTNativeAnimatedNodesManager`. There are two mechanisms that flush operations. One is triggered by `RCTMountingManager` before mounting operations are applied and after they are applied. This works fine but is important to paint the picture. The second mechanism is inside `[RCTNativeAnimatedTurboModule startAnimatingNode]`. It flushes the queues for Fabric nodes only (not sure why Fabric nodes only, I couldn't find any explanation in old diffs). It checks with *NativeAnimated* if a node is managed by Fabric. Keep in mind, *NodesManager* only knows about the nodes when the queues have been flushed. Exampe: JavaScript calls methods on *NativeAnimated*. For example: 1. `createNode` 2. `connectAnimatedNodeToView` 3. `startAnimatingNode`. (here, the queues should be flushed, since we are in Fabric) All of these operations are queued up and for as long as `RCTMountingManager` executes mounting, all proceeds as expected. But if those operations happen after mounting phase, `startAnimatingNode` will not flush the operations queues, because it can't tell if nodeTag is managed by fabric or it isn't. This is because *NodesManager* hasn't been notified about any new nodes. Reviewed By: JoshuaGross, p-sun Differential Revision: D30053890 fbshipit-source-id: b7fe24861d5300f9cfefa813a53df8330fa56d86 * iOS: Log error when invalid NSNull data is passed to RCTAsyncLocalStorage Summary: Changelog: [Internal] Differential Revision: D30081478 fbshipit-source-id: 7d425e71b020eaeb4eb1b33b500fbf5df7ea9c29 * fbshipit-source-id: 909b2667480ed96ae376896d966f6c27f5e73964 * Update OSS Buck definitions (#31948) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31948 Changelog: [Internal] Adds necessary shims to bring our BUCK files closer to parsing/building correctly in open source. This is part of fixing the Buck-based tests on CircleCI which were broken by https://github.com/facebook/react-native/commit/d4ee734f3297463fe7b54af6d69e4ea151cf4cf9. Reviewed By: sammy-SC Differential Revision: D30072866 fbshipit-source-id: 4aebd9f67dd0a102516603915d9a021032611279 * Update Android Dockerfile to include root BUCK file (#31950) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31950 Changelog: [Internal] Adds the root BUCK file to the Docker image we use to test RNTester on CircleCI. See https://github.com/facebook/react-native/commit/df9cd05621f58fe5c67f889b741bfff20c780b0e Reviewed By: ShikaSD Differential Revision: D30099261 fbshipit-source-id: 936c505a0f4e7b791743901a06fa3b14c40b183e * Check for negative `numberOfLines` in TextView Summary: Negative `numberOfLines` prop is not supported by Android and causes a crash during layout measurement. This change adds a check in JS to catch the error earlier. Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30047103 fbshipit-source-id: 4248a0f573c3b6facd25c7ae6ce007a357a1469b * Fix NPE when hierarchy return null values Summary: This diff fixes a NullPointer that was being thorwn when hierarchy values are null changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D30095407 fbshipit-source-id: b0a13661b4506cf94eeb5d99923d4c12cba0f972 * Extend getInspectorDataForInstance to return props Summary: This diff extends the FabricUIManager.getInspectorDataForInstance to return the props of the React Native component associated to the view passed as a parameter. changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D30095406 fbshipit-source-id: 50fdba6636a1f5042dbc113e341c3cb2534a1b04 * Add documentation for FabricUIManager.getInspectorDataForInstance Summary: Add documentation for FabricUIManager.getInspectorDataForInstance changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D30095818 fbshipit-source-id: dfe8590598099e7581460ca45bc0e779690463a6 * chore: remove FlowFixMe (#29468) Summary: Removed FlowFixMe that has been fixed ## Changelog [General] [Fixed] - Removed FlowFixMe that has been fixed Pull Request resolved: https://github.com/facebook/react-native/pull/29468 Test Plan: flow check passes Reviewed By: JoshuaGross Differential Revision: D29967702 Pulled By: lunaleaps fbshipit-source-id: 541279287ba6f21c5c7290bcba7c282f092126ff * Move RCT* Buck targets to GitHub Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30030454 fbshipit-source-id: 02a4c36f5c5ca519e4de3d1a3d79708d0d0b6d01 * Move integration test Buck targets to GitHub Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30032467 fbshipit-source-id: 56e293c821f02e78fe13f5e7f22bcb2b2050019a * Move RNTester unit/integration test Buck targets to GitHub Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30032476 fbshipit-source-id: d1f9a39a6d2fc92f69b9ee931c2a0f3ba37687f6 * Move RCTTestApple into packages/rn-tester Summary: Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D30056021 fbshipit-source-id: 9012ca6934f95946ff157ca472aa6a6e84d7d7e9 * React Native sync for revisions 419cc9c...19092ac Summary: This sync includes the following changes: - **[19092ac8c](https://github.com/facebook/react/commit/19092ac8c )**: Re-add old Fabric Offscreen impl behind flag ([#22018](https://github.com/facebook/react/pull/22018)) //// - **[215db465a](https://github.com/facebook/react/commit/215db465a )**: [Fabric] Add `flex: 1` to Offscreen view container ([#22019](https://github.com/facebook/react/pull/22019)) //// - **[8a37b0ef3](https://github.com/facebook/react/commit/8a37b0ef3 )**: typos fixed ([#21955](https://github.com/facebook/react/pull/21955)) //// - **[e3049bb85](https://github.com/facebook/react/commit/e3049bb85 )**: DevTools scheduling profiler: Add React component measures ([#22013](https://github.com/facebook/react/pull/22013)) //// - **[27bf6f9a8](https://github.com/facebook/react/commit/27bf6f9a8 )**: Scheduling profiler UX changes ([#21990](https://github.com/facebook/react/pull/21990)) //// - **[f0d354efc](https://github.com/facebook/react/commit/f0d354efc )**: [Fabric] Fix reparenting bug in legacy Suspense mount ([#21995](https://github.com/facebook/react/pull/21995)) //// - **[34308b5ad](https://github.com/facebook/react/commit/34308b5ad )**: Tidy up early bailout logic at start of begin phase ([#21852](https://github.com/facebook/react/pull/21852)) //// - **[321087d13](https://github.com/facebook/react/commit/321087d13 )**: [Fizz] Don't add aborted segments to the completedSegments list ([#21976](https://github.com/facebook/react/pull/21976)) //// - **[4cc8ec64c](https://github.com/facebook/react/commit/4cc8ec64c )**: Separate unit tests for ReactFabricHostComponent ([#21969](https://github.com/facebook/react/pull/21969)) //// - **[d4d786493](https://github.com/facebook/react/commit/d4d786493 )**: Fix `ReactFabricHostComponent` methods if detached ([#21967](https://github.com/facebook/react/pull/21967)) //// - **[392253a77](https://github.com/facebook/react/commit/392253a77 )**: [Fabric] Use container node to toggle the visibility of Offscreen and Suspense trees ([#21960](https://github.com/facebook/react/pull/21960)) //// Changelog: [General][Changed] - React Native sync for revisions 419cc9c...19092ac jest_e2e[run_all_tests] Reviewed By: JoshuaGross Differential Revision: D30092460 fbshipit-source-id: 9f118db2419a9a5db26a9b873868f91ab88f2f89 * refactor!: drop deprecated `StatusBarIOS` (#31466) Summary: This component has been merged with `StatusBar` and deprecated since [Jun 24, 2019](https://github.com/facebook/react-native/commit/a8337785539d572009d2cc4263aef7755ae03097) ## Changelog [JavaScript] [Removed] - refactor!: drop deprecated `StatusBarIOS` Pull Request resolved: https://github.com/facebook/react-native/pull/31466 Test Plan: Warning when user imports `StatusBarIOS` Reviewed By: yungsters Differential Revision: D30109324 Pulled By: lunaleaps fbshipit-source-id: fa2d3aa2cf35206ed8a196e09f12af57d3b61ccc * Fix OSS Buck parsing errors (#31957) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31957 Changelog: [Internal] Some fixes for the GitHub shims for FB-internal Buck macros. Should fix the Buck-related breakages in the `test_android` and `test_docker` CI jobs. Also adds license headers to some recently-added files that didn't have them. Reviewed By: mdvacca Differential Revision: D30114177 fbshipit-source-id: 88a24fa7130bd98dd60568566bde51fcfc89df60 * Fix Buck package boundary violation involving RCTEventDispatcher.h (#31965) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31965 Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D30030580 fbshipit-source-id: 3b4140a831c7ad7282aae0ff79c54014dcd82615 * Remove package boundary exceptions in OSS Buck config Summary: Changelog: [Internal] Reviewed By: stepancheg Differential Revision: D30102445 fbshipit-source-id: 571ab5dc41379e01d4482f64418f6383f660dbfa * Update JSLoader.cpp (#29270) Summary: Since react-native-cli is deprecated, the correct command should be `npx react-native start` Pull Request resolved: https://github.com/facebook/react-native/pull/29270 Reviewed By: sammy-SC Differential Revision: D30017028 Pulled By: sota000 fbshipit-source-id: cfcf9e1d150f51750a4e86133bd3167506ee7348 * Warn when negative `numberOfLines` prop set on component Summary: Updates previous variant that was crashing a surface to the non-crashing variant. Now it prints error in console and modifies value to be 0. Changelog: [General][Fixed] Clamp negative values for `numberOfLines` in component Reviewed By: yungsters Differential Revision: D30129658 fbshipit-source-id: fda47a262365573514d3e1e4bf8a26f6d30cdae0 * Make So loading inside generated TMM delegates less confusing Summary: ## Rationale Inlining the maybeLoadSoLibrary private static method makes following the So load chain from TurboModuleManagerDelegate through ReactPackageTurboModuleManagerDelegate to each app's TurboModuleManagerDelegate much easier to understand. Changelog: [Internal] Reviewed By: sshic Differential Revision: D30082675 fbshipit-source-id: ff467d6ac8c792317dd9bdcd91844d3b480cbb60 * Add TODOs to unify component names between JS - Android - iOS - C++ Summary: EZ diff that adds a few TODOs to unify component names between JS - Android - iOS - C++ see task: T97384889 changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D30139942 fbshipit-source-id: 91f51d04e7e7ecba7f059f94a121be43d820647d * Replace Paper -> old renderer Summary: Replace Paper -> old renderer changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D30139941 fbshipit-source-id: 3bb1e81a3df018aa669f3dba1de445107d70116c * Fix Deadlock in RCTi18nUtil (iOS) (#31032) Summary: Note: PR to react-native-macos here https://github.com/microsoft/react-native-macos/pull/733 Internally in Microsoft code, we ran into a deadlock where the main queue and the UIManager queue were both trying to access `[RCTI18nUtil sharedInstance]`, and were blocked on each other. This is similar to an earlier issue with RCTScreenScale decsribed [here](https://github.com/facebook/react-native/issues/18096). To summarize: 1- RCTShadowView (on the UIManager queue) and RCTView (on the main queue) both try to access `[RCTI18nUtil sharedInstance]` 2- The UIManager thread gets there first, and lazily initializes the sharedInstance. Meanwhile, the main thread is waiting on a lock possessed by the UIManager thread 3- As part of the initialization, we set an NSUserDefault, which seems to require the (blocked) main thread. 4- Deadlock. For whatever reason, this only happens on debug. I did not figure out why, but I do know based on [this comment](https://github.com/facebook/react-native/issues/18096#issuecomment-368718081), that the UIManagerQueue should never block the main queue. The fix is to not use NSUserDefaults, and simpy use atomic properties instead. We get the thread safety for free, and it also simplifies the code somewhat without changing the public API. The downside is values aren't persisted anymore, but I do not think that was necessary / intended. ## Changelog [iOS] [Fixed] - Fix deadlock on RCTi18nUtil Pull Request resolved: https://github.com/facebook/react-native/pull/31032 Test Plan: Ran the RTLExample in RNTester, and ensured switching to RTL still worked, and that setting forceRTL would still work after reloading the bundle. https://user-images.githubusercontent.com/6722175/108775429-aefdae80-7526-11eb-9a89-3114f7ddc2af.mov Reviewed By: javache Differential Revision: D29522152 Pulled By: RSNara fbshipit-source-id: 160840f63a7b1d6721b0fd8294fb11990a4509fa * Codegen: Always prepare filesystem Summary: For any Pod that uses the codegen, create references to code-gen'd files in local filesystem regardless of Pod install status by invoking the same command used by `prepare_command` whenever `pod install` is run. This works around the issue where CocoaPods may decide to skip running `prepare_command`. While this is expected CocoaPods behavior, external factors may result in the deletion of the original code-gen'd files in which case we need to make sure that running `pod install` will bring these files back. See Test Plan for more details on how to reproduce the issue being fixed. Fixes T97404254. Changelog: [Internal] Codegen invoked with every `pod install` regardless of pod install status Differential Revision: D30116640 fbshipit-source-id: 81db5dff1d4c4f8ae22b5dbe822609c770789ac8 * - Bump CLI to ^6.0.0 (#31971) Summary: Upgrade CLI to the v6 stable. [Changelog](https://github.com/react-native-community/cli/releases/tag/v6.0.0) ## Changelog [General] [Fix] - Bump CLI to ^6.0.0 Pull Request resolved: https://github.com/facebook/react-native/pull/31971 Test Plan: cc kelset grabbou Reviewed By: TheSavior Differential Revision: D30158170 Pulled By: ShikaSD fbshipit-source-id: 392e22cb112a830778149b4a2b4a19198facf42b * Fix to make taps on views outside parent bounds work on Android (#29039) Summary: By default, Views in React Native have `overflow: visible`. When a child view is outside of the parent view's boundaries, it's visible on Android, but not tappable. This behaviour is incorrect, and doesn't match iOS behaviour. - Taps on Views outside the bounds of a parent with `overflow: visible` (or unset) should register - Taps on Views outside the bounds of a parent with `overflow: hidden` should continue to not register Related issues: - fixes https://github.com/facebook/react-native/issues/21455 - fixes https://github.com/facebook/react-native/issues/27061 - fixes https://github.com/facebook/react-native/issues/27232 ### Fix - Made `findTouchTargetView` not check that the touch was in the bounds of the immediate children, but instead - Check that the touch is in its own bounds when returning itself - Check that the touch for a child is in its own bounds only when `overflow: hidden` is set - Modified related code to adjust to this change - Added RNTesterApp test ## Changelog [Android] [Fixed] - Allow taps on views outside the bounds of a parent with `overflow: hidden` Pull Request resolved: https://github.com/facebook/react-native/pull/29039 Test Plan: This can be tested with 2 examples added to the bottom of the PointerEvents page of the RNTesterApp: | Before | After | | --- | --- | | ![Before](https://user-images.githubusercontent.com/2937410/83610933-19079b00-a535-11ea-8add-22daae0191e1.gif) | ![After](https://user-images.githubusercontent.com/2937410/83610583-8830bf80-a534-11ea-97e2-71e180a70343.gif) | Reviewed By: ShikaSD Differential Revision: D30104853 Pulled By: JoshuaGross fbshipit-source-id: 644a109706258bfe829096354dfe477599e2db23 * Create slider accessibility delegate in createViewInstance (#31942) Summary: Recent change in https://github.com/facebook/react-native/pull/31865 made it so if `ReactSliderManager` is created on the react context creation thread it will crash with the following error. This happens because `ReactAccessibilityDelegate` tries to create a handler on a thread without a looper. This seems to happen because react-native-reanimated tries to get the UIManager module during its initialization which will cause view managers to be created and explains why the crash probably does not happens in RNTester or using only RN bundled modules. ``` 08-03 14:44:56.318 21206 21360 E AndroidRuntime: FATAL EXCEPTION: create_react_context 08-03 14:44:56.318 21206 21360 E AndroidRuntime: Process: com.th3rdwave, PID: 21206 08-03 14:44:56.318 21206 21360 E AndroidRuntime: java.lang.ExceptionInInitializerError 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.shell.MainReactPackage.createViewManagers(MainReactPackage.java:166) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.ReactInstanceManager.getOrCreateViewManagers(ReactInstanceManager.java:882) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.CoreModulesPackage.createUIManager(CoreModulesPackage.java:137) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.CoreModulesPackage.getModule(CoreModulesPackage.java:102) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.TurboReactPackage$ModuleHolderProvider.get(TurboReactPackage.java:159) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.TurboReactPackage$ModuleHolderProvider.get(TurboReactPackage.java:147) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.ModuleHolder.create(ModuleHolder.java:191) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.ModuleHolder.getModule(ModuleHolder.java:156) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.NativeModuleRegistry.getModule(NativeModuleRegistry.java:153) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.CatalystInstanceImpl.getNativeModule(CatalystInstanceImpl.java:486) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.CatalystInstanceImpl.getNativeModule(CatalystInstanceImpl.java:462) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.bridge.ReactContext.getNativeModule(ReactContext.java:176) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.swmansion.reanimated.NodesManager.(NodesManager.java:153) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.swmansion.reanimated.ReanimatedModule.getNodesManager(ReanimatedModule.java:101) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.swmansion.reanimated.ReanimatedJSIModulePackage.getJSIModules(ReanimatedJSIModulePackage.java:17) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.th3rdwave.MainApplication$1$1.getJSIModules(MainApplication.java:135) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.ReactInstanceManager.createReactContext(ReactInstanceManager.java:1329) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.ReactInstanceManager.access$1100(ReactInstanceManager.java:136) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.ReactInstanceManager$5.run(ReactInstanceManager.java:1058) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at java.lang.Thread.run(Thread.java:923) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: Caused by: java.lang.RuntimeException: Can't create handler inside thread Thread[create_react_context,5,main] that has not called Looper.prepare() 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at android.os.Handler.(Handler.java:227) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at android.os.Handler.(Handler.java:129) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.uimanager.ReactAccessibilityDelegate$1.(ReactAccessibilityDelegate.java:185) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.uimanager.ReactAccessibilityDelegate.(ReactAccessibilityDelegate.java:184) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.views.slider.ReactSliderManager$ReactSliderAccessibilityDelegate.(ReactSliderManager.java:281) 08-03 14:44:56.318 21206 21360 E AndroidRuntime: at com.facebook.react.views.slider.ReactSliderManager.(ReactSliderManager.java:301) ``` To fix it I changed the delegate creation to be done in `createViewInstance` which will be called on main thread. This is also more in line with how other accessibility delegates are created for other view managers. Since Slider is probably not used a lot, creating more delegate instance won't be an issue. Another alternative could be to initialize a Looper on the thread that creates the react context, but it seems more involved and probably not needed. ## Changelog [Android] [Fixed] - Create slider accessibility delegate in createViewInstance Pull Request resolved: https://github.com/facebook/react-native/pull/31942 Test Plan: Reproduced the crash in an app and made sure this patch fixes it. Reviewed By: JoshuaGross Differential Revision: D30167451 Pulled By: p-sun fbshipit-source-id: 5327130064db52ac0086e1ae5541a1b3e3954f15 * Flush operations queue when animation starts in RCTNativeAnimatedModule Summary: changelog: [internal] If nodesManager has the information if animated node is managed by Fabric, we can't decide if the operation queue should be flushed before it is flushed. Therefore, keep the information about animated nodes inside a set instead of nodesManager. For simplicity, I will refer to class `RCTNativeAnimatedTurboModule` as *NativeAnimated* and to `RCTNativeAnimatedNodesManager` as *NodesManager* Notice that each call to *NativeAnimated* is queued up in `_operations` or `_preOperations`. When the queues are flushed, only then methods are called on `RCTNativeAnimatedNodesManager`. There are two mechanisms that flush operations. One is triggered by `RCTMountingManager` before mounting operations are applied and after they are applied. This works fine but is important to paint the picture. The second mechanism is inside `[RCTNativeAnimatedTurboModule startAnimatingNode]`. It flushes the queues for Fabric nodes only (not sure why Fabric nodes only, I couldn't find any explanation in old diffs). It checks with *NativeAnimated* if a node is managed by Fabric. Keep in mind, *NodesManager* only knows about the nodes when the queues have been flushed. Exampe: JavaScript calls methods on *NativeAnimated*. For example: 1. `createNode` 2. `connectAnimatedNodeToView` 3. `startAnimatingNode`. (here, the queues should be flushed, since we are in Fabric) All of these operations are queued up and for as long as `RCTMountingManager` executes mounting, all proceeds as expected. But if those operations happen after mounting phase, `startAnimatingNode` will not flush the operations queues, because it can't tell if nodeTag is managed by fabric or it isn't. This is because *NodesManager* hasn't been notified about any new nodes. Reviewed By: RSNara Differential Revision: D30099010 fbshipit-source-id: d3fc021dd4346d1cbbda3b49ecd9d982c543e705 * Add Flow libdefs for `global` Summary: Changelog: [Internal] Currently, `global` is typed as `any` and any `global` properties accesses are untyped. This diff add a flow libdefs for the `global` object as a start point. Reviewed By: yungsters Differential Revision: D30000895 fbshipit-source-id: ab6988d01921a3c2a3434b534b2f69083570fb6d * Feat/dynamic color borders (#31140) Summary: Following up my issue https://github.com/facebook/react-native/issues/30377 I decided to have a look myself and contribute. On iOS, border colors using `PlatformColor` or `DynamicColorIOS` do not update on the fly when the system appearance updates. When the component mounts, the color is correct for the current appearance, but a component unmout/remount is required in order to see the color changing after a system appearance change. Fixes https://github.com/facebook/react-native/issues/30377 ## Changelog [Internal] [Added] - Added `PlatformColor` and `DynamicColorIOS` examples to RNTester Pull Request resolved: https://github.com/facebook/react-native/pull/31140 Test Plan: I added 2 border examples, one using `PlatformColor` and the other using `DynamicColorIOS`. I recorded the following before/after videos showing the effect of my changes: https://user-images.githubusercontent.com/4186230/110828711-9c5dd600-8297-11eb-8bc8-bdc9054b6b44.mov https://user-images.githubusercontent.com/4186230/110828800-b4cdf080-8297-11eb-9d23-07f69dc3a702.mov Reviewed By: lunaleaps Differential Revision: D30073335 Pulled By: charlesbdudley fbshipit-source-id: 2990a6ed40dd08fc2b1f20e93d6f21ec3d8980da * Cleanup warnings in the NDK build Summary: This diff is cleaning up some configurations in the `Android.mk` files of the native build. Specifically I simplified some of the rules and removed a duplicate file specification. Changelog: Internal - Cleanup warnings in the NDK build Reviewed By: ShikaSD Differential Revision: D30220715 fbshipit-source-id: a100953fe977879a6d28cb0a2ef4b3358fb7c774 * Back out "Flush operations queue when animation starts in RCTNativeAnimatedModule" Summary: Changelog: [internal] Original commit changeset: d3fc021dd434 Reviewed By: motiz88 Differential Revision: D30223203 fbshipit-source-id: 8edf79e109858855d13a36fabab2bcae36180df2 * Fix Undefined symbol: __swift_FORCE_LOAD_$_swiftFileProvider when building with Xcode 13 Summary: Changelog: Fix Xcode 13 build error in HelloWorld template Error: {F640400959} Fix: Embed `libswiftFileProvider.tbd` in app. Reviewed By: hramos Differential Revision: D30192423 fbshipit-source-id: 59dbde441e61bc6ab870e2324e5202f4772bee8e * introduce RCTPlatformColorUtils Summary: Changelog: [Internal] in this diff, we add the logic to handle converting PlatformColor strings to their corresponding RGBA values, using `UIColor`'s API as the source of truth of these colors. functionality not covered yet: - customColor - iOS Dynamic Colors - Variant Colors Reviewed By: sammy-SC Differential Revision: D30103451 fbshipit-source-id: 7d7be0f08dc2fb95b606b8f5d73784766787a574 * hook up PlatformColorParser to RCTPlatformColorUtils Summary: Changelog: [Internal] in this diff, we iterate through the list of color passed down in the props, and write the RGBA value of the first valid UIColor Reviewed By: sammy-SC Differential Revision: D30110297 fbshipit-source-id: c6730110129d0fe1f784fa89cd26b46d3dda7f28 * replace SharedColor alias with class for more reliable template deduction Summary: Changelog: [Internal] when we try to write a `SharedColor` type prop in the renderer, the template function we match to is the following: https://www.internalfb.com/intern/diffusion/FBS/browsefile/master/xplat/js/react-native-github/ReactCommon/react/renderer/core/propsConversions.h?commit=28dacb972cda702d37dedd4612bc67c212d4d9eb&lines=108-132 this is because `SharedColor` is an alias of `better::optional`. ultimately, this causes a crash in L130 - the template deduction in L130 interprets the T as an `int`, rather than `SharedColor`, but our `rawValue` is pointing to `SharedColor`. there was a number of options i considered, but didn't feel the most correct: - wrapping `SharedColor` in another `better::optional` - this felt like a hack and didn't really provide any real benefits of the `optional` wrapper. - writing a template specialization on SharedColor - this didn't seem future proof because we could introduce another type that could potentially wrap an integer, which doesn't seem impossible in the future - then we would get some conflict with our `SharedColor` conversion, which is custom to the behavior of colors. - coercing the template during the function call - from an engineering perspective, this didn't seem like a great idea since it isn't clear to the engineer that this would be necessary and they would most likely only find out to do this after seeing a crash on their builds. i ultimately decided to convert `SharedColor` to a simple class wrapper, similar to the implementation already used in Android. this alleviates all of the concerns with the other options above. Reviewed By: sammy-SC Differential Revision: D30149880 fbshipit-source-id: 7e8abafcd9fd7465b13ef227d140e859f8df6ecd * Deploy 0.157.0 to xplat Summary: Changelog: [Internal] Reviewed By: gkz Differential Revision: D30148513 fbshipit-source-id: 7eb17353c3620d6f99d547dd6a781ac0a13a9a72 * General Logging Util (stab) class for native errors (#31998) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/31998 Overall Context: We want to add a way to log errors (e.g. mustfix, warn, etc on the server with stack trace) without crashing the app (e.g. react_native_assert crashes the app). This diff: I am writing very simple logger functions which will get resolved at build time depending on the platforms/apps. Changelog: [internal] Reviewed By: JoshuaGross Differential Revision: D30174404 fbshipit-source-id: 2e5bc865dd8576c5a758c56e080a1e582a8c3ada * Documenting UserFlow.endFailure Summary: We had some confusion lately, where errorName was used to dump "error message". This caused problems in Scuba. This doc should add some clarity on what is expected from endFailure users. Changelog: [Internal][Added] - Documentation for method in UserFlow.js class Reviewed By: mityal Differential Revision: D30192127 fbshipit-source-id: d057668aab714a9342131c83daf41cbe9372cb39 * iOS: When RCTSyncImageManager image times out, log warning instead of error Reviewed By: fkgozali Differential Revision: D30255710 fbshipit-source-id: e5238f718420718265823dd0fb93507d472d3cff * Un-deprecate ReactSoftException Summary: After creating and using this utility, we learned that (1) it's really useful, and (2) its interface is good enough. So, let's un-deprecate this utility. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30251651 fbshipit-source-id: d1ecf81484f865587a5552d5ddf0e68da86397d9 * Rename ReactSoftException to ReactSoftExceptionLogger Summary: ReactSoftException makes it seem like the class is an Exception, when it's actually a logger. This rename I think is more appropriate. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30251735 fbshipit-source-id: 550bd543388e698774ec31753200bd3f722d8c17 * Updated TextInput autoCompleteType prop to autoComplete 2/2 (#26010) Summary: Fix for bug https://github.com/facebook/react-native/issues/26003 Rename TextInput prop "autoCompleteType" to "autoComplete". ## Changelog [Android] [Breaking] - Updated `autoCompleteType` prop of `TextInput` to `autoComplete` Pull Request resolved: https://github.com/facebook/react-native/pull/26010 Test Plan: Sandcastle Reviewed By: mdvacca Differential Revision: D29795575 Pulled By: lunaleaps fbshipit-source-id: 6eba7030968e9b7384529a43a6cd1b3c9e8b2a2c * Remove autoCompleteType as a native component prop Summary: Changelog: [Android][Internal] - Cleanup `autoCompleteType` prop from Android native component. Reviewed By: charlesbdudley Differential Revision: D30057497 fbshipit-source-id: c80dd5682b314112ae70551bf8135372bb1ddc8b * Match native*.js and Native*.js srcs Summary: Globbing is case sensitive only when eden is enabled. This causes Android cold builds to regress by 2 minutes because a large number of react native targets have to be built and fetched. This change causes srcs to match with and without eden. Changelog: [Internal] Reviewed By: cute-jumper Differential Revision: D30266076 fbshipit-source-id: 39ac2cbfa146fcdda1d8d3a6f40b0ec41bfb3c2f * Fix TextInput Cursor jumping to the right when the placeholder null (#28995) Summary: This issue fixes https://github.com/facebook/react-native/issues/28794 fixes https://github.com/facebook/react-native/issues/27658 Flow type ?Stringish allows to set the placeholder value to null. The null value causes the cursor to jump to the right in a TextInput. The fix replaces the placeholder null value with an empty string which avoid calling setHint(null) as causes the placeholder to jump to the right. ## Changelog [Android] [Fixed] - avoid calling setHint with a null parameter causing cursor to jump to the right Pull Request resolved: https://github.com/facebook/react-native/pull/28995 Test Plan: **
CLICK TO OPEN TESTS RESULTS (28 May 2020 20a9473aaa330ad9b6e7a0b42ebd9c4ed41ce60b)**

More videos and information included in issue https://github.com/facebook/react-native/issues/28794 The below test cases are from the [following repository](https://github.com/fabriziobertoglio1987/AwesomeProject) | **BEFORE** | |:-------------------------:| | | | **AFTER** | |:-------------------------:| | | Extensive testing on `RNTester` did not identify any regression. | **AFTER** | |:-------------------------:| | |

**
CLICK TO OPEN TESTS RESULTS (15 February 2021 https://github.com/facebook/react-native/pull/28995/commits/20a9473aaa330ad9b6e7a0b42ebd9c4ed41ce60b)**

| **BEFORE** | |:-------------------------:| |

Reviewed By: charlesbdudley Differential Revision: D30095877 Pulled By: lunaleaps fbshipit-source-id: 38a3e788443a22d48a4335063cd4315638bd8e97 * Bump AGP to 4.2.2 Summary: This is just a minor bump in the Android Gradle plugin. Changelog: [Android][Changed] - Bumped AGP to 4.2.2 allow-large-files Reviewed By: ShikaSD Differential Revision: D30220591 fbshipit-source-id: 217a21e4935bcd258ac3bcd45c7fb1ff5c0a1ead * Flatten the `react-native-codegen` included build. (#32007) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32007 This Diff simplifies the codegen Gradle build. Previously the build used to have a 2-level nesting of included build. Turns out that the `react-native-codegen/android/build.gradle` build is just providing a task and including an inner build that contains the codegen Gradle plugin. I've moved such plugin to the outer build. This will also make sure that the Gradle plugin files are properly index by the IDE when opening the build (as nested included build are not yet supported). Changelog: Internal - Flatten the `react-native-codegen` Gradle included build Reviewed By: fkgozali, ShikaSD Differential Revision: D30227784 fbshipit-source-id: af304afeeba1926f8b7b5b47cf69889d3f808f5f * iOS: Log image url in test environment when image times out Reviewed By: fkgozali Differential Revision: D30280757 fbshipit-source-id: 57385d3fd64f564f1de9ad86ffb2c0064e941df9 * Fix BorderExample for DynamicColorIOS Summary: Changelog: [Internal] - Fix border example for RNTester Reviewed By: charlesbdudley Differential Revision: D30262957 fbshipit-source-id: 677e7a9346bc2f1dc67ec7cc9ad7e36af34ffa60 * Add a flag to warn whenever the legacy NativeModule system is used Summary: When true, this flag will cause React Native to start logging soft exceptions, whenever the legacy NativeModule system is used. This flag is independent of useTurboModules. In practice, it's only enabled when TurboModules is enabled. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30250363 fbshipit-source-id: f610567c5b99a4fbf8252c3962908668f483d028 * Log SoftExceptions when the legacy NativeModule system is used Summary: When ReactFeatureFlags.warnOnLegacyNativeModuleSystemUse is true, we will log a SoftException, whenever: 1. A Java/Cxx NativeModule is created by the legacy system. 2. Any method on the Java NativeModule is executed, including getConstants(). NOTE: Logs to CXXModule use incoming. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30252953 fbshipit-source-id: 570929624d0114bb298c593ba909e5cdbd54bd6c * Introduce JReactSoftExceptionLogger to log SoftExceptions from C++ Summary: When the TurboModule system is enabled, C++ NativeModules shouldn't be used in production. We'll use this JReactSoftExceptionLogger to log soft exceptions from C++ NativeModules this scenario. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D30272694 fbshipit-source-id: 8dadcfe51bcbc353d438d1a403e74da5e2cb9546 * Warn whenever CxxNativeModules are used Summary: After this diff, when ReactFeatureFlags.warnOnLegacyNativeModuleSystemUse is enabled, the legacy NativeModule infra will log soft exceptions whenever legacy NativeModules are accessed/used. Changelog: [Internal] Reviewed By: p-sun Differential Revision: D30272695 fbshipit-source-id: 7111402c1d8b883a600dcb4559e9ff1d56447070 * Fix typo in RCTConvert.m (#31067) Summary: seperated -> separated ## Changelog [Internal] [Fixed] - Fixed typo in comment Pull Request resolved: https://github.com/facebook/react-native/pull/31067 Test Plan: NONE Reviewed By: sammy-SC Differential Revision: D30176244 Pulled By: sota000 fbshipit-source-id: 617607aaa7eb5f613344773c4bbbc09a8c5096c1 * Allow Modal to handle hardware escape key in the same way the back button is handled (#31564) Summary: On Android, when a hardware keyboard is connected pressing the escape key will partially dismiss an active `` without calling the `onRequestClose` callback. The modal will disappear, but I beleive the underlying activity may still be present, blocking interaction with the main app below and leaving things in a partially broken state. This code change allows the escape key to be handled in the same way as the hardware back button, calling the `onRequestClose` and allowing the developer to decide the behaviour. This issue isn't present on iOS, so no change is required there. ## Changelog [Android] [Fixed] - Fix Modal being dismissed incorrectly when pressing escape on a hardware keyboard Pull Request resolved: https://github.com/facebook/react-native/pull/31564 Test Plan: I've tested this manually locally, but unsure if it's possible to test in an automated way as the emulator didn't respond to a hardware escape key in the same way as a physical device. Reviewed By: ShikaSD Differential Revision: D28953718 Pulled By: lunaleaps fbshipit-source-id: 5547bc5d894da0d3d9daf4515b1af9c2407815db * Nullable ReconnectingWebSocket params Summary: Changelog: [Internal] - Annotated the MessageCallback and ConnectionCallback params of the ReconnectingWebSocket with Nullable Reviewed By: makovkastar Differential Revision: D30298832 fbshipit-source-id: 4e0a6ea339d1d8b25fb7bb24dfbada93d5cebc96 * Clean up unbatched only experiment Summary: changelog: [internal] The experiment isn't shipping. Reviewed By: JoshuaGross Differential Revision: D30303379 fbshipit-source-id: 80b89d3738c1640f6abefcad161f95397c88ee04 * Clean up AsyncEventBeatV2 experiment Summary: changelog: [internal] This experiment is abandoned. It regressed engagement metrics. Reviewed By: JoshuaGross Differential Revision: D30303383 fbshipit-source-id: 1d86eb5c7c257d4b369632007d0bda23e80c88ab * Back out "Fix Undefined symbol: __swift_FORCE_LOAD_$_swiftFileProvider when building with Xcode 13" Summary: Changelog: Backout "Fix Xcode 13 build error in HelloWorld template" Original commit changeset: 59dbde441e61 This change breaks the template for Xcode 12.5: {F642871165} Reviewed By: philIip Differential Revision: D30301800 fbshipit-source-id: 4fcd9a5413dafb2cedb2194d5b68ddfd46edd974 * Include Swift lib in LIBRARY_SEARCH_PATHS Summary: changelog: Fix Xcode 13 build error in HelloWorld template Including `usr/lib/swift` fixes error: {F642876047} Reviewed By: p-sun Differential Revision: D30301799 fbshipit-source-id: b93eb51ec5dd929ddc46574fc11bc89934eadeaf * fix#29319 - ios dismiss modal (#31500) Summary: This PR aims to resolve iOS can't dismiss Modal on swipe gesture. https://github.com/facebook/react-native/issues/29319 When modal presentationStyle is pageSheet, iOS allows to dismiss the modal using swipe gesture. This PR adds support for that feature ## Changelog [iOS] [Added] - Support for onRequestClose for iOS Modal component. Pull Request resolved: https://github.com/facebook/react-native/pull/31500 Test Plan: - If onRequestClose updates the visibility state, modal will be closed. ``` ``` https://user-images.githubusercontent.com/23293248/117590263-36cd7f00-b14c-11eb-940c-86e700c0b8e7.mov ## Notes - In this PR, only support for partial drag is added. i.e. user can't drag the modal up and down completely. I added full user dragging but reverted in this [commit](https://github.com/facebook/react-native/commit/bb65b9a60d54b61652d608661eba876b49be3b17) to support controllable onRequestClose. If someone has any suggestion to have full draggable support + controllable onRequestClose, please let me know. Reviewed By: p-sun Differential Revision: D30041625 Pulled By: sammy-SC fbshipit-source-id: 9675da760bd5c070c4f0e1d30271c8af5c50b998 * Fix selectionColor doesn't style Android TextInput selection handles (#31007) Summary: This issue fixes https://github.com/facebook/react-native/issues/30283 selectionColor does not change the handles color. The method setCursorColor changes the cursor color of field `mCursorDrawable` using a reflection for Android Devices lower then API 28. This fix adds a reflection to change color of the left, center and right handles of a selection (mTextSelectHandleLeftRes, mTextSelectHandleRes and mTextSelectHandleRightRes). ## Changelog [Android] [Fixed] - Fix selectionColor doesn't style Android TextInput selection handles Pull Request resolved: https://github.com/facebook/react-native/pull/31007 Test Plan: This changes fix the Java API for which I can not write Java tests as explained in commit https://github.com/facebook/react-native/commit/709a441ecf54cd9465f5946af0454ee7d10d5cbe The java TextInputTest was excluded from the test suite in commit https://github.com/facebook/react-native/commit/709a441ecf54cd9465f5946af0454ee7d10d5cbe as they need the Yoga libraries to run **
CLICK TO OPEN TESTS RESULTS - API 22**

left/right handles do not change color with the cursor | **BEFORE** | |:-------------------------:| | | center Handle color does not change color | **BEFORE** | |:-------------------------:| | | The left and right handle change color with the cursor color | **AFTER** | |:-------------------------:| | | The center handle color is correctly updated | **AFTER** | |:-------------------------:| | | `setCursorColor` changes correctly the cursor color | **AFTER** | |:-------------------------:| | | Default Colors do not have issues | **AFTER** | |:-------------------------:| | | | **AFTER** | |:-------------------------:| | |

Reviewed By: ShikaSD Differential Revision: D28682935 Pulled By: sota000 fbshipit-source-id: ff037c93f36bbf20c915373b995bbfd8e8ca92d0 * Fixing CI error "Entry file RNTester/js/RNTesterApp.ios.js does not exist" (#29263) Summary: PRs are failing with the error "Entry file RNTester/js/RNTesterApp.ios.js does not exist", despite it existing. The if statement around the checker will always trigger because when it looks to see if RNTester/js/RNTesterApp.ios.js exists it's inside of RNTester instead of root. I've added a "../" to solve this. ## Changelog [Internal] [Fixed] - Fixing CI error "Entry file RNTester/js/RNTesterApp.ios.js does not exist" Pull Request resolved: https://github.com/facebook/react-native/pull/29263 Test Plan: ![Screen Shot 2020-07-01 at 11 25 03](https://user-images.githubusercontent.com/65255457/86278790-cc43ce00-bb8d-11ea-8098-9f4a751667ae.png) ![Screen Shot 2020-07-01 at 11 26 52](https://user-images.githubusercontent.com/65255457/86278796-ccdc6480-bb8d-11ea-9d73-63801f77e840.png) Reviewed By: sammy-SC Differential Revision: D30176138 Pulled By: sota000 fbshipit-source-id: 41510b31d3f1a34de7b0b5218ab670ac99409622 * Fix dashed/dotted border drawing when border-radius is 0 (#28359) Summary: This PR fixes the border-style that is not respected when drawing a border with 0 border-radius on Android. This would cause the faster `drawRectangularBackgroundWithBorders` path to be used, but that uses rectangular drawing and doesn't support dashed/dotted stroke patterns. This PR changes the behavior to use the generic `drawRoundedBackgroundWithBorders` code-path which does support dashed/dotted border-styles. ## Changelog `[Android] [Fixed] - Fix dashed/dotted border-drawing when border-radius is 0` Pull Request resolved: https://github.com/facebook/react-native/pull/28359 Test Plan: **Faulty situation:** ![Screenshot_1584721992](https://user-images.githubusercontent.com/6184593/77184987-e838cd80-6ad0-11ea-9585-058eafbd361a.png) **After the fix:** ![Screenshot_1584721410](https://user-images.githubusercontent.com/6184593/77184801-9d1eba80-6ad0-11ea-92a7-7212f40ace73.png) Reviewed By: lunaleaps Differential Revision: D20590739 Pulled By: charlesbdudley fbshipit-source-id: 18657ea21e54f763e22c623bf979b3500c1bdcbd * Add a way to bind log function to the unified react native logger. Summary: In this diff: 1. Convert the ReactNativeLogger to c function for the future compatibility. 2. Bind the log function from Catalyst app 3. Update the call site Changelog: [internal] Reviewed By: JoshuaGross Differential Revision: D30271863 fbshipit-source-id: 4c0ea704cf19f53468a3b72631353959ea999884 * React Native sync for revisions 19092ac...5634ed1 Summary: This sync includes the following changes: - **[424fe5870](https://github.com/facebook/react/commit/424fe5870 )**: Revert "Show a soft error when a text string or number is supplied as a child to non text wrappers ([#21953](https://github.com/facebook/react/pull/21953))" ([#22108](https://github.com/facebook/react/pull/22108)) //// - **[aebf3b456](https://github.com/facebook/react/commit/aebf3b456 )**: [Scheduler] Check for continuous input events ([#22107](https://github.com/facebook/react/pull/22107)) //// - **[e9b2028b3](https://github.com/facebook/react/commit/e9b2028b3 )**: Show a soft error when a text string or number is supplied as a child to non text wrappers ([#21953](https://github.com/facebook/react/pull/21953)) //// - **[ecd73e17b](https://github.com/facebook/react/commit/ecd73e17b )**: Enable enableSuspenseLayoutEffectSemantics flag statically for Facebook ([#22050](https://github.com/facebook/react/pull/22050)) //// - **[a8725a3e6](https://github.com/facebook/react/commit/a8725a3e6 )**: Scheduling profiler: Added lane labels and durations to React measures ([#22029](https://github.com/facebook/react/pull/22029)) //// Changelog: [General][Changed] - React Native sync for revisions 19092ac...5634ed1 jest_e2e[run_all_tests] Reviewed By: kacieb Differential Revision: D30225923 fbshipit-source-id: 562895d3e0d264f40770dadb89d4a16241967c4c * Exclude nativeImageSource.js instead of matching [Nn] Summary: The change to this glob by D30266076 (https://github.com/facebook/react-native/commit/f1b4748a7c649ddff1739e4be57a1d4d89f1db56) lines up suspiciously to a non-reproducible failure in the sources to the rules that use this glob. Changing to see if it mitigates the issue. See https://fb.workplace.com/groups/askbuck/posts/6473961645985729/?comment_id=6476777799037447&reply_comment_id=6477737555608138 Changelog: [Internal] Reviewed By: yungsters Differential Revision: D30361375 fbshipit-source-id: af7b7fe553364fc1d7012bea8d00bf02ee2804fa * Revert D20590739 Summary: This diff is reverting D20590739 (https://github.com/facebook/react-native/commit/3e5998e651eba840603dcb1a9c0be564fc3f868d) D20590739 (https://github.com/facebook/react-native/commit/3e5998e651eba840603dcb1a9c0be564fc3f868d) is making the following tests to fail and this revert diff is either the revert of the blame diff or the revert of the stack of diffs that need to be reverted to revert the blame diff Tests affected: - https://www.internalfb.com/intern/test/281475012591721/ Multisect link: https://www.internalfb.com/intern/testinfra/multisect/476214 ## Changelog `[Android] [Fixed] - Revert: Fix dashed/dotted border-drawing when border-radius is 0` Reviewed By: charlesbdudley Differential Revision: D30361262 fbshipit-source-id: 21dd507deb5817dda1063a267a38749c77e7ae1a * Fix irregular indent in template (#29871) Summary: Fix irregular indent in template/android/app/build.gradle ![image](https://user-images.githubusercontent.com/26166657/92319046-46417900-f04f-11ea-9051-cb4d7bcc3049.png) ## Changelog [Internal] [Fixed] - Fix irregular indent in template Pull Request resolved: https://github.com/facebook/react-native/pull/29871 Test Plan: N/A Reviewed By: passy, cortinico Differential Revision: D30360839 Pulled By: sota000 fbshipit-source-id: 7a92890007716c6e244ceffaa697cdd5ad1a0504 * JS: Fix "Modal | Basic" Test's Layout Summary: Fix the CSS on the main Modal test Move the warning message for the "Transparent" switch to below the switch, since warnings messages are usually under the field they're warning. Move Presentation Style to be before Transparent, since Transparent is a modifier of "overFullScreen" Presentation Style. Reviewed By: lunaleaps Differential Revision: D30323087 fbshipit-source-id: b13d6c958145096da95c9888181ff457b093fb49 * replace testing-support-lib with androidx buck targets in RN Summary: Changelog: [Internal] - codemod testing library Buck redirect to actual dependency Reviewed By: jiawei-lyu Differential Revision: D30379180 fbshipit-source-id: eb9a22569230d07732bd0aa63dddfcfff7c3800f * `Android/ColorProps`: ColorProps with value null should be defaultColor instead of transparent (#29830) Summary: This pr: - Fixes: https://github.com/facebook/react-native/issues/30183 - Fixes: https://github.com/facebook/react-native/issues/30056 - Fixes: https://github.com/facebook/react-native/issues/29950 - Fixes: https://github.com/facebook/react-native/issues/29717 - Fixes: https://github.com/facebook/react-native/issues/29495 - Fixes: https://github.com/facebook/react-native/issues/29412 - Fixes: https://github.com/facebook/react-native/issues/29378 Because most of ReactProps(name = ViewProps.COLOR) accept @ Nullable Integer. For example: https://github.com/facebook/react-native/blob/abb6433f506851430dffb66f0dd34c1e70a223fe/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java#L472-L479 After update to react-native 0.63.2 to make PlatformColor work, there is a new ColorPropSetter. https://github.com/facebook/react-native/blob/abb6433f506851430dffb66f0dd34c1e70a223fe/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java#L194-L215 But ColorPropSetter won't return an nullable value with getValueOrDefault, it will always return it's defaultValue which is 0. And 0 is equal to TRANSPARENT, will cause disappear. ## Changelog [Android] [Fixed] - ColorProps with value null should be defaultColor instead of transparent Pull Request resolved: https://github.com/facebook/react-native/pull/29830 Test Plan: Please initiated a new project and replaced the app with the following code: ``` import * as React from 'react'; import {Text, View, TouchableOpacity, PlatformColor} from 'react-native'; export default function App() { const [active, setActive] = React.useState(false); return ( Example Example2 setActive(!active)}> Toggle Active ); } ``` Thanks you so much for your code review! Reviewed By: JoshuaGross Differential Revision: D30209262 Pulled By: lunaleaps fbshipit-source-id: bc223f84a92f742266cb7b40eb26722551940d76 * Fix Dimensions not updating on Android (#31973) Summary: When retrieving the device dimensions through the JS `Dimensions` utility, the result of `Dimensions.get` can be incorrect on Android. ### Related issues - https://github.com/facebook/react-native/issues/29105 - https://github.com/facebook/react-native/issues/29451 - https://github.com/facebook/react-native/issues/29323 The issue is caused by the Android `DeviceInfoModule` that provides initial screen dimensions and then subsequently updates those by emitting `didUpdateDimensions` events. The assumption in that implementation is that the initial display metrics will not have changed prior to the first check for updated metrics. However that is not the case as the device may be rotated (as shown in the attached video). The solution in this PR is to keep track of the initial dimensions for comparison at the first check for updated metrics. ## Changelog [Android] [Fixed] - Fix Dimensions not updating Pull Request resolved: https://github.com/facebook/react-native/pull/31973 Test Plan: ### Steps to reproduce 1. Install the RNTester app on Android from the `main` branch. 2. Set the device auto-rotation to ON 3. Start the RNTester app 4. While the app is loading, rotate the device 5. Navigate to the `Dimensions` screen 6. Either a. Observe the screen width and height are reversed, or b. Quit the app and return to step 3. ### Verifying the fix #### Manually Using the above steps, the issue should no longer be reproducible. #### Automatically See unit tests in `ReactAndroid/src/test/java/com/facebook/react/modules/deviceinfo/DeviceInfoModuleTest.java` ### Video https://user-images.githubusercontent.com/4940864/128485453-2ae04724-4ac5-4267-a59a-140cc3af626b.mp4 Reviewed By: JoshuaGross Differential Revision: D30319919 Pulled By: lunaleaps fbshipit-source-id: 52a2faeafc522b1c2a196ca40357027eafa1a84b * refactor: remove DefaultProps from the StatusBar Component (#31631) Summary: Issue https://github.com/facebook/react-native/issues/31607. defaultProps makes it difficult to migrate components to functional. ## Changelog [General] [Changed] - Remove defaultProps from the StatusBar Component. Pull Request resolved: https://github.com/facebook/react-native/pull/31631 Test Plan: Verified the behaviour of the existing functionality after the removal on the RN Tester app. https://user-images.githubusercontent.com/11355609/120085709-a2b35f80-c0da-11eb-94f2-2649270155ef.mov Reviewed By: sota000 Differential Revision: D30259324 Pulled By: lunaleaps fbshipit-source-id: 0c8841691198761589fdd029cab36629f7dfa757 * fix AGP 7 compatibility (#32030) Summary: Android Gradle Plugin 7 removed dependency configurations, and it includes compile. Below is a snipped from release notes https://developer.android.com/studio/releases/gradle-plugin I can confirm that RN 0.65.0 app is running as expected on Android with the patch. > **compile** Depending on use case, this has been replaced by api or implementation. Also applies to *Compile variants, for example: debugCompile. ## Changelog [Android] [Changed] - Android Gradle Plugin 7 compatibility Pull Request resolved: https://github.com/facebook/react-native/pull/32030 Test Plan: Create a project with RN 0.65.0 and upgrade Android Gradle Plugin to 7.0.0, and Gradle to 7.0.2. It'll fail to sync. Then apply the change, and it'll sync as normal, and build the app. Reviewed By: passy, ShikaSD Differential Revision: D30394238 Pulled By: cortinico fbshipit-source-id: cabc25754b9cd176a7d6c119d009728f2e5a93d9 * Clean up Fabric startSurface API used in Venice Summary: Update FabricUIManager methods for `SurfaceHandler` to start usual rendering or prerendering based on presence of the view instead of using two methods with same logic. Changelog: [Internal] Reviewed By: sshic Differential Revision: D30346502 fbshipit-source-id: 297f2b4a16dc7af7c36379252bd73e6dc953ff59 * Expose "unreserved" trait constants that can be mapped per-component Summary: Fabric core uses a lot of traits - I am reserving a few more for core usage, and also exposing a few "unreserved" traits. It is recommended that all custom components that do use traits rely on these constants instead of hard-coding any trait values. That way, in the unlikely event that these values change in the future, it will not break components. Changelog: [Internal] Reviewed By: cortinico, RSNara Differential Revision: D30401743 fbshipit-source-id: fb2e8f5cf33c94e31a0c25a89055acfc4eccf066 * Call super.onActivityResult in ReactActivity Summary: This change allows native activities and fragments to also handle onActivityResult callbacks, in addition to sending the result to React Native. Changelog: [Android][Changed] - Call super.onActivityResult in ReactActivity's onActivityResult() Reviewed By: JoshuaGross Differential Revision: D30232449 fbshipit-source-id: cb080d6f2eff57dcf839660ee715cb4068ffcdd5 * Move react_native_log out of utils (#32042) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32042 This diff moves react_native_log out of utils to make it easier/possible to import from modules. Changelog: [internal] Reviewed By: JoshuaGross Differential Revision: D30411247 fbshipit-source-id: 5482761b259600df051a88c6eff1834c882e7230 * fix: Resolve NODE_BINARY *after* finding the path to node (#32029) Summary: We want to resolve `NODE_BINARY` **after** `find-node.sh` runs and sets up any node version manager that we need to setup, otherwise `NODE_BINARY` is always undefined. ## Changelog [Internal] [Fixed] - Resolve NODE_BINARY after finding the right path to node Pull Request resolved: https://github.com/facebook/react-native/pull/32029 Reviewed By: TheSavior Differential Revision: D30401213 Pulled By: yungsters fbshipit-source-id: 386ffeff15b5f371a452488ed078d3adebe0f211 * Ship "Disable 'virtual view' preallocation" experiment in code Summary: The impact of this has proven impressive, and safe. Ship in code and remove feature-flag. Changelog: [Internal] Reviewed By: philIip Differential Revision: D30269561 fbshipit-source-id: 9bb72567cfd881928d14d9bee43cf32b390664fb * Emit soft error for warning Summary: This diff adds a default behavior for the unified logger on Android. Added the call site in the CXXNativeModule. Changelog: [internal] Reviewed By: JoshuaGross Differential Revision: D30377767 fbshipit-source-id: 000014828f2f245dc9492e3617218895d9a33536 * Enable ktfmt Summary: Changelog: [internal] Reviewed By: zertosh Differential Revision: D30423755 fbshipit-source-id: 8ae27b3666214f5144ef8b5ef7fe868afc19b4b9 * Pass configFile: false to Babel parser Summary: Changelog: [Internal] Disables implicit `babel.config.js` lookup in a `parse()` call that does not need any user-specified config. Reviewed By: javache Differential Revision: D30396331 fbshipit-source-id: 9b07c361eae53cdffc6a76ba30f1146a7af65a10 * Passing the scheme field throughout all the metro connection pipeline to allow different scheme other than the default hardcoded http Reviewed By: lunaleaps Differential Revision: D30218490 fbshipit-source-id: 3832c731156a4f88ad1c55be0a0e4f68fa3e1d48 * Adding activity check to enable Dev mode Summary: It is assumed that there will always be an activity associated on enabling the dev support which is not the case. Hence adding that null check. Changelog: [Android][Fixed] - Added null check for activity in onHostResume() Reviewed By: javache Differential Revision: D30411311 fbshipit-source-id: 8936be2df7f16c355693163347d5e1d94c5ce2e1 * Deploy 0.158.0 to xplat Summary: Changelog: [Internal] Reviewed By: dsainati1 Differential Revision: D30426571 fbshipit-source-id: 70689323d066e3b25bf720f454d2146d195df8b3 * - Fix broken Circle CI due to missing BUCK rule for androidx:tests (#32052) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32052 Changelog: Update the OSS React Native dependencies to match the internal dependency structure. Reviewed By: cortinico Differential Revision: D30397818 fbshipit-source-id: a70e26d764729f6ead9eb6a4d689e32d25243571 * Remove BUILD FILE SYNTAX from build files Summary: Changelog: [Internal] Reviewed By: zertosh Differential Revision: D30410441 fbshipit-source-id: 62deebb502121f23270bfa18286b155ad161af2d * Apply new buildifier fixes Summary: Changelog: [Internal] Reviewed By: zertosh Differential Revision: D30407205 fbshipit-source-id: 022a02829d59a900764b228afb9856ed1ba2cf8c * Remove redundant includes Summary: changelog: internal Removing unused headers. Fewer headers = faster compilation Reviewed By: p-sun Differential Revision: D30398600 fbshipit-source-id: a64801e49d283ad1e2d0cb9c9d688445e30bf0ed * Provide logger to YGConfig Summary: Changelog: [internal] Logger needs to be supplied to YGConfig, otherwise the app crashes when Yoga tries to log. Reviewed By: fkgozali Differential Revision: D30394676 fbshipit-source-id: bda464a4e43cb815c00650e1fedf43fe0a06f973 * Set initial maximum surface size to viewport size Summary: Changelog: [internal] There is a possibility of race between JavaScript sending "completeRoot" and maximum size set on surface. To prevent this race, we set the initial maximum size to be equal to the viewport size. Alternative solution is to set maximumSize to {0, 0} initially instead of infinity. This is what old architecture does, even though not explicitly. Reviewed By: fkgozali Differential Revision: D30402207 fbshipit-source-id: 44427404eaf060a81de257797823edf971ffc1bb * iOS: Don't display LogBox in Dev if Bridge was invalided Summary: Bridge can get invalidated during tear down. If a JS error is thrown then, don't display a LogBox so we don't hit the invalid bridge assert in RCTSurface. Reviewed By: fkgozali Differential Revision: D30464848 fbshipit-source-id: 87a8daa95fd06342d194a4805ecfa97279820f2e * Update ImageBackground.js (#32055) Summary: Currently ImageBackGround component has optional style props, but if you don't pass it as prop, it still "thinks" you pass style and crushes. In this pr, I made width and height inside component to be optional so it won't crush. ## Changelog [General] [Fix] - Changed ImageBackground's style so it won't crush. [Screen Shot 2021-08-20 at 15 05 45](https://user-images.githubusercontent.com/62840630/130230568-be02b1a2-52ec-4f9d-b3d3-212552d3882b.png) As you can see in this component, I tried to use ImageBackground without any style props, and my app crushes. Then I added style with empty object and the app didn't crush anymore, as you can see here: ![Screen Shot 2021-08-20 at 15 09 23](https://user-images.githubusercontent.com/62840630/130230932-a576c397-a910-4e40-a202-56482d83dd9c.png). In conclusion, if we make width and height styles optionals inside ImageBackground component, it won't crush anymore. Thoughts: Maybe consider to make style props for this component none-optional because it isn't make any sense that image won't have any style at all. Thanks ahead, that was my first pr, Eden Binyamin. Pull Request resolved: https://github.com/facebook/react-native/pull/32055 Reviewed By: charlesbdudley Differential Revision: D30452297 Pulled By: sshic fbshipit-source-id: b7071aa457dba443ed2f627c2458ea84fd24b36d * Fix typo and grammar (#31916) Summary: > Always leave the campground cleaner than you found it. Fixing: * typo in _dismissed_ * make the subject agree with the verb ## Changelog [Internal] [Fixed] - A typo in a comment Pull Request resolved: https://github.com/facebook/react-native/pull/31916 Test Plan: Grammarly says it's better now. Reviewed By: lunaleaps Differential Revision: D29967403 Pulled By: yungsters fbshipit-source-id: 6cb33328e99e3fceba5f19f4baaa9446340fbbcc * Added Selection prop to TextInputProps Summary: Changelog: [iOS][Added] 1. Added new primitive type "Selection" to C++ 2. Added property "selection" to TextInputProps 3. Added parser for that Reviewed By: sammy-SC Differential Revision: D30043256 fbshipit-source-id: eefa67ca23759761901cba1d2ab3052877a153a7 * Selection prop is applied for TextInput when component is mounting Summary: Changelog: [Internal] TextInput's predefined "selection" prop is now applied when view did move to window, and when attributed string is set. Reviewed By: sammy-SC Differential Revision: D30045271 fbshipit-source-id: e5495171b07a25e1e822421ff1627a8686cd0904 * use correct gradle packageTask and asserts dir for android libraries (#32026) Summary: Fixes https://github.com/facebook/react-native/issues/29577 and https://github.com/react-native-community/upgrade-support/issues/93, when building an android library the package task has a different name, which was not handled correctly in the react.gradle file. The fix uses the existing `packageTask` variable which is correctly set for applications and libraries. This PR also copies the bundled js file into the correct assets directory, which is different from the assets directory of applications. ## Changelog [Android] [Fixed] - Fixed Android library builds with react.gradle file Pull Request resolved: https://github.com/facebook/react-native/pull/32026 Test Plan: Tested with my android library build which includes the `react.gradle` file and the build succeeded. Reviewed By: sshic, ShikaSD Differential Revision: D30368771 Pulled By: cortinico fbshipit-source-id: 8f0df8c4d0fa38d85f7c0b9af56d88799571191d * Codegen: Add codegen.js wrapper around generate-specs.sh Summary: Adds a simple wrapper around the generate-specs.sh bash script. Supports optional flags. Usage: `node ./codegen.js --srcs ./js --modules_library_name FBReactNativeSpec` Remove unused `USE_FABRIC` envvar code from `generate-specs.sh`. Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D30439132 fbshipit-source-id: 07099c1d899606ac2e679fac6d32ea2fa4af40fc * Add Flow libdefs for HermesInternalType Summary: Changelog: [Internal] This diff add a flow libdefs for the `HermesInternalType` to type `HermesInternal` as the first accurately typed `global` property, and filled all the type holes. Reviewed By: yungsters Differential Revision: D29986749 fbshipit-source-id: a94be7919f989b5085f6b264e55145a85020fea9 * Add support for the UIAccessibilityTraitsTabBar Summary: Changelog: Add the capability to set tabbar accessibilityRole which maps to the iOS's UIAccessibilityTraitsTabBar Reviewed By: yungsters Differential Revision: D30490752 fbshipit-source-id: f7561a8932306e133d2f65a5ab40ba0be3899ec3 * Add support for AccessibilityValue Summary: Changelog: [Fabric][iOS] Add support for AccessibilityState Specification: https://reactnative.dev/docs/accessibility#accessibilityvalue Reviewed By: sammy-SC Differential Revision: D30452786 fbshipit-source-id: 0d459d3a7b9c037bd1877e5c7ead40bbb42830c3 * fix typos in comments (#32061) Summary: Fixed some typos in the code comments. ## Changelog [Internal] [Fixed] - Fixed typo in the comments Pull Request resolved: https://github.com/facebook/react-native/pull/32061 Test Plan: N/A Reviewed By: javache Differential Revision: D30482511 Pulled By: cortinico fbshipit-source-id: ff67bc00d57972df88e41ee7a933259673de3aa2 * Add window to jest setup (#28067) Summary: `window` exists in the React Native runtime, but not inside the test environment. Many libraries use `typeof window === 'undefined'` to check if code is running in SSR. Because of the difference in the real environment and test environment, tests can behave different than the real app, which is an unwanted behavior. ## Background I'm using https://github.com/tannerlinsley/react-query in my React Native Project, which works really well. When writing tests, they wouldn't work: jest started and then seemingly did nothing. While debugging I noticed the render was stuck in an infinite loop. Then I noticed the following line inside `react-query`: ```js const isServer = typeof window === 'undefined' ``` I didn't know that the React Native runtime has a global `window`, and thought it's a bug inside react-query. But it does have a `window`, which is not defined inside the test environment. The infinite loop was caused by react-query thinking it is running on the server, which doesn't fetch any data. If the react-query hook mounts, it re-executes because then it should be mounted inside the client. But `isServer` was still `true`. This repeats forever. ## Changelog [General] [Fixed] - Fix `window` not existing in jest setup Pull Request resolved: https://github.com/facebook/react-native/pull/28067 Test Plan: Are there tests to check if the test environment is setup correctly? � Reviewed By: yungsters Differential Revision: D30317021 Pulled By: charlesbdudley fbshipit-source-id: 837ed952833ef8e70c5132c9b4152b0e0f28b4dd * React Native sync for revisions 424fe58...bd5bf55 Summary: Post: https://fb.workplace.com/groups/rnsyncsquad/permalink/879923262900946/ This sync includes the following changes: - **[fc3b6a411](https://github.com/facebook/react/commit/fc3b6a411 )**: Fix a few typos ([#22154](https://github.com/facebook/react/pull/22154)) //// - **[986d0e61d](https://github.com/facebook/react/commit/986d0e61d )**: [Scheduler] Add tests for isInputPending ([#22140](https://github.com/facebook/react/pull/22140)) //// - **[d54be90be](https://github.com/facebook/react/commit/d54be90be )**: Set up test infra for dynamic Scheduler flags ([#22139](https://github.com/facebook/react/pull/22139)) //// - **[7ed0706d7](https://github.com/facebook/react/commit/7ed0706d7 )**: Remove the warning for setState on unmounted components ([#22114](https://github.com/facebook/react/pull/22114)) //// - **[9eb2aaaf8](https://github.com/facebook/react/commit/9eb2aaaf8 )**: Fixed ReactSharedInternals export in UMD bundle ([#22117](https://github.com/facebook/react/pull/22117)) //// - **[bd255700d](https://github.com/facebook/react/commit/bd255700d )**: Show a soft error when a text string or number is supplied as a child to non text wrappers ([#22109](https://github.com/facebook/react/pull/22109)) //// Changelog: [General][Changed] - React Native sync for revisions 424fe58...bd5bf55 jest_e2e[run_all_tests] Reviewed By: yungsters Differential Revision: D30485521 fbshipit-source-id: c5b92356e9e666eae94536ed31b8de43536419f8 * Remove usages of `dynamic_casts` that are used inside assertions Summary: This diff is part of a bigger effort to remove the RTTI flags. To do so we need to remove occurrences of `dynamic_cast` and other functions that rely on runtime type informations. Changelog: [Internal][Changed] - Removed extra asserts relying on dynamic_cast Reviewed By: JoshuaGross Differential Revision: D30483554 fbshipit-source-id: 92b31281841a92c7b43e918938248431265dd654 * Fix broken CI with a run of prettier Summary: This Diff is fixing a broken CircleCI on OSS due to not properly formatted .js files. See https://app.circleci.com/pipelines/github/facebook/react-native/10040/workflows/923cb408-b09c-4425-87c1-2677a7af9681/jobs/213822 The offending diff was D29986749 (https://github.com/facebook/react-native/commit/ff4b33672a6a27d2ed68ae6602e9d29d9b7c3eb1) Changelog: [Internal] - Fix broken CI due to not formatted js files Reviewed By: ShikaSD Differential Revision: D30515439 fbshipit-source-id: 560de04347a8746065981b534ed96f0956d94b9c * Fixed dynamic behavior of on Android (#31538) Summary: This PR fixes https://github.com/facebook/react-native/issues/30717, a bug in `` implementation that prevents it from adjusting text size dynamically on Android. The way `adjustsFontSizeToFit` was implemented in https://github.com/facebook/react-native/issues/26389 (and the design of ReactTextShadowNode) implies that Yoga will call `onMeasure` on every size change of a `` component, which is actually not the case (Yoga can cache the results of the measures, call the function multiple times or do not call at all inferring the size from the size constraints). The implementation of `adjustsFontSizeToFit` computes the adjusted string inside the measure function and then eventually passes that to the view layer where it's being rendered. The proper fix of this issue requires the full redesign of the measure and rendering pipelines and separating them, and that... would be too invasive. And, I believe, this issue is already fixed in Fabric where this part is already designed this way. Instead, this diff implements a small workaround: if `adjustsFontSizeToFit` is enabled, we manually dirty the Yoga node and mark the shadow node updated to force remeasuring. ## Changelog [Android] [Fixed] - Fixed dynamic behavior of on Android Pull Request resolved: https://github.com/facebook/react-native/pull/31538 Test Plan: https://user-images.githubusercontent.com/22032/118508162-8c79cc80-b6f4-11eb-853f-a1a09f82935f.mov Reviewed By: mdvacca Differential Revision: D28631465 Pulled By: yungsters fbshipit-source-id: 7db1d22e2a5a464c7bf941d1d3df8e3fe8df66a2 * Bump @react-native/polyfills version (#32074) Summary: https://github.com/facebook/react-native/commit/8a62583f794875e6dc5d1e4a24889b3b702d9f86 did some renaming inside of the react-native/polyfills project, with the jest preset updated to use the new name. The new package for polyfills has not yet been published, so the jest preset in the main branch will be looking for the new name, while the old name is provided by the currently published react-native/polyfills@1.0.0. This is not hit inside the repo, since the dependency is linked instead of using the published one. Bump react-native/polyfills to 2.0 (breaking change), in preparation for publish. ## Changelog [Internal][Fixed] - Bump react-native/polyfills version Pull Request resolved: https://github.com/facebook/react-native/pull/32074 Reviewed By: lunaleaps, cortinico Differential Revision: D30498104 Pulled By: yungsters fbshipit-source-id: 92dcb159d76bd74cd93cfa09e2155c9c1b2c0a86 * Include Swift lib in LIBRARY_SEARCH_PATHS Summary: changelog: Fix Xcode 13 build error in RNTester Including `usr/lib/swift` fixes error: {F642876047} Reviewed By: fkgozali Differential Revision: D30559838 fbshipit-source-id: 65aad16b550d156c8670eaefcc8bedae99606329 * chore: prefer the local react-native-codegen package (#32096) Summary: Currently, the build breaks if we move `react-native-codegen` from the template's dependencies to root. This is due to `scripts/generate-specs-cli.js` using the one installed under `node_modules` instead of the local one. ## Changelog [Internal] [Fixed] - `scripts/generate-specs-cli.js` should prefer the local `react-native-codegen` package Pull Request resolved: https://github.com/facebook/react-native/pull/32096 Test Plan: 1. Make the following changes ```diff diff --git a/package.json b/package.json index 847c726a69b..78da8232988 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "promise": "^8.0.3", "prop-types": "^15.7.2", "react-devtools-core": "^4.13.0", + "react-native-codegen": "^0.0.7", "react-refresh": "^0.4.0", "regenerator-runtime": "^0.13.2", "scheduler": "^0.20.2", diff --git a/template/package.json b/template/package.json index 715614112ac..5e0762b1b25 100644 --- a/template/package.json +++ b/template/package.json @@ -21,7 +21,6 @@ "eslint": "7.14.0", "jest": "^26.6.3", "metro-react-native-babel-preset": "^0.66.2", - "react-native-codegen": "^0.0.7", "react-test-renderer": "17.0.2" }, "jest": { ``` 2. Run `scripts/test-manual-e2e.sh` ## Expected Behavior Task `:ReactAndroid:buildReactNdkLib` succeeds. ## Actual Behavior ``` > Task :ReactAndroid:buildReactNdkLib FAILED make: Entering directory '~/Source/react-native/ReactAndroid/src/main/jni/react/jni' fcntl(): Bad file descriptor make: Leaving directory '~/Source/react-native/ReactAndroid/src/main/jni/react/jni' ~/Library/Android/sdk/ndk/21.4.7075529/build/core/build-binary.mk:651: Android NDK: Module react_codegen_rncore depends on undefined modules: react_render_components_view ~/Library/Android/sdk/ndk/21.4.7075529/build/core/build-binary.mk:664: *** Android NDK: Note that old versions of ndk-build silently ignored this error case. If your project worked on those versions, the missing libraries were not needed and you can remove those dependencies from the module to fix your build. Alternatively, set APP_ALLOW_MISSING_DEPS=true to allow missing dependencies. . Stop. FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':ReactAndroid:buildReactNdkLib'. > Process 'command '~/Library/Android/sdk/ndk/21.4.7075529/ndk-build'' finished with non-zero exit value 2 * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.9/userguide/command_line_interface.html#sec:command_line_warnings BUILD FAILED in 19s 20 actionable tasks: 20 executed Couldn't generate artifacts ``` Reviewed By: ShikaSD Differential Revision: D30581194 Pulled By: hramos fbshipit-source-id: 3f7a707b33377042502e50887856ff5641fdd52c * feat: add Android 12 BLUETOOTH_ADVERTISE to PermissionsAndroid (#32079) Summary: This PR adds BLUETOOTH_ADVERTISE, which showed up in the latest Android 12 Beta build as new `dangerous` permissions requiring approval for them. https://developer.android.com/reference/android/Manifest.permission.html#BLUETOOTH_ADVERTISE You can see the new set of `SCAN/ADVERTISE/CONNECT` added in this doc - https://developer.android.com/about/versions/12/features/bluetooth-permissions, previously SCAN/CONNECT were added in: https://github.com/facebook/react-native/pull/31488 ## Changelog [Android] [Changed] - Add BLUETOOTH_ADVERTISE to PermissionsAndroid Pull Request resolved: https://github.com/facebook/react-native/pull/32079 Test Plan: ``` PermissionsAndroid.BLUETOOTH_ADVERTISE === 'android.permission.BLUETOOTH_ADVERTISE' ``` Reviewed By: cortinico Differential Revision: D30532656 Pulled By: yungsters fbshipit-source-id: 986ad8cbfc27913df13ab24bba36f6e13104e7d9 * Update manual testing script to also test Hermes for RNTester Summary: Changelog: [Internal] - Update test-manual-e2e.sh to test Hermes for RNTester Reviewed By: ShikaSD Differential Revision: D30569403 fbshipit-source-id: fd45c8158c4c5ad93f33bc7b80464c5fc387a737 * Move react-native-codegen to root * [0.66.0-rc.0] Bump version numbers * Native component check in deprecatedPropType was inverted (#31164) Summary: While investigating an issue hit on a recent sync of [react-native-windows](https://github.com/microsoft/react-native-windows) I noticed that https://github.com/facebook/react-native/commit/e68cf7cee9d36271a1d3899fecff817304bb8bdc appears to have accidently inverted the logic to avoid checking native components. `!UIManager.getViewManagerConfig(componentName)` become `UIManager.hasViewManagerConfig(componentName)` losing the ! Also adding a check in PaperUIManager's getViewManagerConfig to avoid trying to call a sync method when using Chrome Debugging. [Internal] [Fixed] - Restored the previous logic of deprecatedPropType Pull Request resolved: https://github.com/facebook/react-native/pull/31164 Test Plan: Change tested and being submitted in react-native-windows: https://github.com/microsoft/react-native-windows/pull/7397 Reviewed By: hramos Differential Revision: D30624302 Pulled By: fkgozali fbshipit-source-id: 0f26e750283a1fa5eb5f44ecd2cf90617b6d931f * OSS: Fix $ENTRY_FILE check for non-Debug Xcode builds Summary: The original $ENTRY_FILE check was added in https://github.com/facebook/react-native/pull/29012 to help catch misconfiguration for the entry JS file. That turned out breaking some RNTester builds/tests, so https://github.com/facebook/react-native/pull/29263 was added to accommodate the fact that RNTester .xcodeproj file has its own directory hierarchy. The 2nd PR had multiple issues: * It is incorrect to assume that the $ENTRY_FILE always exists in the parent dir of the .xcodeproj location. This caused an issue in RC 0.66: https://github.com/react-native-community/releases/issues/249#issue-983474535 * RNTester has since moved to packages/rn-tester/ (from RNTester/), hence breaking that assumption It turns out RNTester .xcodeproj has incorrectly misconfigured this JS bundling step (not sure since when). The original script invocation passed in the correct path for `RNTesterApp.ios.js`, but as an arg to the `react-native-xcode.sh` instead of by setting `ENTRY_FILE` env var. So this diff does 2 things: * Undid https://github.com/facebook/react-native/pull/29263 * Fix RNTester JS bundling invocation to set the ENTRY_FILE correctly {F659123377} Changelog: [iOS][Fixed] Unbreak $ENTRY_FILE handling for JS bundling Reviewed By: lunaleaps Differential Revision: D30690900 fbshipit-source-id: 7c5802b3eac56c0456edcd4b7478bfa4af48fc27 * OSS: add Xcode 12.5 + M1 machines CocoaPods post_install workaround Summary: Context: there are multiple issues currently exposed by Xcode 12.5 and/or M1 machine + Flipper. To unblock the new 0.66 release, let's add this workaround in the official react_native_pods.rb recipe and make RNTester and new app Podfile's call it directly. Changelog: [iOS][Fixed] Added workaround for Xcode 12.5 / M1 machines build issues Reviewed By: lunaleaps Differential Revision: D30691291 fbshipit-source-id: 8b24cc60da3d620dbc90f95c77f2345e18c28212 * Switch order of search libraries to fix M1 build error Summary: changelog: Resolve Xcode 13 build error on M1 Macs for projects created from RN template Reviewed By: fkgozali Differential Revision: D30693466 fbshipit-source-id: f0b4fd471de38119d636c8e337831aa4d4599c4e * Copy repo-config dependencies for bumping release version Summary: Changelog: [Internal[Fixed] - Revert, yarn workspaces only used in private packages. Copy dependencies over from repo-config instead Original commit changeset: 1dd2adc6a036 Reviewed By: fkgozali Differential Revision: D30599065 fbshipit-source-id: 0efffaaf38bc23bac339e6e1d917736243e1750e * [0.66.0-rc.1] Bump version numbers * [LOCAL] postfix timestamp to bust yarn cache * Make JSI a dynamic library Summary: Ship libjsi as a standalone dynamic library. This prevents problems with exception handling caused by duplicate typeinfo across multiple shared libs, and reduces bundle size by removing duplicate copies of JSI. Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D30599215 fbshipit-source-id: abad1398342a5328daa825f3f684e0067cad7a96 * Revert the Android specific max heap size GCConfig Summary: Changelog: [Category][Internal] This diff reverts the [Androids-specific heap size overrides](github.com/facebook/react-native/commit/63d20d3b1ef35cb4398d63d62f631f7f5d2935c7#diff-4c59ddca85e294a90a0e1bd15ed323ff4e130911d9642680dde44aacbcd7d32c) after [Hermes has changed its default max heap size to 3GiB](https://github.com/facebook/hermes/commit/5f2b47d0be6281fd2605d24efc0b43af42b4033d). You can read about more context there. Reviewed By: yungsters Differential Revision: D30726067 fbshipit-source-id: 1bcc93fdf4da817f3b3d60bd09c6a5a64166eb7e * Bump Hermes npm to 0.9.0 Summary: Changelog: [General][Changed] - Bump Hermes to 0.9.0 allow-large-files Reviewed By: lunaleaps Differential Revision: D30726474 fbshipit-source-id: 742cf68b046d8768e83e00d754e8efcc97586c00 * Bump Hermes pod to 0.9.0 Summary: Changelog: [General][Changed] - Bump Hermes to 0.9.0 (Note: this ignores all push blocking failures!) Reviewed By: lunaleaps Differential Revision: D30726473 fbshipit-source-id: add4149454b3f0333f3c1cb8b5d632371fd1bd80 * Update Podfile.lock * [0.66.0-rc.2] Bump version numbers * Link RCT-Folly against libc++abi Summary: Folly now depends on libc++abi. This solves linker error for RCT-Folly.podspec like this: ``` Undefined symbols for architecture arm64: "___cxa_increment_exception_refcount", referenced from: folly::exception_ptr_get_type(std::exception_ptr const&) in libRCT-Folly.a(Exception.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ``` See https://github.com/react-native-community/releases/issues/251 Note: RNTester was not affected by this bug for some reason, so the only way to verify is via the new app generated via `npx react-native init`. Changelog: [Fixed][iOS] Unbreak Folly linker error Reviewed By: lunaleaps Differential Revision: D30950944 fbshipit-source-id: 3eb146e23faa308a02363761d08849d6801e21ca * Update rn-tester Podfile.lock to prepare for 0.66.0-rc.3 * [0.66.0-rc.3] Bump version numbers * Don’t hard-code CocoaPods’s sandbox path (#32243) Summary: When running `scripts/react_native_pods.rb`, the `Pods` directory may not be in the current working directory, for example, when calling [`pod install`](https://guides.cocoapods.org/terminal/commands.html#pod_install) with `--project-directory=ios`. Therefore, `sed` fails and, ultimately, the build fails. References: * https://rubydoc.info/gems/cocoapods/Pod%2FInstaller:sandbox * https://rubydoc.info/gems/cocoapods/Pod/Sandbox#root-instance_method ## Changelog [iOS] [Fixed] - Fix build error after running `pod install` with `--project-directory=ios` Pull Request resolved: https://github.com/facebook/react-native/pull/32243 Test Plan: 1. `npx react-native init AwesomeProject --version 0.66.0-rc.3 --skip-install` 2. `cd AwesomeProject` 3. `yarn install` 4. `pod install --project-directory=ios` This command prints “sed: Pods/RCT-Folly/folly/portability/Time.h: No such file or directory” but still exits with 0. 5. `npx react-native run-ios` The build fails because of “typedef redefinition with different types” as described in https://github.com/facebook/flipper/issues/834. 6. Apply this patch using `(cd node_modules/react-native && curl https://github.com/kontist/react-native/commit/ec330f756e477e53dde891fe02fd74916d9faef0.patch | patch -p1)` 7. Re-run `pod install --project-directory=ios` 8. Re-run `npx react-native run-ios` The iOS app should now run successfully. Reviewed By: sota000 Differential Revision: D31089656 Pulled By: fkgozali fbshipit-source-id: 431898bed88f68761c7e0e6c79074dc04f43ed23 * OSS: update Podfile.lock automatically when bumping release version Summary: To ensure consistency of RNTester Podfile.lock: * introduce a script to run `pod install` on the current commit * have the script check the exact CocoaPods version to use for consistency * have version bump script run this automatically to keep it up-to-date with the version change To validate, have this change in `0.66-stable` branch, then try: ``` ./scripts/bump-oss-version.js 0.66.0-rc.5 ``` This automatically ran `pod install` which produced the Podfile.lock update. Changelog: [Internal] Reviewed By: TheSavior Differential Revision: D31132867 fbshipit-source-id: 1c82653ca0cfc5471ed2c5091c09648a7acbab90 * [LOCAL] Port react-native-codegen new .gitignore from main This is to bring https://github.com/facebook/react-native/blob/c3ff336326302d7988bf7c187c9dcabed3bae10d/.gitignore#L107 to release branch * OSS: bump-oss-version -- update Podfile.lock later in the flow Summary: There was some hardcoded validation logic to verify package.json and gradle.properties update. Running `pod install` before that failed this validation on release branch, so let's move the pod update a bit later in the flow. This also restrict the version number change check to the specific files for better reliability Changelog: [Internal] Reviewed By: sota000 Differential Revision: D31160139 fbshipit-source-id: d32470d7dfc48c2efab1d2767f3892b33e0b77dd * [0.66.0-rc.4] Bump version numbers * [0.66.0] Bump version numbers * get ios building * remove isSelected and selectedRowIndexPath for now * add workspace * Restore .eslintignore to what it looks like in react-native-macos * Fix easy eslint errors as per the `--fix` option * Fix the rest of the yarn lint errors * Update yarn.lock * Add AccessibilityRole back to Button.js * Fix flow issues on iOS and macOS * Initialize state in VirtualizedSectionList * Update snapshots * Fix parseLogBoxLog tests to include native code blocks * Specify state explicitly for DisplayOptionsStatusExample * Disable "Text with custom accessibility actions" example * android * Fix AnimatedMock spring to handle animated configs * Fix most compile issues for macOS * Fix post_install sed script * Changes that allow RNTester to launch on macOS * Fix isHighContrastEnabled on RNTester accessibility page * Bump special targets in RNTester Podfile to iOS 11 * BorderExample: use a platform color that also exists on macOS * Disable dev mode on ship builds (#888) * revert dev mode on ship builds * rctuicolor * remove unused variable * pod install * fix text fields on macOS * add osx support * image prop and scroll view build failures osx * Fix yarn lint issues * Update Podfile.lock * endline changes * Get rid of macOS RedBox in LayoutEventsExample * fix: Apply proper accessibility role to images on macOS * Add another macOS GH#774 tag * fix snapshot image test failure * upgrade ts to a compatible version * bump podfile.lock * Fix Android patches in fb66merge * change cocoapods version * update internal cocoapods requirements * test increasing min deployable target * min deployment error in CI, bump to 10.15 osx * fix typedef redefinition build error in folly * disable use_flipper in our templates * disable USE_FRAMEWORKS for Flipper support * Revert "disable USE_FRAMEWORKS for Flipper support" This reverts commit c09b6c579c9dc59c1b19d9a82ce3071cd0505a04. * disable post_install of flipper * combine tempated macos post_install * add generate-specs.sh Co-authored-by: Xuan Huang Co-authored-by: Samuel Susla Co-authored-by: Charles Dudley Co-authored-by: Jesse Katsumata Co-authored-by: Sota Ogo Co-authored-by: Rick Hanlon Co-authored-by: David Vacca Co-authored-by: Amy Nichol Co-authored-by: swittk Co-authored-by: Ikko Ashimine Co-authored-by: Joshua Gross Co-authored-by: CodemodService FBSourceClangFormatLinterBot <> Co-authored-by: Michael Chow Co-authored-by: Evan Yeung Co-authored-by: Jacob Parker Co-authored-by: jeswinsimon Co-authored-by: fabriziobertoglio1987 Co-authored-by: Ramanpreet Nara Co-authored-by: Vegas Murphy Co-authored-by: Moti Zilberman Co-authored-by: Test User Co-authored-by: Pieter De Baets Co-authored-by: Paige Sun Co-authored-by: Moti Zilberman Co-authored-by: Andrei Shikov Co-authored-by: Andrew Clark Co-authored-by: Luis Miguel Alvarado Co-authored-by: Sunny Luo Co-authored-by: Saad Najmi Co-authored-by: Héctor Ramos Co-authored-by: Michał Pierzchała Co-authored-by: Harry Yu Co-authored-by: Janic Duplessis Co-authored-by: Jordan Becker Co-authored-by: Nicola Corti Co-authored-by: Phillip Pan Co-authored-by: Dmytro Voronkevych Co-authored-by: Luna Wei Co-authored-by: Chris Tolliday Co-authored-by: Levi Buzolic Co-authored-by: Nishan Bende Co-authored-by: Matthew Gray Co-authored-by: Hein Rutjes Co-authored-by: nacam403 Co-authored-by: Nicholas Tinsley Co-authored-by: hank121314 Co-authored-by: Jonathan Andrew Co-authored-by: alessandro Co-authored-by: Dulmandakh Co-authored-by: Albert Sun Co-authored-by: pera Co-authored-by: Carmi Grushko Co-authored-by: Jimmy Zhang Co-authored-by: Arushi Kesarwani Co-authored-by: Marshall Roch Co-authored-by: Chatura Atapattu Co-authored-by: edenb-moveo <71688494+edenb-moveo@users.noreply.github.com> Co-authored-by: pietro909 <2094604+pietro909@users.noreply.github.com> Co-authored-by: Dmitry Rykun Co-authored-by: Leon Kiefer Co-authored-by: Steven Bell Co-authored-by: Timo Mämecke Co-authored-by: Kacie Bawiec Co-authored-by: Valentin Shergin Co-authored-by: Nick Gerleman Co-authored-by: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Co-authored-by: Connor Tumbleson Co-authored-by: Andrew Coates <30809111+acoates-ms@users.noreply.github.com> Co-authored-by: Kevin Gozali Co-authored-by: Neil Dhar Co-authored-by: Jakob Krigovsky Co-authored-by: Adam Gleitman --- .buckconfig | 3 +- .circleci/Dockerfiles/Dockerfile.android | 3 +- .circleci/config.yml | 122 +- .editorconfig | 7 + .eslintrc | 8 + .flowconfig | 9 +- .flowconfig.android | 9 +- .flowconfig.macos | 7 +- .gitattributes | 2 +- .github/SUPPORT.md | 2 +- ...ml => respond-to-issue-based-on-label.yml} | 2 +- ...label-actions.yml => on-issue-labeled.yml} | 10 +- .gitignore | 10 +- .nvmrc | 1 - BUCK | 1386 ++ CONTRIBUTING.md | 42 +- Folly/folly/portability/Time.h | 4 +- IntegrationTests/AccessibilityManagerTest.js | 2 - IntegrationTests/AsyncStorageTest.js | 57 +- IntegrationTests/BUCK | 30 + .../GlobalEvalWithSourceUrlTest.js | 2 +- IntegrationTests/ImageCachePolicyTest.js | 8 +- .../IntegrationTestHarnessTest.js | 7 +- IntegrationTests/IntegrationTestsApp.js | 20 +- IntegrationTests/LayoutEventsTest.js | 1 + .../ReactContentSizeUpdateTest.js | 2 - IntegrationTests/SizeFlexibilityUpdateTest.js | 2 - IntegrationTests/TimersTest.js | 15 + Libraries/ActionSheetIOS/ActionSheetIOS.js | 4 +- .../NativeActionSheetManager.js | 3 +- .../React-RCTActionSheet.podspec | 4 +- Libraries/Alert/Alert.js | 8 +- Libraries/Alert/NativeAlertManager.js | 2 - Libraries/Alert/RCTAlertManager.android.js | 2 - Libraries/Alert/RCTAlertManager.ios.js | 2 - Libraries/Animated/Animated.js | 2 - Libraries/Animated/AnimatedEvent.js | 7 +- Libraries/Animated/AnimatedImplementation.js | 2 - Libraries/Animated/AnimatedMock.js | 16 +- Libraries/Animated/AnimatedWeb.js | 9 +- Libraries/Animated/NativeAnimatedHelper.js | 17 +- Libraries/Animated/NativeAnimatedModule.js | 2 - .../Animated/NativeAnimatedTurboModule.js | 2 - Libraries/Animated/__tests__/Animated-test.js | 23 +- .../Animated/__tests__/AnimatedNative-test.js | 2 - .../createAnimatedComponentInjection-test.js | 67 + Libraries/Animated/animations/Animation.js | 1 + .../Animated/animations/DecayAnimation.js | 2 + .../Animated/animations/SpringAnimation.js | 1 + .../Animated/animations/TimingAnimation.js | 3 + .../Animated/components/AnimatedFlatList.js | 2 - .../Animated/components/AnimatedImage.js | 8 +- .../Animated/components/AnimatedScrollView.js | 8 +- .../components/AnimatedSectionList.js | 4 +- Libraries/Animated/components/AnimatedText.js | 8 +- Libraries/Animated/components/AnimatedView.js | 6 +- Libraries/Animated/createAnimatedComponent.js | 77 +- .../createAnimatedComponentInjection.js | 48 + .../createAnimatedComponent_EXPERIMENTAL.js | 48 + .../Animated/nodes/AnimatedInterpolation.js | 43 +- Libraries/Animated/nodes/AnimatedProps.js | 1 - Libraries/Animated/nodes/AnimatedValue.js | 23 +- .../Animated/nodes/AnimatedWithChildren.js | 1 + Libraries/Animated/useAnimatedProps.js | 211 + Libraries/AppState/AppState.js | 250 +- Libraries/AppState/NativeAppState.js | 2 - Libraries/BUCK | 36 - Libraries/BatchedBridge/MessageQueue.js | 33 +- Libraries/BatchedBridge/NativeModules.js | 6 +- .../__tests__/MessageQueue-test.js | 2 +- Libraries/Blob/BlobManager.js | 2 - Libraries/Blob/FileReader.js | 4 +- Libraries/Blob/NativeBlobModule.js | 2 - Libraries/Blob/NativeFileReaderModule.js | 2 - Libraries/Blob/RCTBlobManager.h | 3 +- Libraries/Blob/RCTBlobManager.mm | 22 +- Libraries/Blob/RCTBlobPlugins.mm | 7 +- Libraries/Blob/RCTFileReaderModule.mm | 12 +- Libraries/Blob/React-RCTBlob.podspec | 6 +- Libraries/Blob/URL.js | 38 +- Libraries/BugReporting/BugReporting.js | 4 +- Libraries/BugReporting/getReactData.js | 4 +- .../AccessibilityInfo.android.js | 165 - .../AccessibilityInfo.ios.js | 280 - .../AccessibilityInfo/AccessibilityInfo.js | 372 + .../AccessibilityInfo.macos.js | 231 - .../NativeAccessibilityInfo.js | 6 +- .../NativeAccessibilityManager.js | 2 - .../legacySendAccessibilityEvent.android.js | 35 + .../legacySendAccessibilityEvent.ios.js | 26 + .../legacySendAccessibilityEvent.macos.js | 16 + .../ActivityIndicator/ActivityIndicator.js | 43 +- .../ActivityIndicatorViewNativeComponent.js | 2 - .../ActivityIndicator-test.js.snap | 6 - Libraries/Components/Button.js | 73 +- Libraries/Components/Clipboard/Clipboard.js | 2 - .../Components/Clipboard/NativeClipboard.js | 2 - .../DatePicker/DatePickerIOS.android.js | 9 +- .../DatePicker/DatePickerIOS.ios.js | 57 +- .../RCTDatePickerNativeComponent.js | 3 +- .../DatePickerAndroid.android.js | 2 - .../NativeDatePickerAndroid.js | 2 - .../AndroidDrawerLayoutNativeComponent.js | 2 - .../DrawerLayoutAndroid.android.js | 2 - Libraries/Components/Keyboard/Keyboard.js | 111 +- .../Keyboard/KeyboardAvoidingView.js | 44 +- .../Keyboard/NativeKeyboardObserver.js | 2 - .../Keyboard/__tests__/Keyboard-test.js | 26 +- .../MaskedView/MaskedViewIOS.ios.js | 6 +- .../AndroidDialogPickerNativeComponent.js | 82 - .../Picker/AndroidDialogPickerViewConfig.js | 30 - .../AndroidDropdownPickerNativeComponent.js | 69 - Libraries/Components/Picker/Picker.js | 168 - .../Picker/PickerAndroid.android.js | 145 - Libraries/Components/Picker/PickerIOS.ios.js | 165 - .../Picker/RCTPickerNativeComponent.js | 72 - .../Components/Picker/RCTPickerViewConfig.js | 41 - .../Picker/__tests__/Picker-test.js | 34 - .../__snapshots__/Picker-test.js.snap | 97 - Libraries/Components/Pressable/Pressable.js | 27 +- .../Pressable/__tests__/Pressable-test.js | 66 +- .../__snapshots__/Pressable-test.js.snap | 312 + .../Pressable/useAndroidRippleForView.js | 35 +- .../ProgressBarAndroid.android.js | 28 +- .../ProgressBarAndroidNativeComponent.js | 2 - .../ProgressBarAndroid-test.js.snap | 2 - .../ProgressViewIOS.android.js | 9 +- .../ProgressViewIOS/ProgressViewIOS.ios.js | 7 +- .../RCTProgressViewNativeComponent.js | 2 - ...ndroidSwipeRefreshLayoutNativeComponent.js | 14 +- .../PullToRefreshViewNativeComponent.js | 12 +- .../RefreshControl/RefreshControl.js | 33 +- .../__mocks__/RefreshControlMock.js | 5 +- .../RCTSafeAreaViewNativeComponent.js | 2 - .../Components/SafeAreaView/SafeAreaView.js | 2 +- .../__tests__/SafeAreaView-test.js | 2 +- Libraries/Components/ScrollResponder.js | 772 - ...izontalScrollContentViewNativeComponent.js | 35 +- ...roidHorizontalScrollViewNativeComponent.js | 76 +- .../ScrollContentViewNativeComponent.js | 38 +- Libraries/Components/ScrollView/ScrollView.js | 1021 +- .../ScrollView/ScrollViewContext.js | 6 +- .../ScrollView/ScrollViewNativeComponent.js | 96 +- .../ScrollViewNativeComponentType.js | 17 +- .../ScrollView/ScrollViewStickyHeader.js | 498 +- .../ScrollView/ScrollViewViewConfig.js | 18 +- .../ScrollView/__tests__/ScrollView-test.js | 28 +- .../__snapshots__/ScrollView-test.js.snap | 16 +- .../ScrollView/processDecelerationRate.js | 2 - .../RCTSegmentedControlNativeComponent.js | 2 - .../SegmentedControlIOS.android.js | 9 +- .../SegmentedControlIOS.ios.js | 28 +- .../__tests__/SegmentedContolIOS-test.js | 55 + .../SegmentedContolIOS-test.js.snap | 86 + Libraries/Components/Slider/Slider.js | 30 +- .../Slider/SliderNativeComponent.js | 2 - .../Components/Sound/NativeSoundManager.js | 2 - Libraries/Components/Sound/SoundManager.js | 1 - .../NativeStatusBarManagerAndroid.js | 2 - .../StatusBar/NativeStatusBarManagerIOS.js | 2 - Libraries/Components/StatusBar/StatusBar.js | 31 +- .../Components/StatusBar/StatusBarIOS.js | 21 - .../StatusBar/__tests__/StatusBar-test.js | 62 + .../Switch/AndroidSwitchNativeComponent.js | 2 - Libraries/Components/Switch/Switch.js | 216 +- .../Switch/SwitchNativeComponent.js | 2 - .../AndroidTextInputNativeComponent.js | 34 +- .../TextInput/AndroidTextInputViewConfig.js | 12 +- .../TextInput/InputAccessoryView.js | 14 +- .../RCTInputAccessoryViewNativeComponent.js | 2 - .../RCTMultilineTextInputNativeComponent.js | 11 +- .../RCTSingelineTextInputNativeComponent.js | 22 +- ...iewConfig.js => RCTTextInputViewConfig.js} | 8 +- Libraries/Components/TextInput/TextInput.js | 541 +- .../TextInput/TextInputNativeCommands.js | 2 - .../Components/TextInput/TextInputState.js | 4 +- .../TextInput/__tests__/TextInput-test.js | 2 - .../__snapshots__/TextInput-test.js.snap | 20 +- .../ToastAndroid/NativeToastAndroid.js | 2 - .../ToastAndroid/ToastAndroid.android.js | 1 - .../Touchable/BoundingDimensions.js | 3 +- Libraries/Components/Touchable/PooledClass.js | 3 +- Libraries/Components/Touchable/Position.js | 3 +- Libraries/Components/Touchable/Touchable.js | 81 +- .../Components/Touchable/TouchableBounce.js | 2 - .../Touchable/TouchableHighlight.js | 28 +- .../Touchable/TouchableNativeFeedback.js | 21 +- .../Components/Touchable/TouchableOpacity.js | 30 +- .../Touchable/TouchableWithoutFeedback.js | 20 +- .../__tests__/TouchableHighlight-test.js | 72 +- .../__tests__/TouchableNativeFeedback-test.js | 115 + .../__tests__/TouchableOpacity-test.js | 52 + .../TouchableWithoutFeedback-test.js | 91 + .../TouchableHighlight-test.js.snap | 126 + .../TouchableNativeFeedback-test.js.snap | 141 + .../TouchableOpacity-test.js.snap | 98 + .../TouchableWithoutFeedback-test.js.snap | 137 + .../Touchable/ensurePositiveDelayProps.js | 3 +- .../UnimplementedNativeViewNativeComponent.js | 2 - .../UnimplementedViews/UnimplementedView.js | 5 +- .../View/ReactNativeStyleAttributes.js | 201 +- .../View/ReactNativeViewAttributes.js | 3 +- .../View/ReactNativeViewViewConfig.js | 24 +- Libraries/Components/View/View.js | 6 +- .../Components/View/ViewAccessibility.js | 5 +- .../Components/View/ViewNativeComponent.js | 79 +- Libraries/Components/__tests__/Button-test.js | 49 + Libraries/Components/__tests__/Slider-test.js | 37 + .../__snapshots__/Button-test.js.snap | 396 + .../__snapshots__/Slider-test.js.snap | 121 + .../parseHermesStack-test.js.snap | 28 + .../__tests__/parseHermesStack-test.js | 12 + Libraries/Core/Devtools/getDevServer.js | 2 - Libraries/Core/Devtools/parseErrorStack.js | 9 - Libraries/Core/Devtools/parseHermesStack.js | 2 +- Libraries/Core/ExceptionsManager.js | 88 +- Libraries/Core/ExtendedError.js | 19 + Libraries/Core/InitializeCore.js | 1 + Libraries/Core/NativeExceptionsManager.js | 2 - Libraries/Core/ReactFiberErrorDialog.js | 78 +- Libraries/Core/ReactNativeVersion.js | 4 +- Libraries/Core/ReactNativeVersionCheck.js | 2 - .../SegmentFetcher/NativeSegmentFetcher.js | 2 - Libraries/Core/Timers/JSTimers.js | 99 +- Libraries/Core/Timers/NativeTiming.js | 2 - .../Core/Timers/__tests__/JSTimers-test.js | 68 +- Libraries/Core/Timers/immediateShim.js | 67 + Libraries/Core/Timers/queueMicrotask.js | 41 + .../Core/__tests__/ExceptionsManager-test.js | 44 +- Libraries/Core/polyfillPromise.js | 2 +- Libraries/Core/setUpDeveloperTools.js | 111 +- Libraries/Core/setUpReactDevTools.js | 19 +- Libraries/Core/setUpReactRefresh.js | 4 +- Libraries/Core/setUpRegeneratorRuntime.js | 33 +- Libraries/Core/setUpTimers.js | 69 +- Libraries/Core/setUpXHR.js | 8 +- .../DeprecatedImagePropType.android.js | 131 + ...Type.js => DeprecatedImagePropType.ios.js} | 0 .../DeprecatedImagePropType.macos.js | 16 + .../DeprecatedTextInputPropTypes.js | 10 +- .../DeprecatedViewAccessibility.js | 2 + Libraries/EventEmitter/NativeEventEmitter.js | 147 +- .../EventEmitter/RCTDeviceEventEmitter.js | 79 +- Libraries/EventEmitter/RCTEventEmitter.js | 6 +- .../EventEmitter/RCTNativeAppEventEmitter.js | 2 - .../__mocks__/NativeEventEmitter.js | 39 +- Libraries/FBLazyVector/BUCK | 6 +- Libraries/FBLazyVector/FBLazyVector.podspec | 4 +- Libraries/HeapCapture/HeapCapture.js | 2 - Libraries/HeapCapture/NativeJSCHeapCapture.js | 2 - Libraries/Image/AssetSourceResolver.js | 24 +- Libraries/Image/AssetUtils.js | 48 + Libraries/Image/Image.android.js | 175 +- Libraries/Image/Image.ios.js | 90 +- Libraries/Image/ImageAnalyticsTagContext.js | 6 +- Libraries/Image/ImageBackground.js | 4 +- Libraries/Image/ImageInjection.js | 28 + Libraries/Image/ImagePickerIOS.js | 2 - Libraries/Image/ImageSource.js | 71 +- Libraries/Image/ImageViewNativeComponent.js | 97 +- Libraries/Image/ImageViewViewConfig.js | 68 - Libraries/Image/NativeImageEditor.js | 2 - Libraries/Image/NativeImageLoaderAndroid.js | 2 - Libraries/Image/NativeImageLoaderIOS.js | 8 +- Libraries/Image/NativeImagePickerIOS.js | 2 - Libraries/Image/NativeImageStoreAndroid.js | 2 - Libraries/Image/NativeImageStoreIOS.js | 2 - Libraries/Image/RCTAnimatedImage.m | 9 +- Libraries/Image/RCTGIFImageDecoder.mm | 6 + Libraries/Image/RCTImageBlurUtils.m | 28 +- Libraries/Image/RCTImageEditingManager.mm | 8 +- Libraries/Image/RCTImageLoader.h | 4 +- Libraries/Image/RCTImageLoader.mm | 61 +- .../RCTImageLoaderWithAttributionProtocol.h | 5 - Libraries/Image/RCTImagePlugins.mm | 7 +- Libraries/Image/RCTImageStoreManager.mm | 10 +- .../Image/RCTImageURLLoaderWithAttribution.h | 1 + Libraries/Image/RCTImageView.mm | 2 +- Libraries/Image/RCTLocalAssetImageLoader.mm | 5 + Libraries/Image/React-RCTImage.podspec | 6 +- .../Image/TextInlineImageNativeComponent.js | 86 +- Libraries/Image/__tests__/AssetUtils-test.js | 38 + .../__snapshots__/Image-test.js.snap | 1 + Libraries/Image/nativeImageSource.js | 2 - Libraries/Image/resolveAssetSource.js | 3 +- Libraries/Inspector/ElementProperties.js | 2 +- Libraries/Inspector/Inspector.js | 17 +- Libraries/Inspector/InspectorPanel.js | 2 +- Libraries/Interaction/FrameRateLogger.js | 2 - Libraries/Interaction/InteractionManager.js | 13 +- Libraries/Interaction/InteractionMixin.js | 3 +- Libraries/Interaction/PanResponder.js | 2 +- Libraries/LayoutAnimation/LayoutAnimation.js | 70 +- Libraries/Linking/Linking.js | 29 +- Libraries/Linking/NativeIntentAndroid.js | 2 - Libraries/Linking/NativeLinkingManager.js | 2 - Libraries/LinkingIOS/RCTLinkingPlugins.mm | 7 +- Libraries/LinkingIOS/React-RCTLinking.podspec | 6 +- Libraries/Lists/CellRenderMask.js | 145 + Libraries/Lists/FillRateHelper.js | 2 +- Libraries/Lists/FlatList.js | 132 +- Libraries/Lists/SectionList.js | 43 +- Libraries/Lists/SectionListModern.js | 249 + Libraries/Lists/ViewabilityHelper.js | 18 +- Libraries/Lists/VirtualizeUtils.js | 38 +- Libraries/Lists/VirtualizedList.js | 329 +- Libraries/Lists/VirtualizedListContext.js | 5 +- Libraries/Lists/VirtualizedSectionList.js | 501 +- .../__flowtests__/SectionList-flowtest.js | 12 +- .../Lists/__tests__/CellRenderMask-test.js | 179 + Libraries/Lists/__tests__/SectionList-test.js | 6 +- .../Lists/__tests__/VirtualizeUtils-test.js | 5 +- .../Lists/__tests__/VirtualizedList-test.js | 1035 +- .../__tests__/VirtualizedSectionList-test.js | 75 +- .../__snapshots__/FlatList-test.js.snap | 56 +- .../__snapshots__/SectionList-test.js.snap | 39 +- .../VirtualizedList-test.js.snap | 4887 ++++- .../VirtualizedSectionList-test.js.snap | 253 +- Libraries/LogBox/Data/LogBoxData.js | 4 +- Libraries/LogBox/Data/LogBoxLog.js | 2 - Libraries/LogBox/Data/LogBoxSymbolication.js | 2 - .../LogBox/Data/__tests__/LogBoxData-test.js | 6 + .../Data/__tests__/parseLogBoxLog-test.js | 56 +- Libraries/LogBox/Data/parseLogBoxLog.js | 2 - Libraries/LogBox/LogBox.js | 163 +- Libraries/LogBox/LogBoxInspectorContainer.js | 2 - .../LogBox/LogBoxNotificationContainer.js | 2 - Libraries/LogBox/UI/LogBoxButton.js | 2 - Libraries/LogBox/UI/LogBoxInspector.js | 2 - .../LogBox/UI/LogBoxInspectorCodeFrame.js | 2 - Libraries/LogBox/UI/LogBoxInspectorFooter.js | 2 - Libraries/LogBox/UI/LogBoxInspectorHeader.js | 2 - .../LogBox/UI/LogBoxInspectorMessageHeader.js | 2 - .../LogBox/UI/LogBoxInspectorReactFrames.js | 2 - Libraries/LogBox/UI/LogBoxInspectorSection.js | 2 - .../UI/LogBoxInspectorSourceMapStatus.js | 9 +- .../LogBox/UI/LogBoxInspectorStackFrame.js | 2 - .../LogBox/UI/LogBoxInspectorStackFrames.js | 7 +- Libraries/LogBox/UI/LogBoxMessage.js | 2 - Libraries/LogBox/UI/LogBoxNotification.js | 7 +- Libraries/LogBox/UI/LogBoxStyle.js | 2 - .../LogBox/UI/__tests__/LogBoxButton-test.js | 2 - .../__tests__/LogBoxInspectorSection-test.js | 2 - .../LogBoxInspectorStackFrames-test.js | 2 - .../__tests__/LogBox-integration-test.js | 2 - Libraries/LogBox/__tests__/LogBox-test.js | 109 +- .../__fixtures__/ReactWarningFixtures.js | 2 - Libraries/Modal/Modal.js | 67 +- .../Modal/ModalInjection.js | 11 +- Libraries/Modal/NativeModalManager.js | 2 - .../Modal/RCTModalHostViewNativeComponent.js | 13 +- .../__snapshots__/Modal-test.js.snap | 2 + .../NativeAnimation/RCTAnimationPlugins.mm | 7 +- .../RCTNativeAnimatedModule.mm | 9 +- .../RCTNativeAnimatedNodesManager.h | 2 +- .../RCTNativeAnimatedNodesManager.m | 2 +- .../RCTNativeAnimatedTurboModule.h | 3 +- .../RCTNativeAnimatedTurboModule.mm | 54 +- .../React-RCTAnimation.podspec | 8 +- .../NativeComponentRegistry.js | 157 + Libraries/NativeComponent/ViewConfig.js | 50 + .../specs/NativeAnimationsDebugModule.js | 2 - .../NativeModules/specs/NativeDevMenu.js | 2 - .../NativeModules/specs/NativeDevSettings.js | 2 - .../specs/NativeDeviceEventManager.js | 2 - .../specs/NativeDialogManagerAndroid.js | 2 - Libraries/NativeModules/specs/NativeLogBox.js | 2 - Libraries/NativeModules/specs/NativeRedBox.js | 2 - .../NativeModules/specs/NativeSourceCode.js | 2 - Libraries/Network/NativeNetworkingAndroid.js | 2 - Libraries/Network/NativeNetworkingIOS.js | 2 - Libraries/Network/RCTDataRequestHandler.mm | 6 + Libraries/Network/RCTFileRequestHandler.mm | 6 + Libraries/Network/RCTHTTPRequestHandler.h | 5 + Libraries/Network/RCTHTTPRequestHandler.mm | 36 +- Libraries/Network/RCTNetworkPlugins.mm | 7 +- Libraries/Network/RCTNetworking.android.js | 12 +- Libraries/Network/RCTNetworking.h | 2 +- Libraries/Network/RCTNetworking.ios.js | 83 +- Libraries/Network/RCTNetworking.mm | 16 +- Libraries/Network/React-RCTNetwork.podspec | 6 +- Libraries/Network/XMLHttpRequest.js | 8 +- .../Network/__tests__/XMLHttpRequest-test.js | 2 - Libraries/Network/convertRequestBody.js | 3 +- Libraries/NewAppScreen/components/Colors.js | 2 - Libraries/NewAppScreen/components/Header.js | 2 +- .../NewAppScreen/components/HermesBadge.js | 5 +- .../NewAppScreen/components/LearnMoreLinks.js | 1 - Libraries/NewAppScreen/index.js | 2 - .../Performance/NativeJSCSamplingProfiler.js | 2 - .../Performance/QuickPerformanceLogger.js | 8 +- Libraries/Performance/Systrace.js | 8 +- .../NativePermissionsAndroid.js | 7 +- .../PermissionsAndroid/PermissionsAndroid.js | 15 +- Libraries/Pressability/HoverState.js | 2 - Libraries/Pressability/Pressability.js | 46 +- Libraries/Pressability/PressabilityDebug.js | 13 +- .../PressabilityPerformanceEventEmitter.js | 47 + Libraries/Pressability/PressabilityTypes.js | 18 + .../__tests__/Pressability-test.js | 20 +- Libraries/Pressability/usePressability.js | 2 - .../NativePushNotificationManagerIOS.js | 3 + .../PushNotificationIOS.js | 50 +- .../RCTPushNotificationManager.mm | 15 +- .../RCTPushNotificationPlugins.mm | 7 +- .../React-RCTPushNotification.podspec | 6 +- Libraries/RCTRequired/BUCK | 5 +- Libraries/RCTRequired/RCTRequired.podspec | 4 +- Libraries/ReactNative/AppContainer.js | 28 +- Libraries/ReactNative/AppRegistry.js | 55 +- Libraries/ReactNative/DisplayMode.js | 32 + Libraries/ReactNative/DummyUIManager.js | 10 +- Libraries/ReactNative/FabricUIManager.js | 11 +- Libraries/ReactNative/HeadlessJsTaskError.js | 2 - Libraries/ReactNative/I18nManager.js | 32 +- .../NativeHeadlessJsTaskSupport.js | 2 - Libraries/ReactNative/NativeI18nManager.js | 3 +- Libraries/ReactNative/NativeUIManager.js | 5 +- Libraries/ReactNative/PaperUIManager.js | 110 +- Libraries/ReactNative/RootTag.js | 10 +- Libraries/ReactNative/UIManager.js | 10 +- .../UIManagerInjection.js} | 8 +- Libraries/ReactNative/UIManagerProperties.js | 1 + .../getCachedComponentWithDebugName.js | 32 + .../getNativeComponentAttributes.js | 3 +- Libraries/ReactNative/renderApplication.js | 30 +- .../ReactNativePrivateInterface.js | 12 +- Libraries/Reliability/UserFlow.js | 30 +- Libraries/Renderer/REVISION | 2 +- .../implementations/ReactFabric-dev.fb.js | 16536 ++++++++------- .../implementations/ReactFabric-dev.js | 10715 +++++----- .../implementations/ReactFabric-prod.fb.js | 5444 ++--- .../implementations/ReactFabric-prod.js | 4067 ++-- .../ReactFabric-profiling.fb.js | 6124 +++--- .../implementations/ReactFabric-profiling.js | 4842 ++--- .../ReactNativeRenderer-dev.fb.js | 16943 +++++++++------- .../ReactNativeRenderer-dev.js | 10515 +++++----- .../ReactNativeRenderer-prod.fb.js | 5191 ++--- .../ReactNativeRenderer-prod.js | 4417 ++-- .../ReactNativeRenderer-profiling.fb.js | 5777 +++--- .../ReactNativeRenderer-profiling.js | 4856 ++--- Libraries/Renderer/shims/ReactFabric.js | 8 +- Libraries/Renderer/shims/ReactFeatureFlags.js | 3 + Libraries/Renderer/shims/ReactNative.js | 3 + Libraries/Renderer/shims/ReactNativeTypes.js | 167 +- .../shims/ReactNativeViewConfigRegistry.js | 19 +- .../shims/createReactNativeComponentClass.js | 8 +- Libraries/Settings/NativeSettingsManager.js | 2 - Libraries/Settings/RCTSettingsManager.mm | 4 +- Libraries/Settings/RCTSettingsPlugins.mm | 7 +- Libraries/Settings/React-RCTSettings.podspec | 6 +- Libraries/Settings/Settings.ios.js | 6 +- Libraries/Share/NativeShareModule.js | 2 - Libraries/Share/Share.js | 2 - Libraries/Storage/AsyncStorage.js | 117 +- Libraries/Storage/NativeAsyncLocalStorage.js | 19 +- .../Storage/NativeAsyncSQLiteDBStorage.js | 19 +- .../PlatformColorValueTypes.android.js | 2 - .../StyleSheet/PlatformColorValueTypes.ios.js | 19 +- .../PlatformColorValueTypesIOS.ios.js | 11 +- .../StyleSheet/PlatformColorValueTypesIOS.js | 4 +- Libraries/StyleSheet/Rect.js | 2 - Libraries/StyleSheet/StyleSheet.js | 8 +- Libraries/StyleSheet/StyleSheetTypes.js | 5 + Libraries/StyleSheet/StyleSheetValidation.js | 100 - .../StyleSheet/__tests__/flattenStyle-test.js | 6 - .../__tests__/normalizeColor-test.js | 19 + .../__tests__/processColorArray-test.js | 26 +- .../__tests__/splitLayoutProps-test.js | 8 +- Libraries/StyleSheet/flattenStyle.js | 12 +- Libraries/StyleSheet/normalizeColor.js | 2 - Libraries/StyleSheet/processColorArray.js | 22 +- Libraries/StyleSheet/processTransform.js | 12 +- Libraries/StyleSheet/splitLayoutProps.js | 98 +- .../RCTSurfaceHostingComponent.mm | 2 +- Libraries/Text/React-RCTText.podspec | 4 +- Libraries/Text/Text.js | 422 +- Libraries/Text/TextAncestor.js | 8 +- .../Text/TextInput/Multiline/RCTUITextView.h | 2 - .../Text/TextInput/Multiline/RCTUITextView.m | 14 + .../Text/TextInput/RCTBaseTextInputView.m | 8 + Libraries/Text/TextNativeComponent.js | 7 +- Libraries/Text/TextProps.js | 6 + Libraries/TurboModule/RCTExport.js | 2 +- Libraries/TurboModule/TurboModuleRegistry.js | 31 +- .../samples/NativeSampleTurboModule.js | 4 +- Libraries/TypeSafety/RCTTypeSafety.podspec | 6 +- Libraries/Types/CodegenTypes.js | 3 +- Libraries/Types/CoreEventTypes.js | 4 +- .../RootTagTypes.js} | 5 +- Libraries/UTFSequence.js | 2 +- Libraries/Utilities/Appearance.js | 30 +- Libraries/Utilities/BackHandler.android.js | 2 - Libraries/Utilities/DebugEnvironment.js | 4 +- Libraries/Utilities/DevSettings.js | 107 +- Libraries/Utilities/DeviceInfo.js | 2 - Libraries/Utilities/Dimensions.js | 41 +- Libraries/Utilities/FeatureDetection.js | 31 + .../Utilities/GlobalPerformanceLogger.js | 1 - Libraries/Utilities/HMRClient.js | 25 +- Libraries/Utilities/JSDevSupportModule.js | 2 - Libraries/Utilities/LoadingView.android.js | 2 - Libraries/Utilities/LoadingView.ios.js | 2 - Libraries/Utilities/MatrixMath.js | 2 +- Libraries/Utilities/NativeAppearance.js | 2 - Libraries/Utilities/NativeDevLoadingView.js | 2 - .../Utilities/NativeDevSplitBundleLoader.js | 2 - Libraries/Utilities/NativeDeviceInfo.js | 4 +- Libraries/Utilities/NativeJSDevSupport.js | 2 - .../NativePlatformConstantsAndroid.js | 2 - .../Utilities/NativePlatformConstantsIOS.js | 2 - .../Utilities/PerformanceLoggerContext.js | 15 +- Libraries/Utilities/Platform.android.js | 11 +- Libraries/Utilities/Platform.ios.js | 3 +- Libraries/Utilities/Platform.macos.js | 9 +- Libraries/Utilities/ReactNativeTestTools.js | 31 +- .../__tests__/PerformanceLogger-test.js | 2 - .../__tests__/setAndForwardRef-test.js | 12 +- .../Utilities/__tests__/stringifySafe-test.js | 2 - .../Utilities/__tests__/useMergeRefs-test.js | 228 + .../Utilities/__tests__/useRefEffect-test.js | 242 + ...erifyComponentAttributeEquivalence-test.js | 78 +- Libraries/Utilities/codegenNativeCommands.js | 4 +- Libraries/Utilities/codegenNativeComponent.js | 2 - .../Utilities/createPerformanceLogger.js | 2 - .../deepFreezeAndThrowOnMutationInDev.js | 1 + .../Utilities/defineLazyObjectProperty.js | 2 +- Libraries/Utilities/deprecatedPropType.js | 8 +- .../Utilities/registerGeneratedViewConfig.js | 83 - Libraries/Utilities/stringifySafe.js | 4 +- Libraries/Utilities/useColorScheme.js | 8 +- Libraries/Utilities/useMergeRefs.js | 44 + Libraries/Utilities/useRefEffect.js | 45 + Libraries/Utilities/useWindowDimensions.js | 15 +- .../verifyComponentAttributeEquivalence.js | 50 +- Libraries/Vibration/NativeVibration.js | 2 - Libraries/Vibration/RCTVibrationPlugins.mm | 7 +- .../Vibration/React-RCTVibration.podspec | 6 +- Libraries/Vibration/Vibration.js | 2 - Libraries/WebSocket/NativeWebSocketModule.js | 2 - Libraries/WebSocket/WebSocket.js | 43 +- Libraries/WebSocket/WebSocketInterceptor.js | 11 +- .../WebSocket/__tests__/WebSocket-test.js | 1 + Libraries/YellowBox/YellowBoxDeprecated.js | 1 + .../__tests__/YellowBoxDeprecated-test.js | 21 +- .../ReactNativeTypes-flowtest.js | 2 - Libraries/promiseRejectionIsError.js | 24 - Libraries/promiseRejectionTrackingOptions.js | 4 +- Libraries/vendor/emitter/EventEmitter.js | 41 +- Libraries/vendor/emitter/EventSubscription.js | 19 + .../vendor/emitter/_EmitterSubscription.js | 31 +- Libraries/vendor/emitter/_EventEmitter.js | 92 +- .../vendor/emitter/_EventSubscription.js | 18 +- .../emitter/_EventSubscriptionVendor.js | 35 +- .../__flowtests__/EventEmitter-flowtest.js | 125 + README.md | 29 + React-Core.podspec | 15 +- React.podspec | 6 +- .../en.lproj/Localizable.strings | 2 +- React/Base/RCTAssert.h | 53 +- React/Base/RCTAssert.m | 52 + React/Base/RCTBridge.h | 18 +- React/Base/RCTBridge.m | 19 +- React/Base/RCTBridgeModule.h | 104 + React/Base/RCTBundleManager.m | 78 + React/Base/RCTBundleURLProvider.h | 44 +- React/Base/RCTBundleURLProvider.mm | 111 +- React/Base/RCTCallableJSModules.m | 47 + React/Base/RCTConstants.h | 19 +- React/Base/RCTConstants.m | 36 +- React/Base/RCTConvert.m | 48 +- React/Base/RCTCxxConvert.h | 2 +- React/Base/RCTDefines.h | 10 + React/Base/RCTEventDispatcherProtocol.h | 3 +- .../RCTInitializing.h} | 6 +- React/Base/RCTJSInvokerModule.h | 17 - React/Base/RCTJavaScriptLoader.mm | 1 + React/Base/RCTModuleData.h | 23 +- React/Base/RCTModuleData.mm | 124 +- React/Base/RCTModuleRegistry.m | 48 + React/Base/RCTMultipartStreamReader.m | 2 - React/Base/RCTRootView.h | 11 +- React/Base/RCTRootView.m | 16 +- React/Base/RCTTouchHandler.m | 13 +- React/Base/RCTUIKit.h | 4 + React/Base/RCTUtils.m | 8 +- React/Base/RCTVersion.m | 4 +- React/Base/RCTViewRegistry.m | 45 + React/Base/Surface/RCTSurfaceStage.h | 17 +- .../RCTSurfaceHostingProxyRootView.h | 1 + .../RCTSurfaceHostingProxyRootView.mm | 11 + .../RCTSurfaceHostingView.mm | 3 + React/CoreModules/BUCK | 11 +- React/CoreModules/CoreModulesPlugins.mm | 7 +- React/CoreModules/RCTAccessibilityManager.mm | 27 +- React/CoreModules/RCTActionSheetManager.mm | 44 +- React/CoreModules/RCTAlertController.h | 1 + React/CoreModules/RCTAlertController.m | 5 + React/CoreModules/RCTAlertManager.mm | 3 + React/CoreModules/RCTAsyncLocalStorage.mm | 4 + React/CoreModules/RCTDevLoadingView.mm | 45 +- React/CoreModules/RCTDevMenu.h | 5 - React/CoreModules/RCTDevMenu.mm | 123 +- React/CoreModules/RCTDevSettings.h | 14 +- React/CoreModules/RCTDevSettings.mm | 157 +- React/CoreModules/RCTDevSplitBundleLoader.mm | 9 +- React/CoreModules/RCTDeviceInfo.h | 4 +- React/CoreModules/RCTDeviceInfo.mm | 50 +- React/CoreModules/RCTEventDispatcher.h | 3 +- React/CoreModules/RCTEventDispatcher.mm | 43 +- React/CoreModules/RCTExceptionsManager.mm | 30 +- React/CoreModules/RCTKeyboardObserver.mm | 2 +- React/CoreModules/RCTLogBox.mm | 24 +- React/CoreModules/RCTPerfMonitor.mm | 16 +- React/CoreModules/RCTRedBox.mm | 13 +- React/CoreModules/RCTSourceCode.mm | 3 +- React/CoreModules/RCTTiming.h | 3 +- React/CoreModules/RCTTiming.mm | 4 +- React/CoreModules/RCTWebSocketExecutor.mm | 6 + React/CoreModules/React-CoreModules.podspec | 6 +- React/CxxBridge/RCTCxxBridge.mm | 107 +- React/CxxModule/RCTNativeModule.mm | 4 +- React/DevSupport/RCTPackagerConnection.mm | 17 +- .../FBReactNativeSpec.podspec | 26 +- .../RCTActivityIndicatorViewComponentView.mm | 2 +- .../Image/RCTImageComponentView.h | 3 +- .../Image/RCTImageComponentView.mm | 64 +- .../RCTInputAccessoryComponentView.mm | 15 +- ...CTLegacyViewManagerInteropComponentView.mm | 22 +- ...acyViewManagerInteropCoordinatorAdapter.mm | 4 +- .../Modal/RCTFabricModalHostViewController.mm | 7 + .../Modal/RCTModalHostViewComponentView.h | 4 +- .../Modal/RCTModalHostViewComponentView.mm | 97 +- .../Picker/RCTPickerComponentView.h | 19 - .../Picker/RCTPickerComponentView.mm | 205 - .../RCTFabricComponentsPlugins.h | 2 +- .../RCTFabricComponentsPlugins.mm | 2 +- .../RCTSafeAreaViewComponentView.mm | 54 +- .../ScrollView/RCTEnhancedScrollView.h | 6 + .../ScrollView/RCTEnhancedScrollView.mm | 27 +- .../RCTPullToRefreshViewComponentView.mm | 2 +- .../ScrollView/RCTScrollViewComponentView.mm | 285 +- .../Slider/RCTSliderComponentView.mm | 2 +- .../Switch/RCTSwitchComponentView.mm | 2 +- .../Text/RCTAccessibilityElement.h | 23 + .../Text/RCTAccessibilityElement.mm | 22 + ...ParagraphComponentAccessibilityProvider.mm | 23 +- .../Text/RCTParagraphComponentView.mm | 148 +- .../TextInput/RCTTextInputComponentView.mm | 137 +- .../TextInput/RCTTextInputUtils.mm | 50 +- .../RCTUnimplementedViewComponentView.mm | 2 +- .../View/RCTViewComponentView.mm | 162 +- .../Fabric/Mounting/RCTComponentViewFactory.h | 12 +- .../Mounting/RCTComponentViewFactory.mm | 129 +- .../Mounting/RCTComponentViewProtocol.h | 3 + .../Mounting/RCTComponentViewRegistry.mm | 2 +- React/Fabric/Mounting/RCTMountingManager.h | 29 +- React/Fabric/Mounting/RCTMountingManager.mm | 74 +- .../Mounting/UIView+ComponentViewProtocol.h | 4 + .../Mounting/UIView+ComponentViewProtocol.mm | 34 +- React/Fabric/RCTConversions.h | 36 +- React/Fabric/RCTScheduler.h | 27 +- React/Fabric/RCTScheduler.mm | 75 +- React/Fabric/RCTSurfacePresenter.h | 25 +- React/Fabric/RCTSurfacePresenter.mm | 227 +- .../Fabric/RCTSurfacePresenterBridgeAdapter.h | 6 +- .../RCTSurfacePresenterBridgeAdapter.mm | 2 +- React/Fabric/RCTSurfaceRegistry.h | 2 +- React/Fabric/RCTSurfaceTouchHandler.mm | 46 +- React/Fabric/Surface/RCTFabricSurface.h | 15 +- React/Fabric/Surface/RCTFabricSurface.mm | 266 +- React/Modules/RCTEventEmitter.h | 5 +- React/Modules/RCTEventEmitter.m | 19 +- React/Modules/RCTI18nUtil.h | 8 +- React/Modules/RCTI18nUtil.m | 2 +- React/Modules/RCTUIManager.m | 28 +- React/Profiler/RCTProfile.m | 17 +- React/Profiler/RCTProfileTrampoline-arm.S | 2 +- React/Profiler/RCTProfileTrampoline-arm64.S | 4 +- React/React-RCTFabric.podspec | 18 +- .../Text/RCTParagraphComponentViewTests.mm | 72 + React/Views/RCTBorderDrawing.m | 53 +- React/Views/RCTComponentData.h | 11 +- React/Views/RCTComponentData.m | 31 +- React/Views/RCTConvert+CoreLocation.m | 4 +- React/Views/RCTDatePickerManager.m | 33 + React/Views/RCTLayout.m | 46 +- React/Views/RCTModalHostView.h | 6 +- React/Views/RCTModalHostView.m | 72 +- React/Views/RCTModalHostViewManager.m | 24 +- React/Views/RCTModalManager.h | 2 +- React/Views/RCTModalManager.m | 4 +- React/Views/RCTPicker.h | 28 - React/Views/RCTPicker.m | 211 - React/Views/RCTPickerManager.m | 68 - React/Views/RCTShadowView+Layout.m | 27 +- React/Views/RCTShadowView.m | 5 +- React/Views/RCTView.h | 14 +- React/Views/RCTView.m | 80 +- React/Views/RCTViewManager.m | 21 +- React/Views/RCTWeakViewHolder.h | 19 + .../Views/RefreshControl/RCTRefreshControl.m | 26 + .../RefreshControl/RCTRefreshControlManager.m | 1 + React/Views/ScrollView/RCTScrollContentView.m | 2 +- React/Views/ScrollView/RCTScrollView.h | 8 +- React/Views/ScrollView/RCTScrollView.m | 82 +- React/Views/ScrollView/RCTScrollViewManager.m | 3 + React/third-party.xcconfig | 2 +- ReactAndroid/Android-prebuilt.mk | 85 +- ReactAndroid/README.md | 4 +- ReactAndroid/build.gradle | 179 +- ReactAndroid/gradle.properties | 13 +- ReactAndroid/proguard-rules.pro | 8 +- ReactAndroid/release.gradle | 142 - ReactAndroid/src/androidTest/buck-runner/BUCK | 1 + .../java/com/facebook/react/testing/BUCK | 3 +- .../ReactAppInstrumentationTestCase.java | 2 +- .../facebook/react/testing/idledetection/BUCK | 3 +- .../idledetection/ReactIdleDetectionUtil.java | 2 +- .../com/facebook/react/testing/network/BUCK | 1 + .../java/com/facebook/react/testing/rule/BUCK | 11 +- .../java/com/facebook/react/tests/BUCK | 2 +- .../react/tests/ReactPickerTestCase.java | 196 - .../react/tests/TextInputTestCase.java | 3 +- .../java/com/facebook/react/tests/core/BUCK | 11 +- ReactAndroid/src/androidTest/js/BUCK | 26 + .../androidTest/js/PickerAndroidTestModule.js | 89 - ReactAndroid/src/androidTest/js/TestBundle.js | 5 - .../src/androidTest/js/UIManagerTestModule.js | 13 +- ReactAndroid/src/main/java/com/facebook/BUCK | 1 + .../facebook/debug/debugoverlay/model/BUCK | 1 + .../main/java/com/facebook/debug/holder/BUCK | 1 + .../main/java/com/facebook/debug/tags/BUCK | 1 + .../hermes/instrumentation/Android.mk | 4 +- .../com/facebook/hermes/instrumentation/BUCK | 2 + .../facebook/hermes/reactexecutor/Android.mk | 8 +- .../com/facebook/hermes/reactexecutor/BUCK | 2 + .../reactexecutor/HermesExecutorFactory.java | 2 +- .../facebook/hermes/reactexecutor/OnLoad.cpp | 15 + .../hermes/reactexecutor/RuntimeConfig.java | 6 - .../java/com/facebook/hermes/unicode/BUCK | 1 + .../src/main/java/com/facebook/perftest/BUCK | 1 + .../com/facebook/proguard/annotations/BUCK | 5 +- .../annotations/proguard_annotations.pro | 1 + .../src/main/java/com/facebook/react/BUCK | 5 +- .../facebook/react/CoreModulesPackage.java | 5 +- .../com/facebook/react/ReactActivity.java | 1 + .../facebook/react/ReactActivityDelegate.java | 6 +- .../ReactAndroidHWInputDeviceHelper.java | 5 + .../com/facebook/react/ReactFragment.java | 8 +- .../facebook/react/ReactFragmentActivity.java | 15 - .../facebook/react/ReactInstanceManager.java | 212 +- .../react/ReactInstanceManagerBuilder.java | 10 +- .../com/facebook/react/ReactNativeHost.java | 9 +- ...eactPackageTurboModuleManagerDelegate.java | 24 +- .../com/facebook/react/ReactRootView.java | 116 +- .../java/com/facebook/react/animated/BUCK | 3 +- .../react/animated/NativeAnimatedModule.java | 12 +- .../animated/NativeAnimatedNodesManager.java | 99 +- .../com/facebook/react/bridge/Arguments.java | 4 + .../main/java/com/facebook/react/bridge/BUCK | 2 + .../react/bridge/BackgroundExecutor.java | 5 +- .../facebook/react/bridge/BaseJavaModule.java | 12 +- .../react/bridge/CatalystInstanceImpl.java | 10 +- .../react/bridge/CxxModuleWrapperBase.java | 5 +- .../react/bridge/JSIModuleRegistry.java | 4 + .../react/bridge/JavaModuleWrapper.java | 37 + .../facebook/react/bridge/ModuleHolder.java | 2 +- .../facebook/react/bridge/NativeModule.java | 9 +- .../react/bridge/NativeModuleRegistry.java | 26 + .../facebook/react/bridge/ReactContext.java | 54 +- .../bridge/ReactContextBaseJavaModule.java | 5 +- .../react/bridge/ReactMarkerConstants.java | 16 +- ...ion.java => ReactSoftExceptionLogger.java} | 11 +- .../react/bridge/ReadableNativeMap.java | 54 +- .../facebook/react/bridge/SoftAssertions.java | 15 +- .../com/facebook/react/bridge/UIManager.java | 39 +- .../main/java/com/facebook/react/common/BUCK | 3 + .../react/common/build/ReactBuildConfig.java | 1 + .../com/facebook/react/common/mapbuffer/BUCK | 29 + .../common/mapbuffer/ReadableMapBuffer.java | 347 + .../mapbuffer/ReadableMapBufferSoLoader.java | 33 + .../react/common/mapbuffer/jni/Android.mk | 39 + .../facebook/react/common/mapbuffer/jni/BUCK | 34 + .../jni/react/common/mapbuffer/OnLoad.cpp | 15 + .../common/mapbuffer/ReadableMapBuffer.cpp | 76 + .../common/mapbuffer/ReadableMapBuffer.h | 51 + .../com/facebook/react/common/network/BUCK | 1 + .../main/java/com/facebook/react/config/BUCK | 4 +- .../react/config/ReactFeatureFlags.java | 88 +- .../java/com/facebook/react/devsupport/BUCK | 4 +- .../devsupport/BridgeDevSupportManager.java | 275 + .../devsupport/DevLoadingViewController.java | 4 +- .../react/devsupport/DevServerHelper.java | 77 +- .../devsupport/DevSupportManagerBase.java | 520 +- .../devsupport/DevSupportManagerFactory.java | 16 +- .../devsupport/DevSupportManagerImpl.java | 82 - .../devsupport/DisabledDevSupportManager.java | 14 +- .../react/devsupport/LogBoxModule.java | 2 +- .../react/devsupport/PackagerStatusCheck.java | 100 + ...elper.java => ReactInstanceDevHelper.java} | 5 +- .../react/devsupport/RedBoxHandler.java | 18 +- .../interfaces/BundleLoadCallback.java | 10 +- .../interfaces/DevSupportManager.java | 7 +- .../devsupport/interfaces/ErrorType.java | 23 + .../main/java/com/facebook/react/fabric/BUCK | 3 +- .../com/facebook/react/fabric/Binding.java | 11 +- .../react/fabric/FabricComponents.java | 7 +- .../react/fabric/FabricJSIModuleProvider.java | 88 +- .../react/fabric/FabricUIManager.java | 1082 +- .../react/fabric/StateWrapperImpl.java | 61 +- .../facebook/react/fabric/SurfaceHandler.java | 50 + .../react/fabric/SurfaceHandlerBinding.java | 131 + .../fabric/events/EventEmitterWrapper.java | 37 +- .../fabric/events/FabricEventEmitter.java | 34 +- .../com/facebook/react/fabric/jni/Android.mk | 9 +- .../java/com/facebook/react/fabric/jni/BUCK | 9 +- .../com/facebook/react/fabric/jni/Binding.cpp | 915 +- .../com/facebook/react/fabric/jni/Binding.h | 47 +- .../fabric/jni/CoreComponentsRegistry.cpp | 9 +- .../react/fabric/jni/EventEmitterWrapper.cpp | 24 +- .../react/fabric/jni/EventEmitterWrapper.h | 4 + .../com/facebook/react/fabric/jni/OnLoad.cpp | 2 + .../react/fabric/jni/StateWrapperImpl.cpp | 43 +- .../react/fabric/jni/StateWrapperImpl.h | 4 +- .../fabric/jni/SurfaceHandlerBinding.cpp | 122 + .../react/fabric/jni/SurfaceHandlerBinding.h | 68 + .../fabric/mounting/MountItemDispatcher.java | 406 + .../fabric/mounting/MountingManager.java | 929 +- .../mounting/SurfaceMountingManager.java | 1008 + .../mounting/mountitems/BatchMountItem.java | 117 - .../mounting/mountitems/CreateMountItem.java | 68 - .../DispatchIntCommandMountItem.java | 11 +- .../DispatchStringCommandMountItem.java | 11 +- .../mounting/mountitems/InsertMountItem.java | 47 - .../mountitems/IntBufferBatchMountItem.java | 73 +- .../fabric/mounting/mountitems/MountItem.java | 4 + .../mountitems/PreAllocateViewMountItem.java | 44 +- .../RemoveDeleteMultiMountItem.java | 90 - .../mountitems/SendAccessibilityEvent.java | 15 +- .../UpdateEventEmitterMountItem.java | 33 - .../mountitems/UpdateLayoutMountItem.java | 90 - .../mountitems/UpdatePaddingMountItem.java | 53 - .../mountitems/UpdatePropsMountItem.java | 42 - .../mountitems/UpdateStateMountItem.java | 43 - .../com/facebook/react/jscexecutor/Android.mk | 4 +- .../java/com/facebook/react/jscexecutor/BUCK | 1 + .../main/java/com/facebook/react/jstasks/BUCK | 1 + .../react/jstasks/HeadlessJsTaskContext.java | 6 +- .../facebook/react/module/annotations/BUCK | 1 + .../java/com/facebook/react/module/model/BUCK | 1 + .../AccessibilityInfoModule.java | 25 +- .../react/modules/accessibilityinfo/BUCK | 3 +- .../facebook/react/modules/appearance/BUCK | 3 +- .../facebook/react/modules/appregistry/BUCK | 1 + .../modules/appstate/AppStateModule.java | 12 +- .../com/facebook/react/modules/appstate/BUCK | 3 +- .../java/com/facebook/react/modules/blob/BUCK | 3 +- .../react/modules/blob/BlobProvider.java | 42 +- .../react/modules/blob/jni/Android.mk | 4 +- .../com/facebook/react/modules/blob/jni/BUCK | 2 +- .../react/modules/blob/jni/BlobCollector.cpp | 1 + .../facebook/react/modules/bundleloader/BUCK | 3 +- .../com/facebook/react/modules/camera/BUCK | 3 +- .../com/facebook/react/modules/clipboard/BUCK | 1 + .../com/facebook/react/modules/common/BUCK | 1 + .../java/com/facebook/react/modules/core/BUCK | 3 +- .../react/modules/core/TimingModule.java | 7 +- .../facebook/react/modules/datepicker/BUCK | 3 +- .../datepicker/DatePickerDialogModule.java | 32 +- .../modules/debug/AnimationsDebugModule.java | 2 +- .../com/facebook/react/modules/debug/BUCK | 4 +- .../facebook/react/modules/deviceinfo/BUCK | 3 +- .../modules/deviceinfo/DeviceInfoModule.java | 27 +- .../com/facebook/react/modules/dialog/BUCK | 3 +- .../react/modules/dialog/DialogModule.java | 16 +- .../com/facebook/react/modules/fabric/BUCK | 1 + .../com/facebook/react/modules/fresco/BUCK | 1 + .../react/modules/fresco/FrescoModule.java | 10 + .../facebook/react/modules/i18nmanager/BUCK | 4 +- .../i18nmanager/I18nManagerModule.java | 24 +- .../com/facebook/react/modules/image/BUCK | 3 +- .../com/facebook/react/modules/intent/BUCK | 3 +- .../com/facebook/react/modules/network/BUCK | 3 +- .../modules/network/NetworkingModule.java | 2 +- .../modules/network/OkHttpClientProvider.java | 19 +- .../facebook/react/modules/permissions/BUCK | 3 +- .../com/facebook/react/modules/share/BUCK | 3 +- .../com/facebook/react/modules/sound/BUCK | 3 +- .../com/facebook/react/modules/statusbar/BUCK | 3 +- .../modules/storage/AsyncStorageModule.java | 2 +- .../com/facebook/react/modules/storage/BUCK | 3 +- .../facebook/react/modules/systeminfo/BUCK | 6 +- .../systeminfo/ReactNativeVersion.java | 4 +- .../com/facebook/react/modules/toast/BUCK | 3 +- .../com/facebook/react/modules/vibration/BUCK | 3 +- .../com/facebook/react/modules/websocket/BUCK | 3 +- .../facebook/react/packagerconnection/BUCK | 1 + .../ReconnectingWebSocket.java | 4 +- .../com/facebook/react/reactperflogger/BUCK | 1 + .../react/reactperflogger/jni/Android.mk | 2 +- .../facebook/react/reactperflogger/jni/BUCK | 2 +- .../com/facebook/react/runtimescheduler/BUCK | 20 + .../RuntimeSchedulerManager.java | 39 + .../react/runtimescheduler/jni/Android.mk | 34 + .../facebook/react/runtimescheduler/jni/BUCK | 35 + .../react/runtimescheduler/jni/OnLoad.cpp | 15 + .../jni/RuntimeSchedulerManager.cpp | 46 + .../jni/RuntimeSchedulerManager.h | 40 + .../main/java/com/facebook/react/shell/BUCK | 2 +- .../react/shell/MainReactPackage.java | 4 - .../main/java/com/facebook/react/surface/BUCK | 1 + .../main/java/com/facebook/react/touch/BUCK | 1 + .../com/facebook/react/turbomodule/core/BUCK | 3 +- .../turbomodule/core/TurboModuleManager.java | 21 +- .../core/TurboModuleManagerDelegate.java | 3 + .../core/TurboModulePerfLogger.java | 2 + .../react/turbomodule/core/interfaces/BUCK | 1 + .../core/interfaces/TurboModule.java | 8 +- .../react/turbomodule/core/jni/Android.mk | 8 +- .../facebook/react/turbomodule/core/jni/BUCK | 5 +- .../jni/ReactCommon/TurboModuleManager.cpp | 201 +- .../core/jni/ReactCommon/TurboModuleManager.h | 19 +- .../java/com/facebook/react/uimanager/BUCK | 7 +- .../react/uimanager/BaseViewManager.java | 16 +- .../uimanager/ComponentNameResolver.java | 17 + .../ComponentNameResolverManager.java | 41 + .../react/uimanager/DisplayMetricsHolder.java | 35 +- .../uimanager/FabricViewStateManager.java | 24 +- .../react/uimanager/JSTouchDispatcher.java | 27 + .../uimanager/NativeViewHierarchyManager.java | 17 +- .../NativeViewHierarchyOptimizer.java | 23 +- .../react/uimanager/OnLayoutEvent.java | 23 +- .../facebook/react/uimanager/PixelUtil.java | 7 +- .../uimanager/ReactAccessibilityDelegate.java | 38 +- .../ReactClippingProhibitedView.java | 26 + .../ReactClippingViewGroupHelper.java | 54 +- .../react/uimanager/ReactOverflowView.java | 25 + .../facebook/react/uimanager/ReactRoot.java | 14 + .../react/uimanager/RootViewUtil.java | 18 + .../react/uimanager/StateWrapper.java | 28 +- .../react/uimanager/ThemedReactContext.java | 42 +- .../react/uimanager/TouchTargetHelper.java | 169 +- .../react/uimanager/UIImplementation.java | 51 +- .../uimanager/UIImplementationProvider.java | 48 +- .../react/uimanager/UIManagerHelper.java | 97 +- .../react/uimanager/UIManagerModule.java | 109 +- .../UIManagerModuleConstantsHelper.java | 3 +- .../react/uimanager/UIViewOperationQueue.java | 19 +- .../facebook/react/uimanager/ViewManager.java | 28 +- .../react/uimanager/ViewManagerRegistry.java | 4 +- .../react/uimanager/ViewManagerResolver.java | 26 + .../uimanager/ViewManagersPropertyCache.java | 17 +- .../facebook/react/uimanager/annotations/BUCK | 1 + .../com/facebook/react/uimanager/common/BUCK | 2 +- .../events/BlackHoleEventDispatcher.java | 3 + .../events/ContentSizeChangeEvent.java | 11 +- .../react/uimanager/events/Event.java | 140 +- .../uimanager/events/EventDispatcher.java | 3 + .../uimanager/events/EventDispatcherImpl.java | 11 +- .../events/LockFreeEventDispatcherImpl.java | 236 + .../uimanager/events/RCTEventEmitter.java | 10 + .../events/RCTModernEventEmitter.java | 32 + .../uimanager/events/ReactEventEmitter.java | 105 +- .../react/uimanager/events/TouchEvent.java | 71 +- .../react/uimanager/events/TouchesHelper.java | 11 +- .../facebook/react/uimanager/interfaces/BUCK | 21 + .../BaseViewManagerDelegate.java | 0 .../BaseViewManagerInterface.java | 0 .../uimanager/{ => interfaces}/FloatUtil.java | 0 .../uimanager/{ => interfaces}/Spacing.java | 0 .../{ => interfaces}/ViewManagerDelegate.java | 0 .../uimanager/{ => interfaces}/ViewProps.java | 12 +- .../facebook/react/uimanager/jni/Android.mk | 37 + .../com/facebook/react/uimanager/jni/BUCK | 41 + .../jni/ComponentNameResolverManager.cpp | 77 + .../jni/ComponentNameResolverManager.h | 54 + .../facebook/react/uimanager/jni/OnLoad.cpp | 16 + .../com/facebook/react/uimanager/util/BUCK | 1 + .../main/java/com/facebook/react/util/BUCK | 1 + .../ActivityIndicatorViewManagerDelegate.java | 42 - ...ActivityIndicatorViewManagerInterface.java | 20 - .../AndroidDialogPickerManagerDelegate.java | 48 - .../AndroidDialogPickerManagerInterface.java | 23 - .../AndroidDrawerLayoutManagerDelegate.java | 61 - .../AndroidDrawerLayoutManagerInterface.java | 24 - .../AndroidDropdownPickerManagerDelegate.java | 48 - ...AndroidDropdownPickerManagerInterface.java | 22 - .../AndroidProgressBarManagerDelegate.java | 51 - .../AndroidProgressBarManagerInterface.java | 23 - ...roidSwipeRefreshLayoutManagerDelegate.java | 58 - ...oidSwipeRefreshLayoutManagerInterface.java | 24 - .../AndroidSwitchManagerDelegate.java | 67 - .../AndroidSwitchManagerInterface.java | 26 - .../java/com/facebook/react/viewmanagers/BUCK | 1 + .../MaskedViewManagerDelegate.java | 26 - .../MaskedViewManagerInterface.java | 16 - .../ModalHostViewManagerDelegate.java | 54 - .../ModalHostViewManagerInterface.java | 25 - .../ProgressViewManagerDelegate.java | 49 - .../ProgressViewManagerInterface.java | 23 - .../SafeAreaViewManagerDelegate.java | 32 - .../SafeAreaViewManagerInterface.java | 16 - .../SegmentedControlManagerDelegate.java | 52 - .../SegmentedControlManagerInterface.java | 24 - .../viewmanagers/SliderManagerDelegate.java | 73 - .../viewmanagers/SliderManagerInterface.java | 31 - ...nimplementedNativeViewManagerDelegate.java | 32 - ...implementedNativeViewManagerInterface.java | 17 - .../react/viewmanagers/jni/Android.mk | 29 - .../components/rncore/ComponentDescriptors.h | 31 - .../components/rncore/EventEmitters.cpp | 141 - .../components/rncore/EventEmitters.h | 223 - .../renderer/components/rncore/Props.cpp | 191 - .../react/renderer/components/rncore/Props.h | 529 - .../components/rncore/ShadowNodes.cpp | 28 - .../renderer/components/rncore/ShadowNodes.h | 117 - .../java/com/facebook/react/views/common/BUCK | 1 + .../java/com/facebook/react/views/drawer/BUCK | 5 +- .../drawer/ReactDrawerLayoutManager.java | 25 +- .../drawer/events/DrawerClosedEvent.java | 19 +- .../drawer/events/DrawerOpenedEvent.java | 19 +- .../views/drawer/events/DrawerSlideEvent.java | 20 +- .../events/DrawerStateChangedEvent.java | 20 +- .../java/com/facebook/react/views/image/BUCK | 2 + .../react/views/image/ImageLoadEvent.java | 64 +- .../image/ReactCallerContextFactory.java | 4 +- .../react/views/image/ReactImageManager.java | 19 +- .../react/views/image/ReactImageView.java | 101 +- .../com/facebook/react/views/imagehelper/BUCK | 2 + .../react/views/imagehelper/ImageSource.java | 17 + .../java/com/facebook/react/views/modal/BUCK | 6 +- .../views/modal/ReactModalHostManager.java | 16 +- .../react/views/modal/ReactModalHostView.java | 55 +- .../react/views/modal/RequestCloseEvent.java | 16 +- .../facebook/react/views/modal/ShowEvent.java | 16 +- .../java/com/facebook/react/views/picker/BUCK | 29 - .../picker/ReactDialogPickerManager.java | 51 - .../picker/ReactDropdownPickerManager.java | 50 - .../react/views/picker/ReactPicker.java | 196 - .../views/picker/ReactPickerAdapter.java | 95 - .../react/views/picker/ReactPickerItem.java | 43 - .../views/picker/ReactPickerManager.java | 97 - .../picker/events/PickerItemSelectEvent.java | 40 - .../com/facebook/react/views/progressbar/BUCK | 5 +- .../java/com/facebook/react/views/scroll/BUCK | 2 + .../ReactHorizontalScrollContainerView.java | 35 +- .../scroll/ReactHorizontalScrollView.java | 213 +- .../ReactHorizontalScrollViewManager.java | 13 +- .../react/views/scroll/ReactScrollView.java | 126 +- .../views/scroll/ReactScrollViewHelper.java | 23 +- .../views/scroll/ReactScrollViewManager.java | 15 +- .../react/views/scroll/ScrollEvent.java | 55 +- .../java/com/facebook/react/views/slider/BUCK | 5 +- .../react/views/slider/ReactSliderEvent.java | 5 - .../views/slider/ReactSliderManager.java | 49 +- .../slider/ReactSlidingCompleteEvent.java | 29 +- .../facebook/react/views/swiperefresh/BUCK | 5 +- .../views/swiperefresh/RefreshEvent.java | 16 +- .../SwipeRefreshLayoutManager.java | 25 +- .../com/facebook/react/views/switchview/BUCK | 5 +- .../react/views/switchview/ReactSwitch.java | 13 + .../views/switchview/ReactSwitchEvent.java | 22 +- .../views/switchview/ReactSwitchManager.java | 16 +- .../java/com/facebook/react/views/text/BUCK | 2 + .../react/views/text/CustomStyleSpan.java | 14 +- .../views/text/ReactBaseTextShadowNode.java | 15 +- .../react/views/text/ReactClickableSpan.java | 3 +- .../react/views/text/ReactFontManager.java | 103 +- .../react/views/text/ReactTextShadowNode.java | 20 +- .../react/views/text/ReactTextView.java | 11 + .../views/text/ReactTextViewManager.java | 49 +- .../react/views/text/ReactTypefaceUtils.java | 100 +- .../react/views/text/TextAttributeProps.java | 354 +- .../react/views/text/TextLayoutManager.java | 84 +- .../text/TextLayoutManagerMapBuffer.java | 596 + .../react/views/text/TypefaceStyle.java | 72 + .../react/views/text/frescosupport/BUCK | 1 + .../com/facebook/react/views/textinput/BUCK | 2 + .../ReactContentSizeChangedEvent.java | 17 +- .../react/views/textinput/ReactEditText.java | 59 +- .../ReactEditTextInputConnectionWrapper.java | 11 +- .../textinput/ReactTextChangedEvent.java | 16 +- .../textinput/ReactTextInputBlurEvent.java | 16 +- .../ReactTextInputEndEditingEvent.java | 16 +- .../views/textinput/ReactTextInputEvent.java | 17 +- .../textinput/ReactTextInputFocusEvent.java | 26 +- .../ReactTextInputKeyPressEvent.java | 29 +- .../textinput/ReactTextInputManager.java | 227 +- .../ReactTextInputSelectionEvent.java | 17 +- .../ReactTextInputSubmitEditingEvent.java | 26 +- .../react/views/unimplementedview/BUCK | 1 + .../java/com/facebook/react/views/view/BUCK | 1 + .../react/views/view/ReactDrawableHelper.java | 6 +- .../view/ReactViewBackgroundDrawable.java | 47 +- .../react/views/view/ReactViewGroup.java | 128 +- .../react/views/view/ReactViewManager.java | 4 +- .../react/views/view/ViewGroupClickEvent.java | 15 +- .../src/main/java/com/facebook/systrace/BUCK | 1 + .../main/java/com/facebook/yoga/YogaNode.java | 20 +- .../com/facebook/yoga/YogaNodeJNIBase.java | 26 +- .../java/com/facebook/yoga/YogaProps.java | 151 + ReactAndroid/src/main/jni/first-party/fb/BUCK | 4 + .../jni/first-party/fb/include/fb/RefPtr.h | 2 +- .../fb/include/fb/StaticInitialized.h | 2 +- .../first-party/yogajni/jni/YGJNIVanilla.cpp | 9 +- .../first-party/yogajni/jni/YGJTypesVanilla.h | 12 +- .../src/main/jni/react/jni/Android.mk | 12 +- ReactAndroid/src/main/jni/react/jni/BUCK | 5 +- .../jni/react/jni/CatalystInstanceImpl.cpp | 57 +- .../main/jni/react/jni/CatalystInstanceImpl.h | 4 + .../react/jni/JReactSoftExceptionLogger.cpp | 21 + .../jni/react/jni/JReactSoftExceptionLogger.h | 28 + .../src/main/jni/react/jni/JSLoader.cpp | 2 +- .../main/jni/react/jni/JavaModuleWrapper.cpp | 94 - .../main/jni/react/jni/JavaModuleWrapper.h | 30 - .../src/main/jni/react/jni/ProxyExecutor.h | 1 + .../main/jni/react/jni/ReadableNativeMap.cpp | 13 +- .../src/main/jni/third-party/boost/Android.mk | 9 +- .../boost/asm/arm/jump_arm_aapcs_elf_gas.S | 86 + .../boost/asm/arm/make_arm_aapcs_elf_gas.S | 79 + .../boost/asm/arm/ontop_arm_aapcs_elf_gas.S | 91 + .../asm/arm64/jump_arm64_aapcs_elf_gas.S | 114 + .../asm/arm64/make_arm64_aapcs_elf_gas.S | 85 + .../asm/arm64/ontop_arm64_aapcs_elf_gas.S | 113 + .../boost/asm/x86/jump_i386_sysv_elf_gas.S | 78 + .../boost/asm/x86/make_i386_sysv_elf_gas.S | 106 + .../boost/asm/x86/ontop_i386_sysv_elf_gas.S | 85 + .../asm/x86_64/jump_x86_64_sysv_elf_gas.S | 76 + .../asm/x86_64/make_x86_64_sysv_elf_gas.S | 81 + .../asm/x86_64/ontop_x86_64_sysv_elf_gas.S | 79 + .../src/main/jni/third-party/fmt/Android.mk | 15 + .../src/main/jni/third-party/folly/Android.mk | 52 +- .../main/jni/third-party/libevent/Android.mk | 36 + .../third-party/libevent/evconfig-private.h | 49 + .../jni/third-party/libevent/event-config.h | 340 + .../java/com/facebook/common/logging/BUCK | 1 + ReactAndroid/src/main/libraries/fbjni/BUCK | 4 +- .../libraries/fresco/fresco-react-native/BUCK | 107 +- .../soloader/java/com/facebook/soloader/BUCK | 10 +- .../main/res/devsupport/values/strings.xml | 3 +- .../uimanager/values/strings_unlocalized.xml | 12 +- .../main/third-party/android/androidx/BUCK | 61 + .../main/third-party/android/support/v4/BUCK | 685 - .../android/support/v7/appcompat/BUCK | 62 - .../support/v7/appcompat/aar-unpacker.py | 20 - .../src/main/third-party/java/asm/BUCK | 1 + .../src/main/third-party/java/fest/BUCK | 1 + .../third-party/java/infer-annotations/BUCK | 4 +- .../src/main/third-party/java/junit/BUCK | 1 + .../src/main/third-party/java/mockito/BUCK | 1 + .../src/main/third-party/java/mockito2/BUCK | 1 + .../src/main/third-party/java/okhttp/BUCK | 38 +- .../src/main/third-party/java/okio/BUCK | 20 +- .../java/robolectric/{4.4 => }/BUCK | 1 + .../src/main/third-party/java/sqlite/BUCK | 1 + .../third-party/java/testing-support-lib/BUCK | 31 - ReactAndroid/src/main/third-party/kotlin/BUCK | 91 + .../java/com/facebook/common/logging/BUCK | 1 + .../java/com/facebook/react/RootViewTest.java | 11 +- .../NativeAnimatedNodeTraversalTest.java | 2 +- .../test/java/com/facebook/react/bridge/BUCK | 3 +- .../react/bridge/ReactTestHelper.java | 1 + .../JSDebuggerWebSocketClientTest.java | 4 +- .../test/java/com/facebook/react/modules/BUCK | 1 + .../deviceinfo/DeviceInfoModuleTest.java | 168 + .../modules/dialog/DialogModuleTest.java | 2 +- .../modules/network/NetworkingModuleTest.java | 20 +- .../modules/timing/TimingModuleTest.java | 2 +- .../react/uimanager/BaseViewManagerTest.java | 32 + .../uimanager/SimpleViewPropertyTest.java | 10 +- .../views/image/ReactImagePropertyTest.java | 8 + .../textinput/ReactTextInputPropertyTest.java | 4 + .../test/java/org/mockito/configuration/BUCK | 1 + ReactCommon/React-Fabric.podspec | 240 +- ReactCommon/ReactCommon.podspec | 13 +- ReactCommon/better/Android.mk | 2 +- ReactCommon/better/BUCK | 4 +- ReactCommon/callinvoker/Android.mk | 2 +- ReactCommon/callinvoker/BUCK | 2 +- .../callinvoker/React-callinvoker.podspec | 6 +- ReactCommon/cxxreact/Android.mk | 3 +- ReactCommon/cxxreact/BUCK | 6 +- ReactCommon/cxxreact/CxxNativeModule.cpp | 28 + ReactCommon/cxxreact/CxxNativeModule.h | 9 + ReactCommon/cxxreact/Instance.cpp | 34 +- ReactCommon/cxxreact/Instance.h | 1 + ReactCommon/cxxreact/JSBundleType.cpp | 5 + ReactCommon/cxxreact/JSBundleType.h | 1 + ReactCommon/cxxreact/JsArgumentHelpers-inl.h | 6 +- ReactCommon/cxxreact/JsArgumentHelpers.h | 4 +- ReactCommon/cxxreact/MethodCall.cpp | 4 +- ReactCommon/cxxreact/ModuleRegistry.cpp | 5 + ReactCommon/cxxreact/NativeToJsBridge.cpp | 21 - ReactCommon/cxxreact/NativeToJsBridge.h | 6 - ReactCommon/cxxreact/React-cxxreact.podspec | 11 +- ReactCommon/cxxreact/ReactNativeVersion.h | 4 +- ReactCommon/cxxreact/SystraceSection.h | 4 +- ReactCommon/cxxreact/re_worker_requirements | 6 - ReactCommon/hermes/React-hermes.podspec | 53 + ReactCommon/hermes/executor/Android.mk | 8 +- ReactCommon/hermes/inspector/Android.mk | 3 +- ReactCommon/hermes/inspector/BUCK | 13 +- ReactCommon/hermes/inspector/Inspector.cpp | 5 +- ReactCommon/hermes/inspector/Inspector.h | 11 +- .../hermes/inspector/InspectorState.cpp | 14 +- .../hermes/inspector/chrome/Connection.cpp | 115 + .../hermes/inspector/chrome/MessageTypes.cpp | 216 +- .../hermes/inspector/chrome/MessageTypes.h | 116 +- .../hermes/inspector/chrome/cli/main.cpp | 11 +- .../chrome/tests/ConnectionTests.cpp | 144 + .../hermes/inspector/tools/message_types.txt | 4 + .../tools/msggen/__tests__/CommandTest.js | 4 +- .../tools/msggen/__tests__/EventTest.js | 4 +- .../tools/msggen/__tests__/GraphTest.js | 4 +- .../msggen/__tests__/HeaderWriterTest.js | 4 +- .../__tests__/ImplementationWriterTest.js | 4 +- .../tools/msggen/__tests__/PropertyTest.js | 4 +- .../tools/msggen/__tests__/TypeTest.js | 4 +- .../inspector/tools/msggen/package.json | 2 +- .../inspector/tools/msggen/src/Command.js | 2 - .../inspector/tools/msggen/src/Converters.js | 2 - .../inspector/tools/msggen/src/Event.js | 2 - .../inspector/tools/msggen/src/Graph.js | 2 - .../tools/msggen/src/HeaderWriter.js | 2 - .../tools/msggen/src/ImplementationWriter.js | 2 - .../inspector/tools/msggen/src/Property.js | 3 +- .../inspector/tools/msggen/src/TestHelpers.js | 4 +- .../hermes/inspector/tools/msggen/src/Type.js | 2 - .../inspector/tools/msggen/src/index.js | 4 +- .../hermes/inspector/tools/msggen/yarn.lock | 3642 ++-- ReactCommon/jsi/Android.mk | 8 +- ReactCommon/jsi/BUCK | 6 +- ReactCommon/jsi/JSCRuntime.cpp | 7 + ReactCommon/jsi/React-jsi.podspec | 10 +- ReactCommon/jsi/jsi/CMakeLists.txt | 2 +- ReactCommon/jsi/jsi/decorator.h | 15 + ReactCommon/jsi/jsi/instrumentation.h | 13 + ReactCommon/jsi/jsi/jsi.cpp | 3 + ReactCommon/jsi/jsi/jsi.h | 35 +- ReactCommon/jsi/jsi/jsilib-posix.cpp | 12 +- ReactCommon/jsi/jsi/test/testlib.cpp | 1 + ReactCommon/jsiexecutor/Android.mk | 4 +- .../jsiexecutor/React-jsiexecutor.podspec | 8 +- .../jsiexecutor/jsireact/JSIExecutor.cpp | 39 +- .../jsiexecutor/jsireact/JSINativeModules.cpp | 2 + ReactCommon/jsinspector/BUCK | 2 + .../jsinspector/React-jsinspector.podspec | 4 +- .../src/test/java/com/facebook/powermock/BUCK | 2 + ReactCommon/logger/Android.mk | 23 + ReactCommon/logger/BUCK | 43 + ReactCommon/logger/React-logger.podspec | 40 + ReactCommon/logger/react_native_log.cpp | 52 + ReactCommon/logger/react_native_log.h | 33 + ReactCommon/react/config/Android.mk | 2 +- ReactCommon/react/config/BUCK | 2 +- ReactCommon/react/debug/Android.mk | 31 + ReactCommon/react/debug/BUCK | 69 + ReactCommon/react/debug/flags.h | 19 + .../react/debug/react_native_assert.cpp | 45 + ReactCommon/react/debug/react_native_assert.h | 64 + .../react/nativemodule/core/Android.mk | 6 +- ReactCommon/react/nativemodule/core/BUCK | 7 +- .../core/ReactCommon/LongLivedObject.cpp | 1 + .../core/ReactCommon/LongLivedObject.h | 5 +- .../core/ReactCommon/TurboModule.cpp | 2 +- .../core/ReactCommon/TurboModule.h | 4 +- .../core/ReactCommon/TurboModuleBinding.cpp | 57 +- .../core/ReactCommon/TurboModuleBinding.h | 14 +- .../core/ReactCommon/TurboModuleUtils.h | 57 +- .../android/ReactCommon/JavaTurboModule.cpp | 228 +- .../android/ReactCommon/JavaTurboModule.h | 20 +- .../core/platform/ios/RCTBlockGuard.h | 24 + .../core/platform/ios/RCTBlockGuard.mm | 28 + .../core/platform/ios/RCTTurboModule.h | 22 +- .../core/platform/ios/RCTTurboModule.mm | 145 +- .../core/platform/ios/RCTTurboModuleManager.h | 6 - .../platform/ios/RCTTurboModuleManager.mm | 217 +- ReactCommon/react/nativemodule/samples/BUCK | 12 +- .../samples/platform/android/Android.mk | 4 +- .../android/NativeSampleTurboModuleSpec.java | 3 + .../platform/android/SampleTurboModule.java | 10 + .../ios/RCTNativeSampleTurboModuleSpec.h | 1 + .../ios/RCTNativeSampleTurboModuleSpec.mm | 11 + .../platform/ios/RCTSampleTurboCxxModule.mm | 12 + .../platform/ios/RCTSampleTurboModule.mm | 8 +- .../ios/SampleTurboCxxModuleLegacyImpl.cpp | 11 + .../ios/SampleTurboCxxModuleLegacyImpl.h | 1 + .../react/renderer/animations/Android.mk | 5 +- ReactCommon/react/renderer/animations/BUCK | 8 +- .../animations/LayoutAnimationDriver.cpp | 149 +- .../animations/LayoutAnimationDriver.h | 5 +- .../LayoutAnimationKeyFrameManager.cpp | 1066 +- .../LayoutAnimationKeyFrameManager.h | 133 +- .../animations/tests/LayoutAnimationTest.cpp | 544 + .../renderer/attributedstring/Android.mk | 6 +- .../attributedstring/AttributedStringBox.cpp | 34 +- .../attributedstring/AttributedStringBox.h | 4 +- .../react/renderer/attributedstring/BUCK | 13 +- .../attributedstring/TextAttributes.cpp | 9 +- .../attributedstring/TextAttributes.h | 2 + .../renderer/attributedstring/conversions.h | 974 +- .../renderer/attributedstring/primitives.h | 16 + .../tests/AttributedStringBoxTest.cpp | 105 + .../tests/AttributedStringTest.cpp | 37 +- .../tests/ParagraphAttributesTest.cpp | 19 +- .../tests/TextAttributesTest.cpp | 28 +- .../renderer/componentregistry/Android.mk | 5 +- .../react/renderer/componentregistry/BUCK | 9 +- .../ComponentDescriptorProvider.h | 9 +- .../ComponentDescriptorProviderRegistry.cpp | 4 +- .../ComponentDescriptorProviderRegistry.h | 1 + .../ComponentDescriptorRegistry.cpp | 90 +- .../ComponentDescriptorRegistry.h | 5 +- .../componentNameByReactViewName.cpp | 73 + .../componentNameByReactViewName.h} | 9 +- .../componentregistry/native/Android.mk | 29 + .../renderer/componentregistry/native/BUCK | 58 + .../native/NativeComponentRegistryBinding.cpp | 68 + .../native/NativeComponentRegistryBinding.h | 61 + .../renderer/components/image/Android.mk | 8 +- .../react/renderer/components/image/BUCK | 10 +- .../image/ImageComponentDescriptor.h | 5 +- .../renderer/components/image/ImageProps.cpp | 37 +- .../renderer/components/image/ImageProps.h | 6 +- .../components/image/ImageShadowNode.cpp | 10 +- .../renderer/components/image/ImageState.h | 10 +- .../renderer/components/image/conversions.h | 47 +- .../renderer/components/inputaccessory/BUCK | 7 +- .../InputAccessoryComponentDescriptor.h | 8 +- .../components/legacyviewmanagerinterop/BUCK | 6 +- ...acyViewManagerInteropComponentDescriptor.h | 2 +- ...cyViewManagerInteropComponentDescriptor.mm | 21 +- .../LegacyViewManagerInteropViewProps.cpp | 7 +- .../LegacyViewManagerInteropViewProps.h | 2 + .../RCTLegacyViewManagerInteropCoordinator.h | 2 +- .../RCTLegacyViewManagerInteropCoordinator.mm | 89 +- .../renderer/components/modal/Android.mk | 7 +- .../react/renderer/components/modal/BUCK | 8 +- .../modal/ModalHostViewComponentDescriptor.h | 8 +- .../components/modal/ModalHostViewState.h | 11 +- .../renderer/components/picker/Android.mk | 37 - .../AndroidDialogPickerEventEmitter.cpp | 23 - .../AndroidDialogPickerEventEmitter.h | 27 - .../AndroidDialogPickerProps.cpp | 28 - .../androidpicker/AndroidDialogPickerProps.h | 77 - .../AndroidDialogPickerShadowNode.cpp | 16 - .../AndroidDialogPickerShadowNode.h | 29 - .../AndroidDropdownPickerEventEmitter.cpp | 23 - .../AndroidDropdownPickerEventEmitter.h | 27 - .../AndroidDropdownPickerProps.cpp | 28 - .../AndroidDropdownPickerProps.h | 77 - .../AndroidDropdownPickerShadowNode.cpp | 17 - .../AndroidDropdownPickerShadowNode.h | 29 - .../iospicker/PickerComponentDescriptor.h | 26 - .../picker/iospicker/PickerEventEmitter.cpp | 23 - .../picker/iospicker/PickerEventEmitter.h | 28 - .../picker/iospicker/PickerProps.cpp | 46 - .../components/picker/iospicker/PickerProps.h | 36 - .../picker/iospicker/PickerShadowNode.h | 33 - .../components/picker/iospicker/conversions.h | 47 - .../components/picker/iospicker/primitives.h | 29 - .../components/progressbar/Android.mk | 6 +- .../renderer/components/progressbar/BUCK | 7 +- .../AndroidProgressBarComponentDescriptor.h | 6 +- .../react/renderer/components/root/Android.mk | 7 +- .../react/renderer/components/root/BUCK | 7 +- .../renderer/components/root/RootProps.cpp | 14 +- .../renderer/components/root/RootProps.h | 7 +- .../components/root/RootShadowNode.cpp | 8 +- .../renderer/components/root/RootShadowNode.h | 2 + .../root/tests/RootShadowNodeTest.cpp | 38 +- .../renderer/components/safeareaview/BUCK | 7 +- .../SafeAreaViewComponentDescriptor.h | 8 +- .../safeareaview/SafeAreaViewShadowNode.h | 7 + .../safeareaview/SafeAreaViewState.h | 4 +- .../renderer/components/scrollview/Android.mk | 8 +- .../react/renderer/components/scrollview/BUCK | 9 +- .../scrollview/RCTComponentViewHelpers.h | 38 + .../components/scrollview/ScrollViewProps.cpp | 65 +- .../components/scrollview/ScrollViewProps.h | 15 +- .../scrollview/ScrollViewShadowNode.cpp | 25 +- .../scrollview/ScrollViewShadowNode.h | 1 + .../components/scrollview/ScrollViewState.cpp | 2 +- .../components/scrollview/ScrollViewState.h | 19 +- .../components/scrollview/conversions.h | 5 + .../renderer/components/slider/Android.mk | 7 +- .../react/renderer/components/slider/BUCK | 8 +- .../slider/SliderComponentDescriptor.h | 6 +- .../components/slider/SliderShadowNode.h | 17 +- .../renderer/components/slider/SliderState.h | 8 + .../ios/SliderMeasurementsManager.cpp | 4 +- .../renderer/components/switch/Android.mk | 6 +- .../react/renderer/components/switch/BUCK | 6 +- .../AndroidSwitchComponentDescriptor.h | 6 +- .../react/renderer/components/text/Android.mk | 8 +- .../react/renderer/components/text/BUCK | 14 +- .../components/text/BaseTextProps.cpp | 32 + .../renderer/components/text/BaseTextProps.h | 6 +- .../components/text/BaseTextShadowNode.cpp | 5 +- .../text/ParagraphComponentDescriptor.h | 15 +- .../components/text/ParagraphProps.cpp | 21 +- .../renderer/components/text/ParagraphProps.h | 6 +- .../components/text/ParagraphShadowNode.cpp | 32 +- .../components/text/ParagraphShadowNode.h | 13 +- .../components/text/ParagraphState.cpp | 4 + .../renderer/components/text/ParagraphState.h | 11 +- .../renderer/components/text/RawTextProps.cpp | 5 +- .../renderer/components/text/RawTextProps.h | 6 +- .../components/text/RawTextShadowNode.h | 38 +- .../renderer/components/text/TextProps.cpp | 9 +- .../renderer/components/text/TextProps.h | 6 +- .../renderer/components/text/TextShadowNode.h | 23 + .../renderer/components/text/conversions.h | 22 + .../text/tests/ParagraphLocalDataTest.cpp | 13 +- .../renderer/components/textinput/Android.mk | 8 +- .../react/renderer/components/textinput/BUCK | 12 +- .../AndroidTextInputComponentDescriptor.h | 13 +- .../AndroidTextInputProps.cpp | 149 +- .../androidtextinput/AndroidTextInputProps.h | 16 +- .../AndroidTextInputShadowNode.cpp | 31 +- .../AndroidTextInputShadowNode.h | 10 +- .../AndroidTextInputState.cpp | 3 - .../androidtextinput/AndroidTextInputState.h | 13 +- .../components/textinput/iostextinput/BUCK | 9 +- .../TextInputComponentDescriptor.h | 8 +- .../textinput/iostextinput/TextInputProps.cpp | 68 +- .../textinput/iostextinput/TextInputProps.h | 11 +- .../iostextinput/TextInputShadowNode.cpp | 5 +- .../iostextinput/TextInputShadowNode.h | 13 +- .../textinput/iostextinput/TextInputState.h | 2 + .../textinput/iostextinput/conversions.h | 26 +- .../textinput/iostextinput/primitives.h | 6 + .../textinput/iostextinput/propsConversions.h | 65 +- .../components/unimplementedview/Android.mk | 7 +- .../components/unimplementedview/BUCK | 7 +- .../UnimplementedViewComponentDescriptor.cpp | 11 +- .../UnimplementedViewComponentDescriptor.h | 7 +- .../UnimplementedViewProps.h | 1 + .../components/view/AccessibilityPrimitives.h | 28 + .../components/view/AccessibilityProps.cpp | 25 +- .../components/view/AccessibilityProps.h | 5 +- .../react/renderer/components/view/Android.mk | 8 +- .../react/renderer/components/view/BUCK | 8 +- .../react/renderer/components/view/Touch.h | 33 +- .../renderer/components/view/TouchEvent.h | 2 - .../components/view/TouchEventEmitter.cpp | 40 +- .../components/view/TouchEventEmitter.h | 3 +- .../components/view/ViewComponentDescriptor.h | 11 +- .../components/view/ViewEventEmitter.cpp | 82 +- .../components/view/ViewEventEmitter.h | 32 +- .../renderer/components/view/ViewProps.cpp | 76 +- .../renderer/components/view/ViewProps.h | 8 +- .../components/view/ViewPropsInterpolation.h | 12 +- .../components/view/ViewShadowNode.cpp | 21 +- .../view/YogaLayoutableShadowNode.cpp | 264 +- .../view/YogaLayoutableShadowNode.h | 13 +- .../components/view/YogaStylableProps.cpp | 5 +- .../components/view/YogaStylableProps.h | 2 + .../view/accessibilityPropsConversions.h | 119 +- .../renderer/components/view/conversions.h | 146 +- .../renderer/components/view/primitives.h | 9 +- .../components/view/propsConversions.h | 191 +- .../components/view/tests/ViewTest.cpp | 20 +- ReactCommon/react/renderer/core/Android.mk | 6 +- ReactCommon/react/renderer/core/BUCK | 11 +- .../react/renderer/core/BatchedEventQueue.cpp | 26 +- .../react/renderer/core/BatchedEventQueue.h | 12 +- .../react/renderer/core/ComponentDescriptor.h | 9 +- .../core/ConcreteComponentDescriptor.h | 45 +- .../react/renderer/core/ConcreteShadowNode.h | 17 +- .../react/renderer/core/ConcreteState.h | 65 +- .../react/renderer/core/ConcreteStateTeller.h | 152 - ReactCommon/react/renderer/core/Constants.cpp | 24 + .../Constants.h} | 14 +- .../renderer/core/DynamicPropsUtilities.cpp | 35 + .../DynamicPropsUtilities.h} | 9 +- .../react/renderer/core/EventDispatcher.cpp | 24 +- .../react/renderer/core/EventDispatcher.h | 15 +- .../react/renderer/core/EventEmitter.cpp | 34 +- .../react/renderer/core/EventEmitter.h | 9 +- ReactCommon/react/renderer/core/EventPipe.h | 2 + .../react/renderer/core/EventPriority.h | 2 +- .../react/renderer/core/EventQueue.cpp | 79 +- ReactCommon/react/renderer/core/EventQueue.h | 24 +- .../renderer/core/EventQueueProcessor.cpp | 82 + .../react/renderer/core/EventQueueProcessor.h | 36 + .../react/renderer/core/EventTarget.cpp | 6 +- .../react/renderer/core/LayoutConstraints.h | 11 +- .../react/renderer/core/LayoutMetrics.cpp | 65 + .../react/renderer/core/LayoutMetrics.h | 42 +- .../react/renderer/core/LayoutPrimitives.h | 20 +- .../renderer/core/LayoutableShadowNode.cpp | 9 +- .../renderer/core/LayoutableShadowNode.h | 24 +- ReactCommon/react/renderer/core/Props.cpp | 12 +- ReactCommon/react/renderer/core/Props.h | 6 +- .../react/renderer/core/PropsParserContext.h | 28 + ReactCommon/react/renderer/core/RawEvent.cpp | 6 +- ReactCommon/react/renderer/core/RawEvent.h | 43 +- ReactCommon/react/renderer/core/RawProps.cpp | 8 +- ReactCommon/react/renderer/core/RawProps.h | 4 +- .../react/renderer/core/RawPropsKey.cpp | 17 +- .../react/renderer/core/RawPropsKeyMap.cpp | 14 +- .../react/renderer/core/RawPropsParser.cpp | 17 +- .../react/renderer/core/RawPropsParser.h | 17 +- ReactCommon/react/renderer/core/RawValue.h | 16 +- .../react/renderer/core/ReactEventPriority.h | 43 + .../react/renderer/core/ReactPrimitives.h | 34 + ReactCommon/react/renderer/core/Sealable.cpp | 7 +- ReactCommon/react/renderer/core/Sealable.h | 6 +- .../react/renderer/core/ShadowNode.cpp | 58 +- ReactCommon/react/renderer/core/ShadowNode.h | 18 +- .../react/renderer/core/ShadowNodeFamily.cpp | 3 +- .../react/renderer/core/ShadowNodeFamily.h | 2 +- .../react/renderer/core/ShadowNodeTraits.h | 37 +- ReactCommon/react/renderer/core/State.h | 7 +- ReactCommon/react/renderer/core/StateData.h | 3 + ReactCommon/react/renderer/core/StateUpdate.h | 2 - .../renderer/core/UnbatchedEventQueue.cpp | 2 - ReactCommon/react/renderer/core/conversions.h | 11 + .../react/renderer/core/propsConversions.h | 28 +- .../core/tests/ComponentDescriptorTest.cpp | 20 +- .../core/tests/ConcreteShadowNodeTest.cpp | 2 +- .../core/tests/DynamicPropsUtilitiesTest.cpp | 66 + .../core/tests/EventQueueProcessorTest.cpp | 134 + .../core/tests/LayoutableShadowNodeTest.cpp | 33 +- .../renderer/core/tests/RawPropsTest.cpp | 129 +- .../react/renderer/core/tests/TestComponent.h | 18 +- .../renderer/core/tests/traitCastTest.cpp | 31 + ReactCommon/react/renderer/debug/Android.mk | 2 +- ReactCommon/react/renderer/debug/BUCK | 10 +- .../renderer/debug/DebugStringConvertible.h | 36 +- .../react/renderer/debug/SystraceSection.h | 4 +- ReactCommon/react/renderer/debug/flags.h | 50 + ReactCommon/react/renderer/element/BUCK | 6 +- .../renderer/element/ComponentBuilder.cpp | 7 +- .../react/renderer/graphics/Android.mk | 8 +- ReactCommon/react/renderer/graphics/BUCK | 20 +- .../renderer/graphics/React-graphics.podspec | 19 +- ReactCommon/react/renderer/graphics/Rect.h | 7 +- .../renderer/graphics/RectangleCorners.h | 4 +- .../react/renderer/graphics/RectangleEdges.h | 29 +- .../react/renderer/graphics/Transform.cpp | 7 +- .../react/renderer/graphics/conversions.h | 146 +- .../renderer/graphics/PlatformColorParser.h | 67 + .../cxx/react/renderer/graphics/Color.cpp | 29 +- .../cxx/react/renderer/graphics/Color.h | 2 + .../renderer/graphics/PlatformColorParser.h | 29 + .../renderer/graphics/platform/ios/Color.cpp | 29 +- .../renderer/graphics/platform/ios/Color.h | 45 +- .../platform/ios/PlatformColorParser.h | 34 + .../platform/ios/RCTPlatformColorUtils.h | 12 + .../platform/ios/RCTPlatformColorUtils.mm | 206 + .../react/renderer/graphics/rounding.h | 15 +- .../renderer/graphics/tests/TransformTest.cpp | 1 + .../react/renderer/imagemanager/Android.mk | 5 +- ReactCommon/react/renderer/imagemanager/BUCK | 9 +- .../renderer/imagemanager/ImageRequest.h | 4 +- .../ImageResponseObserverCoordinator.cpp | 9 +- .../renderer/imagemanager/ImageTelemetry.cpp | 6 - .../renderer/imagemanager/ImageTelemetry.h | 15 +- .../platform/ios/ImageRequest.cpp | 7 +- .../platform/ios/RCTImageManager.mm | 1 - .../ios/RCTImagePrimitivesConversions.h | 14 +- .../platform/ios/RCTSyncImageManager.mm | 2 +- .../react/renderer/leakchecker/Android.mk | 29 + .../picker/iospicker => leakchecker}/BUCK | 20 +- .../renderer/leakchecker/LeakChecker.cpp | 60 + .../react/renderer/leakchecker/LeakChecker.h | 39 + .../leakchecker/WeakFamilyRegistry.cpp | 37 + .../renderer/leakchecker/WeakFamilyRegistry.h | 39 + .../react/renderer/mapbuffer/Android.mk | 15 +- ReactCommon/react/renderer/mapbuffer/BUCK | 22 +- .../react/renderer/mapbuffer/MapBuffer.cpp | 135 +- .../react/renderer/mapbuffer/MapBuffer.h | 44 +- .../renderer/mapbuffer/MapBufferBuilder.cpp | 226 + .../renderer/mapbuffer/MapBufferBuilder.h | 94 + .../react/renderer/mapbuffer/primitives.h | 91 + .../mapbuffer/tests/MapBufferTest.cpp | 146 +- .../react/renderer/mounting/Android.mk | 6 +- ReactCommon/react/renderer/mounting/BUCK | 9 +- .../renderer/mounting/Differentiator.cpp | 1807 +- .../react/renderer/mounting/Differentiator.h | 50 +- .../renderer/mounting/MountingCoordinator.cpp | 32 +- .../renderer/mounting/MountingCoordinator.h | 18 +- .../renderer/mounting/MountingTransaction.h | 4 +- .../mounting/MountingTransactionMetadata.h | 2 +- .../react/renderer/mounting/ShadowTree.cpp | 97 +- .../react/renderer/mounting/ShadowTree.h | 53 +- .../renderer/mounting/ShadowTreeDelegate.h | 11 + .../renderer/mounting/ShadowTreeRegistry.cpp | 4 +- .../renderer/mounting/ShadowTreeRevision.h | 2 +- .../react/renderer/mounting/ShadowView.cpp | 20 +- .../react/renderer/mounting/ShadowView.h | 48 +- .../renderer/mounting/ShadowViewMutation.cpp | 24 +- .../renderer/mounting/ShadowViewMutation.h | 14 +- .../react/renderer/mounting/StubView.cpp | 42 +- .../react/renderer/mounting/StubView.h | 6 + .../react/renderer/mounting/StubViewTree.cpp | 310 +- .../react/renderer/mounting/StubViewTree.h | 18 +- .../renderer/mounting/TelemetryController.cpp | 2 +- .../renderer/mounting/TelemetryController.h | 2 +- .../mounting/TransactionTelemetry.cpp | 142 - ReactCommon/react/renderer/mounting/stubs.cpp | 60 +- ReactCommon/react/renderer/mounting/stubs.h | 14 +- .../renderer/mounting/tests/MountingTest.cpp | 195 +- .../tests/ShadowTreeLifeCycleTest.cpp | 282 +- .../mounting/tests/StackingContextTest.cpp | 787 + .../tests/StateReconciliationTest.cpp | 57 +- .../tests/TransactionTelemetryTest.cpp | 125 - .../renderer/runtimescheduler/Android.mk | 27 + .../react/renderer/runtimescheduler/BUCK | 77 + .../runtimescheduler/RuntimeScheduler.cpp | 116 + .../runtimescheduler/RuntimeScheduler.h | 103 + .../RuntimeSchedulerBinding.cpp | 170 + .../RuntimeSchedulerBinding.h | 42 + .../runtimescheduler/RuntimeSchedulerClock.h | 22 + .../runtimescheduler/SchedulerPriority.h | 64 + .../react/renderer/runtimescheduler/Task.cpp | 35 + .../react/renderer/runtimescheduler/Task.h | 46 + .../renderer/runtimescheduler/primitives.h | 39 + .../tests/RuntimeSchedulerTest.cpp | 472 + .../tests/SchedulerPriorityTest.cpp | 46 + .../runtimescheduler/tests/StubClock.h | 41 + .../runtimescheduler/tests/StubQueue.h | 38 + .../react/renderer/scheduler/Android.mk | 6 +- .../scheduler/AsynchronousEventBeat.cpp | 29 +- .../scheduler/AsynchronousEventBeat.h | 8 +- ReactCommon/react/renderer/scheduler/BUCK | 8 +- .../InspectorData.h} | 17 +- .../react/renderer/scheduler/Scheduler.cpp | 256 +- .../react/renderer/scheduler/Scheduler.h | 76 +- .../renderer/scheduler/SchedulerDelegate.h | 26 +- .../renderer/scheduler/SchedulerToolbox.h | 10 + .../renderer/scheduler/SurfaceHandler.cpp | 317 + .../react/renderer/scheduler/SurfaceHandler.h | 209 + .../renderer/scheduler/SurfaceManager.cpp | 104 + .../react/renderer/scheduler/SurfaceManager.h | 67 + .../scheduler/SynchronousEventBeat.cpp | 19 +- .../renderer/scheduler/SynchronousEventBeat.h | 5 +- .../react/renderer/telemetry/Android.mk | 31 + ReactCommon/react/renderer/telemetry/BUCK | 84 + .../SurfaceTelemetry.cpp | 5 + .../SurfaceTelemetry.h | 4 +- .../telemetry/TransactionTelemetry.cpp | 163 + .../TransactionTelemetry.h | 11 + .../tests/TransactionTelemetryTest.cpp | 176 + .../renderer/templateprocessor/Android.mk | 2 +- .../react/renderer/templateprocessor/BUCK | 6 +- .../templateprocessor/UITemplateProcessor.cpp | 10 +- .../tests/UITemplateProcessorTest.cpp | 10 +- .../renderer/textlayoutmanager/Android.mk | 7 +- .../react/renderer/textlayoutmanager/BUCK | 8 +- .../textlayoutmanager/TextMeasureCache.cpp | 21 +- .../textlayoutmanager/TextLayoutManager.cpp | 228 +- .../textlayoutmanager/TextLayoutManager.h | 18 +- .../platform/cxx/TextLayoutManager.cpp | 18 +- .../platform/cxx/TextLayoutManager.h | 17 +- .../platform/ios/RCTAttributedTextUtils.mm | 27 +- .../platform/ios/RCTTextLayoutManager.mm | 25 +- .../platform/ios/TextLayoutManager.mm | 28 +- .../{components/picker => timeline}/BUCK | 54 +- .../react/renderer/timeline/Timeline.cpp | 120 + .../react/renderer/timeline/Timeline.h | 63 + .../renderer/timeline/TimelineController.cpp | 77 + .../renderer/timeline/TimelineController.h | 80 + .../react/renderer/timeline/TimelineFrame.cpp | 25 + .../react/renderer/timeline/TimelineFrame.h | 46 + .../renderer/timeline/TimelineHandler.cpp | 97 + .../react/renderer/timeline/TimelineHandler.h | 80 + .../renderer/timeline/TimelineSnapshot.cpp | 30 + .../renderer/timeline/TimelineSnapshot.h | 36 + .../react/renderer/uimanager/Android.mk | 6 +- ReactCommon/react/renderer/uimanager/BUCK | 8 +- .../uimanager/LayoutAnimationStatusDelegate.h | 6 +- .../react/renderer/uimanager/UIManager.cpp | 253 +- .../react/renderer/uimanager/UIManager.h | 92 +- .../uimanager/UIManagerAnimationDelegate.h | 6 +- .../renderer/uimanager/UIManagerBinding.cpp | 433 +- .../renderer/uimanager/UIManagerBinding.h | 41 +- .../renderer/uimanager/UIManagerCommitHook.h | 43 + .../renderer/uimanager/UIManagerDelegate.h | 36 +- .../react/renderer/uimanager/primitives.h | 66 +- ReactCommon/react/test_utils/BUCK | 54 + .../mounting/tests => test_utils}/Entropy.h | 4 + ReactCommon/react/test_utils/MockClock.h | 29 + .../shadowTreeGeneration.h | 71 +- ReactCommon/react/utils/Android.mk | 11 +- ReactCommon/react/utils/BUCK | 11 +- .../utils/CalledOnceMovableOnlyFunction.h | 10 +- ReactCommon/react/utils/ContextContainer.h | 21 +- ReactCommon/react/utils/LayoutManager.h | 150 + .../react/utils/ManagedObjectWrapper.h | 4 +- ReactCommon/react/utils/RunLoopObserver.cpp | 9 +- ReactCommon/reactperflogger/Android.mk | 2 +- ReactCommon/reactperflogger/BUCK | 2 +- .../reactperflogger/React-perflogger.podspec | 6 +- ReactCommon/runtimeexecutor/Android.mk | 2 +- ReactCommon/runtimeexecutor/BUCK | 4 +- .../React-runtimeexecutor.podspec | 6 +- .../ReactCommon/RuntimeExecutor.h | 16 +- ReactCommon/yoga/Yoga.podspec | 6 +- ReactCommon/yoga/yoga/BitUtils.h | 5 +- ReactCommon/yoga/yoga/CompactValue.h | 4 +- ReactCommon/yoga/yoga/Utils.cpp | 2 +- ReactCommon/yoga/yoga/YGNode.cpp | 221 +- ReactCommon/yoga/yoga/YGNode.h | 11 + ReactCommon/yoga/yoga/YGNodePrint.cpp | 11 +- ReactCommon/yoga/yoga/Yoga-internal.h | 9 +- ReactCommon/yoga/yoga/Yoga.cpp | 277 +- ReactCommon/yoga/yoga/Yoga.h | 2 +- .../React-TurboModuleCxx-RNW.podspec | 4 +- .../React-TurboModuleCxx-WinRTPort.podspec | 4 +- Releases.md | 10 +- .../patches/Build/ReactAndroid/NuGet.Config | 4 +- .../Build/ReactAndroid/ReactAndroid.nuspec | 4 +- .../patches/Build/ReactAndroid/build.gradle | 24 +- .../Build/ReactAndroid/gradle.properties | 14 +- .../Build/ReactAndroid/packages.config | 4 +- .../patches/Build/ReactAndroid/release.gradle | 10 - .../src/main/jni/third-party/boost/Android.mk | 12 +- .../View/ReactNativeViewViewConfigAndroid.js | 8 +- .../views/view/ReactClippingViewManager.java | 4 +- .../react/views/view/ReactViewFocusEvent.java | 4 +- .../react/views/view/ReactViewManager.java | 18 +- .../uimanager/ViewManagersPropertyCache.java | 35 - .../modules/debug/DevSettingsModule.java | 12 +- .../facebook/react/ReactInstanceManager.java | 18 +- .../react/bridge/CatalystInstance.java | 4 +- .../react/bridge/CatalystInstanceImpl.java | 24 +- .../jni/react/jni/CatalystInstanceImpl.cpp | 27 +- .../main/jni/react/jni/CatalystInstanceImpl.h | 10 +- .../ReactCommon/cxxreact/CxxModule.h | 4 +- .../ReactCommon/cxxreact/CxxNativeModule.cpp | 6 +- .../ReactCommon/cxxreact/CxxNativeModule.h | 10 +- .../ReactCommon/cxxreact/Instance.cpp | 6 +- .../ReactCommon/cxxreact/Instance.h | 4 +- .../ReactCommon/cxxreact/PlatformBundleInfo.h | 4 +- .../react/ReactInstanceManagerBuilder.java | 10 +- .../react/bridge/ReactMarkerConstants.java | 11 +- .../com/facebook/react/v8executor/Android.mk | 4 +- .../com/facebook/react/v8executor/OnLoad.cpp | 4 +- .../facebook/react/v8executor/V8Executor.java | 4 +- .../react/v8executor/V8ExecutorFactory.cpp | 4 +- .../react/v8executor/V8ExecutorFactory.h | 4 +- .../react/v8executor/V8ExecutorFactory.java | 4 +- .../src/main/jni/react/jni/Android.mk | 12 +- .../src/main/jni/react/jni/JReactMarker.cpp | 6 +- .../src/main/jni/third-party/v8jsi/Android.mk | 4 +- .../V8/ReactCommon/cxxreact/ReactMarker.h | 4 +- bots/README.md | 2 +- bots/code-analysis-bot.js | 150 +- bots/dangerfile.js | 8 +- bots/report-bundle-size.js | 4 +- build.gradle.kts | 18 +- flow-typed/npm/promise_v8.x.x.js | 6 +- flow-typed/npm/react-test-renderer_v16.x.x.js | 79 + flow/HermesInternalType.js | 114 + flow/global.js | 23 + gradle.properties | 4 + gradle/wrapper/gradle-wrapper.properties | 2 +- index.js | 201 +- interface.js | 8 - jest/mockNativeComponent.js | 36 + jest/preprocessor.js | 83 +- jest/renderer.js | 12 +- jest/setup.js | 74 +- .../HelloWorld.xcodeproj/project.pbxproj | 4 +- .../generator-macos/templates/macos/Podfile | 8 +- metro.config.js | 2 - package.json | 83 +- packages/assets/BUCK | 1 - .../__snapshots__/index-test.js.snap | 40 +- .../__tests__/index-test.js | 1 + packages/babel-plugin-codegen/index.js | 11 +- packages/babel-plugin-codegen/package.json | 4 +- .../index.js | 5 +- .../package.json | 17 +- .../yarn.lock | 972 +- .../__tests__/react-native-modules-test.js | 104 +- packages/eslint-plugin-codegen/package.json | 2 +- .../react-native-modules.js | 132 +- .../README.md | 2 +- .../platform-colors.js | 1 - packages/normalize-color/BUCK | 1 - packages/normalize-color/base.js | 10 + packages/polyfills/BUCK | 12 + .../{Object.es7.js => Object.es8.js} | 0 ...{Object.es7-test.js => Object.es8-test.js} | 4 +- packages/polyfills/error-guard.js | 10 +- packages/polyfills/index.js | 2 +- packages/polyfills/package.json | 2 +- packages/react-native-codegen/BUCK | 33 +- packages/react-native-codegen/DEFS.bzl | 235 +- .../react-native-codegen/android/build.gradle | 58 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradlePlugin/build.gradle | 27 - .../android/settings.gradle | 6 +- .../codegen/generator/JavaGenerator.java | 0 .../codegen/generator/SchemaJsonParser.java | 0 .../codegen/generator/model/AliasType.java | 0 .../codegen/generator/model/AnyType.java | 0 .../codegen/generator/model/ArrayType.java | 0 .../codegen/generator/model/BooleanType.java | 0 .../generator/model/CodegenException.java | 0 .../codegen/generator/model/DoubleType.java | 0 .../codegen/generator/model/FloatType.java | 0 .../codegen/generator/model/FunctionType.java | 0 .../generator/model/GenericObjectType.java | 0 .../codegen/generator/model/Int32Type.java | 0 .../generator/model/NativeModuleType.java | 0 .../codegen/generator/model/NullableType.java | 0 .../codegen/generator/model/NumberType.java | 0 .../codegen/generator/model/ObjectType.java | 0 .../codegen/generator/model/PromiseType.java | 0 .../model/ReservedFunctionValueType.java | 0 .../codegen/generator/model/StringType.java | 0 .../react/codegen/generator/model/Type.java | 0 .../codegen/generator/model/TypeData.java | 0 .../react/codegen/generator/model/TypeId.java | 0 .../codegen/generator/model/VoidType.java | 0 .../generator/resolver/AliasResolvedType.java | 0 .../generator/resolver/Annotations.java | 0 .../generator/resolver/AnyResolvedType.java | 0 .../generator/resolver/ArrayResolvedType.java | 0 .../resolver/BooleanResolvedType.java | 0 .../generator/resolver/ClassNames.java | 0 .../resolver/FunctionResolvedType.java | 2 + .../resolver/GenericObjectResolvedType.java | 0 .../resolver/NativeModuleResolvedType.java | 0 .../resolver/NullableResolvedType.java | 0 .../resolver/NumberResolvedType.java | 0 .../resolver/ObjectResolvedType.java | 0 .../resolver/PromiseResolvedType.java | 0 .../generator/resolver/ReactClassNames.java | 0 .../ReservedFunctionValueResolvedType.java | 0 .../generator/resolver/ResolvedType.java | 0 .../resolver/StringResolvedType.java | 0 .../generator/resolver/TypeResolver.java | 0 .../codegen/generator/resolver/TypeUtils.java | 0 .../generator/resolver/VoidResolvedType.java | 0 .../react/codegen/plugin/CodegenPlugin.java | 7 +- .../plugin/CodegenPluginExtension.java | 2 +- .../components/ArrayPropsNativeComponent.js | 2 - .../components/BooleanPropNativeComponent.js | 2 - .../components/ColorPropNativeComponent.js | 2 - .../EdgeInsetsPropNativeComponent.js | 2 - .../components/EnumPropNativeComponent.js | 2 - .../EventNestedObjectPropsNativeComponent.js | 2 - .../components/EventPropsNativeComponent.js | 2 - .../components/FloatPropsNativeComponent.js | 2 - .../components/ImagePropNativeComponent.js | 2 - .../components/IntegerPropNativeComponent.js | 2 - .../InterfaceOnlyNativeComponent.js | 2 - .../MultiNativePropNativeComponent.js | 2 - .../NoPropsNoEventsNativeComponent.js | 2 - .../components/ObjectPropsNativeComponent.js | 2 - .../components/PointPropNativeComponent.js | 2 - .../components/StringPropNativeComponent.js | 2 - .../modules/NativeArrayTurboModule.js | 2 - .../modules/NativeBooleanTurboModule.js | 2 - .../modules/NativeCallbackTurboModule.js | 2 - .../modules/NativeNullableTurboModule.js | 2 - .../modules/NativeNumberTurboModule.js | 2 - .../modules/NativeObjectTurboModule.js | 2 - .../NativeOptionalObjectTurboModule.js | 2 - .../modules/NativePromiseTurboModule.js | 2 - .../modules/NativeSampleTurboModule.js | 2 - .../modules/NativeSampleTurboModuleArrays.js | 2 - .../NativeSampleTurboModuleNullable.js | 2 - ...iveSampleTurboModuleNullableAndOptional.js | 2 - .../NativeSampleTurboModuleOptional.js | 2 - .../modules/NativeStringTurboModule.js | 2 - .../e2e/__tests__/modules/BUCK | 11 - .../modules/GenerateModuleObjCpp-test.js | 10 +- .../GenerateModuleObjCpp-test.js.snap | 1209 +- packages/react-native-codegen/package.json | 6 +- .../react-native-codegen/scripts/oss/build.sh | 50 +- .../react-native-codegen/src/CodegenSchema.js | 478 +- .../src/cli/generators/generate-all.js | 8 +- .../src/cli/verify_with_old_codegen.js | 52 - .../src/cli/verify_with_old_codegen.sh | 19 - .../src/generators/RNCodegen.js | 45 +- .../src/generators/Utils.js | 11 +- .../src/generators/components/CppHelpers.js | 9 +- .../GenerateComponentDescriptorH.js | 2 +- .../components/GenerateComponentHObjCpp.js | 33 +- .../components/GenerateEventEmitterCpp.js | 34 +- .../components/GenerateEventEmitterH.js | 35 +- .../generators/components/GeneratePropsCpp.js | 9 +- .../generators/components/GeneratePropsH.js | 52 +- .../components/GeneratePropsJavaDelegate.js | 26 +- .../components/GeneratePropsJavaInterface.js | 26 +- .../GeneratePropsJavaPojo/PojoCollector.js | 187 + .../components/GeneratePropsJavaPojo/index.js | 80 + .../GeneratePropsJavaPojo/serializePojo.js | 285 + .../components/GenerateShadowNodeCpp.js | 2 +- .../components/GenerateShadowNodeH.js | 2 +- .../generators/components/GenerateTests.js | 20 +- .../components/GenerateViewConfigJs.js | 14 +- .../components/__test_fixtures__/fixtures.js | 170 +- .../GenerateComponentDescriptorH-test.js | 4 +- .../GenerateComponentHObjCpp-test.js | 4 +- .../__tests__/GenerateEventEmitterCpp-test.js | 4 +- .../__tests__/GenerateEventEmitterH-test.js | 4 +- .../__tests__/GeneratePropsCpp-test.js | 4 +- .../__tests__/GeneratePropsH-test.js | 4 +- .../GeneratePropsJavaDelegate-test.js | 4 +- .../GeneratePropsJavaInterface-test.js | 4 +- .../__tests__/GeneratePropsJavaPojo-test.js | 27 + .../__tests__/GenerateShadowNodeH-test.js | 4 +- .../__tests__/GenerateTests-test.js | 4 +- .../GeneratePropsCpp-test.js.snap | 211 +- .../__snapshots__/GeneratePropsH-test.js.snap | 187 +- .../GeneratePropsJavaDelegate-test.js.snap | 78 +- .../GeneratePropsJavaInterface-test.js.snap | 52 +- .../GeneratePropsJavaPojo-test.js.snap | 1177 ++ .../__snapshots__/GenerateTests-test.js.snap | 466 +- .../GenerateViewConfigJs-test.js.snap | 460 +- .../generators/modules/GenerateModuleCpp.js | 23 +- .../src/generators/modules/GenerateModuleH.js | 10 +- .../modules/GenerateModuleJavaSpec.js | 35 +- .../modules/GenerateModuleJniCpp.js | 53 +- .../generators/modules/GenerateModuleJniH.js | 21 +- .../GenerateModuleObjCpp/StructCollector.js | 19 +- .../modules/GenerateModuleObjCpp/Utils.js | 4 - .../header/serializeConstantsStruct.js | 33 +- .../header/serializeRegularStruct.js | 31 +- .../header/serializeStruct.js | 4 +- .../modules/GenerateModuleObjCpp/index.js | 31 +- .../GenerateModuleObjCpp/serializeMethod.js | 54 +- .../source/serializeModule.js | 16 +- .../src/generators/modules/Utils.js | 4 +- .../modules/__test_fixtures__/fixtures.js | 4 +- .../__tests__/GenerateModuleCpp-test.js | 6 +- .../modules/__tests__/GenerateModuleH-test.js | 6 +- .../__tests__/GenerateModuleHObjCpp-test.js | 9 +- .../__tests__/GenerateModuleJavaSpec-test.js | 6 +- .../__tests__/GenerateModuleJniCpp-test.js | 6 +- .../__tests__/GenerateModuleJniH-test.js | 6 +- .../__tests__/GenerateModuleMm-test.js | 12 +- .../GenerateModuleHObjCpp-test.js.snap | 16 +- .../GenerateModuleJavaSpec-test.js.snap | 34 + .../GenerateModuleJniCpp-test.js.snap | 24 +- .../GenerateModuleJniH-test.js.snap | 60 +- .../GenerateModuleMm-test.js.snap | 26 +- .../component-parser-test.js.snap | 7769 ++++--- .../src/parsers/flow/components/commands.js | 17 +- .../src/parsers/flow/components/events.js | 47 +- .../src/parsers/flow/components/extends.js | 2 +- .../src/parsers/flow/components/index.js | 2 +- .../src/parsers/flow/components/options.js | 6 +- .../src/parsers/flow/components/props.js | 17 +- .../src/parsers/flow/components/schema.js | 13 +- .../src/parsers/flow/errors.js | 12 +- .../src/parsers/flow/index.js | 210 +- .../modules/__test_fixtures__/fixtures.js | 26 + .../module-parser-snapshot-test.js.snap | 45 +- .../__tests__/module-parser-e2e-test.js | 96 +- .../src/parsers/flow/modules/errors.js | 119 +- .../src/parsers/flow/modules/index.js | 322 +- .../src/parsers/flow/utils.js | 77 +- .../src/parsers/schema/index.js | 2 +- .../build.gradle.kts | 29 + .../facebook/react/AndroidConfiguration.kt | 22 + .../com/facebook/react/ReactAppExtension.kt | 110 + .../com/facebook/react/ReactAppPlugin.kt | 36 + .../com/facebook/react/TaskConfiguration.kt | 241 + .../react/tasks/BundleJsAndAssetsTask.kt | 80 + .../facebook/react/tasks/HermesBinaryTask.kt | 74 + .../com/facebook/react/tasks/TaskUtils.kt | 19 + packages/react-native-macos-init/package.json | 2 +- packages/react-native-macos-init/src/cli.ts | 87 +- packages/rn-tester/BUCK | 250 +- packages/rn-tester/Gemfile | 3 +- .../NativeScreenshotManager.js | 2 - packages/rn-tester/Podfile | 53 +- packages/rn-tester/Podfile.lock | 307 +- packages/rn-tester/RCTTest/RCTTestModule.mm | 3 +- packages/rn-tester/RCTTest/RCTTestRunner.m | 103 +- .../rn-tester/RCTTest/React-RCTTest.podspec | 6 +- packages/rn-tester/README.md | 2 +- .../rn-tester/RNTester-macOS/AppDelegate.mm | 6 +- packages/rn-tester/RNTester-tvOS/Info.plist | 2 - packages/rn-tester/RNTester/AppDelegate.mm | 110 +- .../customColor.colorset/Contents.json | 38 + packages/rn-tester/RNTester/Info.plist | 2 - .../RNTester/RNTesterTurboModuleProvider.h | 6 - .../RNTester/RNTesterTurboModuleProvider.mm | 9 - .../RCTLoggingTests.m | 37 +- .../RNTesterPods.xcodeproj/project.pbxproj | 462 +- .../RNTesterIntegrationTests.xcscheme | 5 - .../RNTesterUnitTests/RCTBlobManagerTests.m | 1 + .../RCTBundleURLProviderTests.m | 2 +- .../RCTEventDispatcherTests.m | 49 +- .../RCTModuleInitNotificationRaceTests.m | 6 +- .../RNTesterUnitTests/RCTModuleInitTests.m | 6 +- packages/rn-tester/android/app/build.gradle | 50 +- .../rn-tester/android/app/gradle.properties | 2 +- .../android/app/src/main/AndroidManifest.xml | 5 + .../react/uiapp/RNTesterApplication.java | 55 +- .../RNTesterTurboModuleManagerDelegate.java | 24 +- .../android/app/src/main/jni/Android.mk | 4 +- .../main/jni/RNTesterAppModuleProvider.cpp | 4 +- .../app/src/main/res/values/strings.xml | 1 + packages/rn-tester/js/RNTesterApp.android.js | 2 - packages/rn-tester/js/RNTesterApp.ios.js | 22 +- packages/rn-tester/js/RNTesterAppShared.js | 179 +- .../js/assets/bottom-nav-center-box.png | Bin 1340 -> 0 bytes .../rn-tester/js/components/ExamplePage.js | 99 - .../js/components/ListExampleShared.js | 26 +- .../js/components/RNTConfigurationBlock.js | 44 + packages/rn-tester/js/components/RNTOption.js | 88 + .../js/components/RNTPressableRow.js | 97 + .../rn-tester/js/components/RNTTestDetails.js | 96 + .../{RNTesterHeader.js => RNTTitleBar.js} | 43 +- .../rn-tester/js/components/RNTesterBlock.js | 28 +- .../js/components/RNTesterBookmarkButton.js | 2 - .../rn-tester/js/components/RNTesterButton.js | 2 + .../js/components/RNTesterDocumentationURL.js | 2 - .../components/RNTesterEmptyBookmarksState.js | 2 - .../js/components/RNTesterExampleContainer.js | 113 - .../js/components/RNTesterExampleFilter.js | 17 +- .../js/components/RNTesterModuleContainer.js | 157 + ...erExampleList.js => RNTesterModuleList.js} | 92 +- .../rn-tester/js/components/RNTesterNavbar.js | 16 +- .../rn-tester/js/components/RNTesterPage.js | 2 - .../js/components/RNTesterSettingSwitchRow.js | 6 +- .../rn-tester/js/components/RNTesterTheme.js | 2 - .../rn-tester/js/components/RNTesterTitle.js | 2 - .../rn-tester/js/components/TextInlineView.js | 6 +- .../rn-tester/js/components/TextLegend.js | 470 +- .../js/components/createExamplePage.js | 8 +- .../AccessibilityAndroidExample.android.js | 52 +- .../Accessibility/AccessibilityExample.js | 503 +- .../ActionSheetIOS/ActionSheetIOSExample.js | 38 + .../ActivityIndicatorExample.js | 1 - .../js/examples/Alert/AlertExample.js | 2 - .../js/examples/Alert/AlertIOSExample.js | 12 +- .../js/examples/Alert/AlertMacOSExample.js | 10 +- .../js/examples/Animated/AnimatedExample.js | 458 - .../js/examples/Animated/AnimatedIndex.js | 44 + .../ComposeAnimationsWithEasingExample.js | 136 + .../js/examples/Animated/ComposingExample.js | 251 + .../Animated/ContinuousInteractionsExample.js | 22 + .../js/examples/Animated/EasingExample.js | 208 + .../js/examples/Animated/FadeInViewExample.js | 99 + .../js/examples/Animated/LoopingExample.js | 103 + .../js/examples/Animated/MovingBoxExample.js | 138 + .../Animated/RotatingImagesExample.js | 111 + .../Animated/TransformBounceExample.js | 123 + .../Animated/TransformStylesExample.js | 168 + .../Animated/utils/ToggleNativeDriver.js | 48 + .../AnimatedGratuitousApp/AnExApp.js | 19 +- .../AnimatedGratuitousApp/AnExBobble.js | 0 .../AnimatedGratuitousApp/AnExChained.js | 10 +- .../AnimatedGratuitousApp/AnExScroll.js | 0 .../AnimatedGratuitousApp/AnExSet.js | 0 .../AnimatedGratuitousApp/AnExSlides.md | 0 .../AnimatedGratuitousApp/AnExTilt.js | 2 +- .../js/examples/AppState/AppStateExample.js | 53 +- .../examples/Appearance/AppearanceExample.js | 19 +- .../js/examples/Border/BorderExample.js | 46 +- .../js/examples/Button/ButtonExample.js | 23 + .../js/examples/Crash/CrashExample.js | 1 - .../DevSettings/DevSettingsExample.js | 2 - .../examples/Dimensions/DimensionsExample.js | 22 +- .../FlatList/FlatList-onEndReached.js | 28 + .../FlatList-onViewableItemsChanged.js | 38 + .../FlatList/FlatList-withSeparators.js | 27 + .../js/examples/FlatList/FlatListExample.js | 72 +- .../js/examples/FlatList/FlatListExamples.js | 323 + .../js/examples/Image/ImageExample.js | 346 +- .../JSResponderHandlerExample.js | 2 - .../KeyboardAvoidingViewExample.js | 55 +- .../js/examples/Layout/LayoutEventsExample.js | 15 +- .../js/examples/Modal/ModalExample.js | 291 +- .../js/examples/Modal/ModalOnShow.js | 137 + .../js/examples/Modal/ModalPresentation.js | 264 + .../MultiColumn/MultiColumnExample.js | 37 +- .../NativeAnimationsExample.js | 24 +- .../OrientationChangeExample.js | 2 - .../PanResponder/PanResponderExample.js | 11 +- .../PermissionsAndroid/PermissionsExample.js | 197 +- .../PlatformColor/PlatformColorExample.js | 17 +- .../PointerEvents/PointerEventsExample.js | 111 +- .../js/examples/Pressable/PressableExample.js | 23 +- .../rn-tester/js/examples/RTL/RTLExample.js | 9 +- .../RefreshControl/RefreshControlExample.js | 1 - .../RootViewSizeFlexibilityExampleApp.js | 1 + .../ScrollView/ScrollViewAnimatedExample.js | 11 +- .../examples/ScrollView/ScrollViewExample.js | 1071 +- .../ScrollViewIndicatorInsetsExample.ios.js | 112 + .../ScrollViewIndicatorInsetsExample.macos.js | 112 + .../ScrollViewPressableStickyHeaderExample.js | 97 + .../SectionList/SectionList-contentInset.js | 84 + .../SectionList/SectionList-inverted.js | 44 + .../SectionList/SectionList-onEndReached.js | 46 + .../SectionList-onViewableItemsChanged.js | 77 + .../SectionList/SectionList-scrollable.js | 350 + .../SectionList-stickyHeadersEnabled.js | 53 + .../SectionList/SectionList-withSeparators.js | 63 + .../SectionList/SectionListBaseExample.js | 142 + .../SectionList/SectionListExample.js | 304 - .../examples/SectionList/SectionListIndex.js | 34 + .../js/examples/Share/ShareExample.js | 46 + .../examples/Snapshot/SnapshotViewIOS.ios.js | 4 +- .../SwipeableCardExample.js | 207 + .../js/examples/Switch/SwitchExample.js | 21 +- .../Text/TextAdjustsDynamicLayoutExample.js | 55 + .../js/examples/Text/TextExample.android.js | 16 +- .../js/examples/Text/TextExample.ios.js | 73 +- .../TextInput/TextInputExample.android.js | 36 +- .../TextInput/TextInputExample.ios.js | 106 +- .../TextInput/TextInputSharedExamples.js | 99 +- .../js/examples/Timer/TimerExample.js | 4 + .../js/examples/Touchable/TouchableExample.js | 119 +- .../js/examples/Transform/TransformExample.js | 20 +- .../TurboModule/SampleTurboModuleExample.js | 20 +- .../rn-tester/js/examples/View/ViewExample.js | 1 + .../js/examples/XHR/XHRExampleBinaryUpload.js | 43 +- .../js/examples/XHR/XHRExampleOnTimeOut.js | 1 + packages/rn-tester/js/types/RNTesterTypes.js | 37 +- .../js/utils/RNTesterList.android.js | 42 +- .../rn-tester/js/utils/RNTesterList.ios.js | 52 +- .../rn-tester/js/utils/RNTesterReducer.js | 27 +- .../js/utils/RNTesterStatePersister.js | 8 +- .../rn-tester/js/utils/testerStateUtils.js | 14 +- .../js/utils/useAsyncStorageReducer.js | 2 - packages/rn-tester/package.json | 4 +- packages/rn-tester/yarn.lock | 1026 + react.gradle | 61 +- repo-config/package.json | 25 +- scripts/.tests.env | 4 +- scripts/bump-oss-version.js | 32 +- scripts/circleci/analyze_code.sh | 2 +- scripts/circleci/buck_fetch.sh | 46 +- scripts/circleci/gradle_download_deps.sh | 2 +- scripts/codegen.js | 54 + scripts/find-node.sh | 39 + scripts/generate-native-modules-specs.sh | 79 - scripts/generate-rncore.sh | 14 - ...les-specs-cli.js => generate-specs-cli.js} | 33 +- scripts/generate-specs.sh | 99 + scripts/ios-configure-glog.sh | 2 +- scripts/lint-java.js | 205 + scripts/publish-npm.js | 2 +- scripts/react-native-xcode.sh | 37 +- scripts/react_native_pods.rb | 159 +- scripts/test-manual-e2e.sh | 58 +- scripts/update_podfile_lock.sh | 41 + settings.gradle.kts | 1 + template/_editorconfig | 3 + template/_flowconfig | 7 +- template/_gitattributes | 3 + template/_gitignore | 1 + template/android/app/build.gradle | 19 +- .../app/src/main/res/values/styles.xml | 1 - template/android/build.gradle | 14 +- template/android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../ios/HelloWorld.xcodeproj/project.pbxproj | 10 +- template/ios/Podfile | 16 +- template/package.json | 21 +- third-party-podspecs/DoubleConversion.podspec | 4 +- third-party-podspecs/RCT-Folly.podspec | 47 +- .../boost-for-react-native.podspec | 2 +- third-party-podspecs/boost.podspec | 23 + third-party-podspecs/glog.podspec | 2 +- third-party-podspecs/libevent.podspec | 565 - tools/build_defs/apple/config_utils_defs.bzl | 12 + .../apple/fb_apple_asset_catalog.bzl | 7 +- tools/build_defs/apple/fb_apple_bundle.bzl | 7 + tools/build_defs/apple/fb_apple_test.bzl | 7 + tools/build_defs/apple/fb_js_dep.bzl | 7 + tools/build_defs/apple/flag_defs.bzl | 16 + .../build_defs/apple/plugins/plugin_defs.bzl | 7 + .../fb_xplat_platform_specific_rule.bzl | 16 + tools/build_defs/fb_xplat_resource.bzl | 7 + tools/build_defs/js_glob.bzl | 40 + tools/build_defs/oss/metro_defs.bzl | 9 + tools/build_defs/oss/rn_codegen_defs.bzl | 72 + tools/build_defs/oss/rn_defs.bzl | 107 +- yarn.lock | 5679 +++--- 2184 files changed, 129841 insertions(+), 85716 deletions(-) rename .github/{label-actions.yml => respond-to-issue-based-on-label.yml} (96%) rename .github/workflows/{process-label-actions.yml => on-issue-labeled.yml} (54%) delete mode 100644 .nvmrc create mode 100644 BUCK create mode 100644 IntegrationTests/BUCK create mode 100644 Libraries/Animated/__tests__/createAnimatedComponentInjection-test.js create mode 100644 Libraries/Animated/createAnimatedComponentInjection.js create mode 100644 Libraries/Animated/createAnimatedComponent_EXPERIMENTAL.js create mode 100644 Libraries/Animated/useAnimatedProps.js delete mode 100644 Libraries/BUCK delete mode 100644 Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js delete mode 100644 Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js create mode 100644 Libraries/Components/AccessibilityInfo/AccessibilityInfo.js delete mode 100644 Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js create mode 100644 Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js create mode 100644 Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js create mode 100644 Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.macos.js delete mode 100644 Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js delete mode 100644 Libraries/Components/Picker/AndroidDialogPickerViewConfig.js delete mode 100644 Libraries/Components/Picker/AndroidDropdownPickerNativeComponent.js delete mode 100644 Libraries/Components/Picker/Picker.js delete mode 100644 Libraries/Components/Picker/PickerAndroid.android.js delete mode 100644 Libraries/Components/Picker/PickerIOS.ios.js delete mode 100644 Libraries/Components/Picker/RCTPickerNativeComponent.js delete mode 100644 Libraries/Components/Picker/RCTPickerViewConfig.js delete mode 100644 Libraries/Components/Picker/__tests__/Picker-test.js delete mode 100644 Libraries/Components/Picker/__tests__/__snapshots__/Picker-test.js.snap delete mode 100644 Libraries/Components/ScrollResponder.js create mode 100644 Libraries/Components/SegmentedControlIOS/__tests__/SegmentedContolIOS-test.js create mode 100644 Libraries/Components/SegmentedControlIOS/__tests__/__snapshots__/SegmentedContolIOS-test.js.snap delete mode 100644 Libraries/Components/StatusBar/StatusBarIOS.js create mode 100644 Libraries/Components/StatusBar/__tests__/StatusBar-test.js rename Libraries/Components/TextInput/{RCTSinglelineTextInputViewConfig.js => RCTTextInputViewConfig.js} (93%) create mode 100644 Libraries/Components/Touchable/__tests__/TouchableNativeFeedback-test.js create mode 100644 Libraries/Components/Touchable/__tests__/TouchableOpacity-test.js create mode 100644 Libraries/Components/Touchable/__tests__/TouchableWithoutFeedback-test.js create mode 100644 Libraries/Components/Touchable/__tests__/__snapshots__/TouchableNativeFeedback-test.js.snap create mode 100644 Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap create mode 100644 Libraries/Components/Touchable/__tests__/__snapshots__/TouchableWithoutFeedback-test.js.snap create mode 100644 Libraries/Components/__tests__/Button-test.js create mode 100644 Libraries/Components/__tests__/Slider-test.js create mode 100644 Libraries/Components/__tests__/__snapshots__/Button-test.js.snap create mode 100644 Libraries/Components/__tests__/__snapshots__/Slider-test.js.snap create mode 100644 Libraries/Core/ExtendedError.js create mode 100644 Libraries/Core/Timers/immediateShim.js create mode 100644 Libraries/Core/Timers/queueMicrotask.js create mode 100644 Libraries/DeprecatedPropTypes/DeprecatedImagePropType.android.js rename Libraries/DeprecatedPropTypes/{DeprecatedImagePropType.js => DeprecatedImagePropType.ios.js} (100%) create mode 100644 Libraries/DeprecatedPropTypes/DeprecatedImagePropType.macos.js create mode 100644 Libraries/Image/AssetUtils.js create mode 100644 Libraries/Image/ImageInjection.js delete mode 100644 Libraries/Image/ImageViewViewConfig.js create mode 100644 Libraries/Image/__tests__/AssetUtils-test.js create mode 100644 Libraries/Lists/CellRenderMask.js create mode 100644 Libraries/Lists/SectionListModern.js create mode 100644 Libraries/Lists/__tests__/CellRenderMask-test.js rename packages/react-native-codegen/android/gradlePlugin-build/settings.gradle => Libraries/Modal/ModalInjection.js (58%) create mode 100644 Libraries/NativeComponent/NativeComponentRegistry.js create mode 100644 Libraries/NativeComponent/ViewConfig.js create mode 100644 Libraries/Pressability/PressabilityPerformanceEventEmitter.js create mode 100644 Libraries/Pressability/PressabilityTypes.js create mode 100644 Libraries/ReactNative/DisplayMode.js rename Libraries/{Text/TextInjection.js => ReactNative/UIManagerInjection.js} (73%) create mode 100644 Libraries/ReactNative/getCachedComponentWithDebugName.js delete mode 100644 Libraries/StyleSheet/StyleSheetValidation.js rename Libraries/{Components/Picker/PickerAndroid.ios.js => Types/RootTagTypes.js} (70%) create mode 100644 Libraries/Utilities/FeatureDetection.js create mode 100644 Libraries/Utilities/__tests__/useMergeRefs-test.js create mode 100644 Libraries/Utilities/__tests__/useRefEffect-test.js delete mode 100644 Libraries/Utilities/registerGeneratedViewConfig.js create mode 100644 Libraries/Utilities/useMergeRefs.js create mode 100644 Libraries/Utilities/useRefEffect.js delete mode 100644 Libraries/promiseRejectionIsError.js create mode 100644 Libraries/vendor/emitter/EventSubscription.js create mode 100644 Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js create mode 100644 React/Base/RCTBundleManager.m create mode 100644 React/Base/RCTCallableJSModules.m rename React/{Views/RCTPickerManager.h => Base/RCTInitializing.h} (68%) delete mode 100644 React/Base/RCTJSInvokerModule.h create mode 100644 React/Base/RCTModuleRegistry.m create mode 100644 React/Base/RCTViewRegistry.m rename {Libraries => React}/FBReactNativeSpec/FBReactNativeSpec.podspec (60%) delete mode 100644 React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.h delete mode 100644 React/Fabric/Mounting/ComponentViews/Picker/RCTPickerComponentView.mm create mode 100644 React/Fabric/Mounting/ComponentViews/Text/RCTAccessibilityElement.h create mode 100644 React/Fabric/Mounting/ComponentViews/Text/RCTAccessibilityElement.mm delete mode 100644 React/Views/RCTPicker.h delete mode 100644 React/Views/RCTPicker.m delete mode 100644 React/Views/RCTPickerManager.m create mode 100644 React/Views/RCTWeakViewHolder.h delete mode 100644 ReactAndroid/release.gradle delete mode 100644 ReactAndroid/src/androidTest/java/com/facebook/react/tests/ReactPickerTestCase.java create mode 100644 ReactAndroid/src/androidTest/js/BUCK delete mode 100644 ReactAndroid/src/androidTest/js/PickerAndroidTestModule.js delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/ReactFragmentActivity.java rename ReactAndroid/src/main/java/com/facebook/react/{turbomodule/core => }/ReactPackageTurboModuleManagerDelegate.java (82%) rename ReactAndroid/src/main/java/com/facebook/react/bridge/{ReactSoftException.java => ReactSoftExceptionLogger.java} (83%) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBufferSoLoader.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/Android.mk create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/react/common/mapbuffer/OnLoad.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/react/common/mapbuffer/ReadableMapBuffer.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/react/common/mapbuffer/ReadableMapBuffer.h create mode 100644 ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/devsupport/PackagerStatusCheck.java rename ReactAndroid/src/main/java/com/facebook/react/devsupport/{ReactInstanceManagerDevHelper.java => ReactInstanceDevHelper.java} (88%) rename packages/react-native-codegen/android/gradlePlugin-build/build.gradle => ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/BundleLoadCallback.java (63%) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/ErrorType.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/SurfaceHandler.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/SurfaceHandlerBinding.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/jni/SurfaceHandlerBinding.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/jni/SurfaceHandlerBinding.h create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/BatchMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/CreateMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/InsertMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/RemoveDeleteMultiMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateEventEmitterMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateLayoutMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePropsMountItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdateStateMountItem.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ComponentNameResolver.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ComponentNameResolverManager.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactClippingProhibitedView.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactOverflowView.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerResolver.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/events/LockFreeEventDispatcherImpl.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BUCK rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/BaseViewManagerDelegate.java (100%) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/BaseViewManagerInterface.java (100%) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/FloatUtil.java (100%) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/Spacing.java (100%) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/ViewManagerDelegate.java (100%) rename ReactAndroid/src/main/java/com/facebook/react/uimanager/{ => interfaces}/ViewProps.java (96%) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/Android.mk create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/ComponentNameResolverManager.cpp create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/ComponentNameResolverManager.h create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/OnLoad.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ActivityIndicatorViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDialogPickerManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDialogPickerManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDrawerLayoutManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidDropdownPickerManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidProgressBarManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidSwitchManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/MaskedViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ModalHostViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/ProgressViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SafeAreaViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SegmentedControlManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SliderManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerDelegate.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/UnimplementedNativeViewManagerInterface.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/Android.mk delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ComponentDescriptors.h delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/EventEmitters.h delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/Props.h delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.cpp delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/viewmanagers/jni/react/renderer/components/rncore/ShadowNodes.h delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/BUCK delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDialogPickerManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactDropdownPickerManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPicker.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerAdapter.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerItem.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/picker/events/PickerItemSelectEvent.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/text/TypefaceStyle.java create mode 100644 ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.java create mode 100644 ReactAndroid/src/main/jni/react/jni/JReactSoftExceptionLogger.cpp create mode 100644 ReactAndroid/src/main/jni/react/jni/JReactSoftExceptionLogger.h create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm/jump_arm_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm/make_arm_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm/ontop_arm_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm64/jump_arm64_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm64/make_arm64_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/arm64/ontop_arm64_aapcs_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86/jump_i386_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86/make_i386_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86/ontop_i386_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86_64/jump_x86_64_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86_64/make_x86_64_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/boost/asm/x86_64/ontop_x86_64_sysv_elf_gas.S create mode 100644 ReactAndroid/src/main/jni/third-party/fmt/Android.mk create mode 100644 ReactAndroid/src/main/jni/third-party/libevent/Android.mk create mode 100644 ReactAndroid/src/main/jni/third-party/libevent/evconfig-private.h create mode 100644 ReactAndroid/src/main/jni/third-party/libevent/event-config.h delete mode 100644 ReactAndroid/src/main/third-party/android/support/v4/BUCK delete mode 100644 ReactAndroid/src/main/third-party/android/support/v7/appcompat/BUCK delete mode 100644 ReactAndroid/src/main/third-party/android/support/v7/appcompat/aar-unpacker.py rename ReactAndroid/src/main/third-party/java/robolectric/{4.4 => }/BUCK (99%) create mode 100644 ReactAndroid/src/main/third-party/kotlin/BUCK create mode 100644 ReactAndroid/src/test/java/com/facebook/react/modules/deviceinfo/DeviceInfoModuleTest.java delete mode 100644 ReactCommon/cxxreact/re_worker_requirements create mode 100644 ReactCommon/hermes/React-hermes.podspec create mode 100644 ReactCommon/logger/Android.mk create mode 100644 ReactCommon/logger/BUCK create mode 100644 ReactCommon/logger/React-logger.podspec create mode 100644 ReactCommon/logger/react_native_log.cpp create mode 100644 ReactCommon/logger/react_native_log.h create mode 100644 ReactCommon/react/debug/Android.mk create mode 100644 ReactCommon/react/debug/BUCK create mode 100644 ReactCommon/react/debug/flags.h create mode 100644 ReactCommon/react/debug/react_native_assert.cpp create mode 100644 ReactCommon/react/debug/react_native_assert.h create mode 100644 ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.h create mode 100644 ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.mm create mode 100644 ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp create mode 100644 ReactCommon/react/renderer/attributedstring/tests/AttributedStringBoxTest.cpp create mode 100644 ReactCommon/react/renderer/componentregistry/componentNameByReactViewName.cpp rename ReactCommon/react/renderer/{components/picker/iospicker/PickerShadowNode.cpp => componentregistry/componentNameByReactViewName.h} (62%) create mode 100644 ReactCommon/react/renderer/componentregistry/native/Android.mk create mode 100644 ReactCommon/react/renderer/componentregistry/native/BUCK create mode 100644 ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.cpp create mode 100644 ReactCommon/react/renderer/componentregistry/native/NativeComponentRegistryBinding.h delete mode 100644 ReactCommon/react/renderer/components/picker/Android.mk delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerEventEmitter.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerEventEmitter.h delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerProps.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerProps.h delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerShadowNode.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerShadowNode.h delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerEventEmitter.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerEventEmitter.h delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerProps.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerProps.h delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerShadowNode.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerShadowNode.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerComponentDescriptor.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerEventEmitter.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerProps.cpp delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerProps.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/PickerShadowNode.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/conversions.h delete mode 100644 ReactCommon/react/renderer/components/picker/iospicker/primitives.h delete mode 100644 ReactCommon/react/renderer/core/ConcreteStateTeller.h create mode 100644 ReactCommon/react/renderer/core/Constants.cpp rename ReactCommon/react/renderer/{components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDropdownPickerComponentDescriptor.h => core/Constants.h} (53%) create mode 100644 ReactCommon/react/renderer/core/DynamicPropsUtilities.cpp rename ReactCommon/react/renderer/{components/picker/iospicker/PickerState.h => core/DynamicPropsUtilities.h} (68%) create mode 100644 ReactCommon/react/renderer/core/EventQueueProcessor.cpp create mode 100644 ReactCommon/react/renderer/core/EventQueueProcessor.h create mode 100644 ReactCommon/react/renderer/core/LayoutMetrics.cpp create mode 100644 ReactCommon/react/renderer/core/PropsParserContext.h create mode 100644 ReactCommon/react/renderer/core/ReactEventPriority.h create mode 100644 ReactCommon/react/renderer/core/tests/DynamicPropsUtilitiesTest.cpp create mode 100644 ReactCommon/react/renderer/core/tests/EventQueueProcessorTest.cpp create mode 100644 ReactCommon/react/renderer/debug/flags.h create mode 100644 ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h create mode 100644 ReactCommon/react/renderer/graphics/platform/cxx/react/renderer/graphics/PlatformColorParser.h create mode 100644 ReactCommon/react/renderer/graphics/platform/ios/PlatformColorParser.h create mode 100644 ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.h create mode 100644 ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.mm create mode 100644 ReactCommon/react/renderer/leakchecker/Android.mk rename ReactCommon/react/renderer/{components/picker/iospicker => leakchecker}/BUCK (63%) create mode 100644 ReactCommon/react/renderer/leakchecker/LeakChecker.cpp create mode 100644 ReactCommon/react/renderer/leakchecker/LeakChecker.h create mode 100644 ReactCommon/react/renderer/leakchecker/WeakFamilyRegistry.cpp create mode 100644 ReactCommon/react/renderer/leakchecker/WeakFamilyRegistry.h create mode 100644 ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp create mode 100644 ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h create mode 100644 ReactCommon/react/renderer/mapbuffer/primitives.h delete mode 100644 ReactCommon/react/renderer/mounting/TransactionTelemetry.cpp create mode 100644 ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp delete mode 100644 ReactCommon/react/renderer/mounting/tests/TransactionTelemetryTest.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/Android.mk create mode 100644 ReactCommon/react/renderer/runtimescheduler/BUCK create mode 100644 ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/Task.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/Task.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/primitives.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/tests/SchedulerPriorityTest.cpp create mode 100644 ReactCommon/react/renderer/runtimescheduler/tests/StubClock.h create mode 100644 ReactCommon/react/renderer/runtimescheduler/tests/StubQueue.h rename ReactCommon/react/renderer/{components/picker/androidpicker/react/renderer/components/androidpicker/AndroidDialogPickerComponentDescriptor.h => scheduler/InspectorData.h} (51%) create mode 100644 ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp create mode 100644 ReactCommon/react/renderer/scheduler/SurfaceHandler.h create mode 100644 ReactCommon/react/renderer/scheduler/SurfaceManager.cpp create mode 100644 ReactCommon/react/renderer/scheduler/SurfaceManager.h create mode 100644 ReactCommon/react/renderer/telemetry/Android.mk create mode 100644 ReactCommon/react/renderer/telemetry/BUCK rename ReactCommon/react/renderer/{mounting => telemetry}/SurfaceTelemetry.cpp (93%) rename ReactCommon/react/renderer/{mounting => telemetry}/SurfaceTelemetry.h (91%) create mode 100644 ReactCommon/react/renderer/telemetry/TransactionTelemetry.cpp rename ReactCommon/react/renderer/{mounting => telemetry}/TransactionTelemetry.h (85%) create mode 100644 ReactCommon/react/renderer/telemetry/tests/TransactionTelemetryTest.cpp rename ReactCommon/react/renderer/{components/picker => timeline}/BUCK (52%) create mode 100644 ReactCommon/react/renderer/timeline/Timeline.cpp create mode 100644 ReactCommon/react/renderer/timeline/Timeline.h create mode 100644 ReactCommon/react/renderer/timeline/TimelineController.cpp create mode 100644 ReactCommon/react/renderer/timeline/TimelineController.h create mode 100644 ReactCommon/react/renderer/timeline/TimelineFrame.cpp create mode 100644 ReactCommon/react/renderer/timeline/TimelineFrame.h create mode 100644 ReactCommon/react/renderer/timeline/TimelineHandler.cpp create mode 100644 ReactCommon/react/renderer/timeline/TimelineHandler.h create mode 100644 ReactCommon/react/renderer/timeline/TimelineSnapshot.cpp create mode 100644 ReactCommon/react/renderer/timeline/TimelineSnapshot.h create mode 100644 ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h create mode 100644 ReactCommon/react/test_utils/BUCK rename ReactCommon/react/{renderer/mounting/tests => test_utils}/Entropy.h (96%) create mode 100644 ReactCommon/react/test_utils/MockClock.h rename ReactCommon/react/{renderer/mounting/tests => test_utils}/shadowTreeGeneration.h (74%) create mode 100644 ReactCommon/react/utils/LayoutManager.h delete mode 100644 android-patches/patches/Build/ReactAndroid/release.gradle create mode 100644 flow-typed/npm/react-test-renderer_v16.x.x.js create mode 100644 flow/HermesInternalType.js create mode 100644 flow/global.js create mode 100644 jest/mockNativeComponent.js rename packages/polyfills/{Object.es7.js => Object.es8.js} (100%) rename packages/polyfills/__tests__/{Object.es7-test.js => Object.es8-test.js} (98%) delete mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/AliasType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/AnyType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/ArrayType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/BooleanType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/CodegenException.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/DoubleType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/FloatType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/FunctionType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/GenericObjectType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/Int32Type.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/NativeModuleType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/NullableType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/NumberType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/ObjectType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/ReservedFunctionValueType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/StringType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/Type.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/TypeData.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/TypeId.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/model/VoidType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/AliasResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/Annotations.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/AnyResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ArrayResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/BooleanResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ClassNames.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java (98%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/GenericObjectResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/NativeModuleResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/NullableResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/NumberResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ObjectResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/PromiseResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ReactClassNames.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ReservedFunctionValueResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/ResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/StringResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/TypeResolver.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/TypeUtils.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java (100%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java (95%) rename packages/react-native-codegen/android/{gradlePlugin-build/gradlePlugin => }/src/main/java/com/facebook/react/codegen/plugin/CodegenPluginExtension.java (94%) delete mode 100644 packages/react-native-codegen/e2e/__tests__/modules/BUCK delete mode 100755 packages/react-native-codegen/src/cli/verify_with_old_codegen.js delete mode 100755 packages/react-native-codegen/src/cli/verify_with_old_codegen.sh rename Libraries/Components/Picker/PickerIOS.android.js => packages/react-native-codegen/src/generators/Utils.js (58%) create mode 100644 packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/PojoCollector.js create mode 100644 packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/index.js create mode 100644 packages/react-native-codegen/src/generators/components/GeneratePropsJavaPojo/serializePojo.js create mode 100644 packages/react-native-codegen/src/generators/components/__tests__/GeneratePropsJavaPojo-test.js create mode 100644 packages/react-native-codegen/src/generators/components/__tests__/__snapshots__/GeneratePropsJavaPojo-test.js.snap create mode 100644 packages/react-native-gradle-plugin/build.gradle.kts create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/AndroidConfiguration.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppExtension.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactAppPlugin.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleJsAndAssetsTask.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/HermesBinaryTask.kt create mode 100644 packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/TaskUtils.kt create mode 100644 packages/rn-tester/RNTester/Images.xcassets/customColor.colorset/Contents.json delete mode 100644 packages/rn-tester/js/assets/bottom-nav-center-box.png delete mode 100644 packages/rn-tester/js/components/ExamplePage.js create mode 100644 packages/rn-tester/js/components/RNTConfigurationBlock.js create mode 100644 packages/rn-tester/js/components/RNTOption.js create mode 100644 packages/rn-tester/js/components/RNTPressableRow.js create mode 100644 packages/rn-tester/js/components/RNTTestDetails.js rename packages/rn-tester/js/components/{RNTesterHeader.js => RNTTitleBar.js} (78%) delete mode 100644 packages/rn-tester/js/components/RNTesterExampleContainer.js create mode 100644 packages/rn-tester/js/components/RNTesterModuleContainer.js rename packages/rn-tester/js/components/{RNTesterExampleList.js => RNTesterModuleList.js} (83%) delete mode 100644 packages/rn-tester/js/examples/Animated/AnimatedExample.js create mode 100644 packages/rn-tester/js/examples/Animated/AnimatedIndex.js create mode 100644 packages/rn-tester/js/examples/Animated/ComposeAnimationsWithEasingExample.js create mode 100644 packages/rn-tester/js/examples/Animated/ComposingExample.js create mode 100644 packages/rn-tester/js/examples/Animated/ContinuousInteractionsExample.js create mode 100644 packages/rn-tester/js/examples/Animated/EasingExample.js create mode 100644 packages/rn-tester/js/examples/Animated/FadeInViewExample.js create mode 100644 packages/rn-tester/js/examples/Animated/LoopingExample.js create mode 100644 packages/rn-tester/js/examples/Animated/MovingBoxExample.js create mode 100644 packages/rn-tester/js/examples/Animated/RotatingImagesExample.js create mode 100644 packages/rn-tester/js/examples/Animated/TransformBounceExample.js create mode 100644 packages/rn-tester/js/examples/Animated/TransformStylesExample.js create mode 100644 packages/rn-tester/js/examples/Animated/utils/ToggleNativeDriver.js rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExApp.js (95%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExBobble.js (100%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExChained.js (94%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExScroll.js (100%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExSet.js (100%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExSlides.md (100%) rename packages/rn-tester/js/examples/{Animated => }/AnimatedGratuitousApp/AnExTilt.js (98%) create mode 100644 packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js create mode 100644 packages/rn-tester/js/examples/FlatList/FlatList-onViewableItemsChanged.js create mode 100644 packages/rn-tester/js/examples/FlatList/FlatList-withSeparators.js create mode 100644 packages/rn-tester/js/examples/FlatList/FlatListExamples.js create mode 100644 packages/rn-tester/js/examples/Modal/ModalOnShow.js create mode 100644 packages/rn-tester/js/examples/Modal/ModalPresentation.js create mode 100644 packages/rn-tester/js/examples/ScrollView/ScrollViewIndicatorInsetsExample.ios.js create mode 100644 packages/rn-tester/js/examples/ScrollView/ScrollViewIndicatorInsetsExample.macos.js create mode 100644 packages/rn-tester/js/examples/ScrollView/ScrollViewPressableStickyHeaderExample.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-contentInset.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-inverted.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-scrollable.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-stickyHeadersEnabled.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js delete mode 100644 packages/rn-tester/js/examples/SectionList/SectionListExample.js create mode 100644 packages/rn-tester/js/examples/SectionList/SectionListIndex.js create mode 100644 packages/rn-tester/js/examples/SwipeableCardExample/SwipeableCardExample.js create mode 100644 packages/rn-tester/js/examples/Text/TextAdjustsDynamicLayoutExample.js create mode 100644 packages/rn-tester/yarn.lock create mode 100644 scripts/codegen.js create mode 100755 scripts/find-node.sh delete mode 100755 scripts/generate-native-modules-specs.sh delete mode 100755 scripts/generate-rncore.sh rename scripts/{generate-native-modules-specs-cli.js => generate-specs-cli.js} (65%) create mode 100755 scripts/generate-specs.sh create mode 100644 scripts/lint-java.js create mode 100755 scripts/update_podfile_lock.sh create mode 100644 template/_editorconfig create mode 100644 template/_gitattributes create mode 100644 third-party-podspecs/boost.podspec delete mode 100644 third-party-podspecs/libevent.podspec create mode 100644 tools/build_defs/apple/config_utils_defs.bzl rename packages/react-native-codegen/src/cli/verify_all_modules_with_old_codegen.sh => tools/build_defs/apple/fb_apple_asset_catalog.bzl (58%) mode change 100755 => 100644 create mode 100644 tools/build_defs/apple/fb_apple_bundle.bzl create mode 100644 tools/build_defs/apple/fb_apple_test.bzl create mode 100644 tools/build_defs/apple/fb_js_dep.bzl create mode 100644 tools/build_defs/apple/flag_defs.bzl create mode 100644 tools/build_defs/apple/plugins/plugin_defs.bzl create mode 100644 tools/build_defs/fb_xplat_platform_specific_rule.bzl create mode 100644 tools/build_defs/fb_xplat_resource.bzl create mode 100644 tools/build_defs/js_glob.bzl create mode 100644 tools/build_defs/oss/metro_defs.bzl diff --git a/.buckconfig b/.buckconfig index 0740647479601e..07ec813646f170 100644 --- a/.buckconfig +++ b/.buckconfig @@ -1,6 +1,6 @@ [android] - target = android-29 + target = android-30 [download] max_number_of_retries = 3 @@ -8,7 +8,6 @@ [maven_repositories] central = https://repo1.maven.org/maven2 google = https://maven.google.com/ - jcenter = https://jcenter.bintray.com/ [alias] rntester = //packages/rn-tester/android/app:app diff --git a/.circleci/Dockerfiles/Dockerfile.android b/.circleci/Dockerfiles/Dockerfile.android index 23513414924ed2..96a361b9fa5ebb 100644 --- a/.circleci/Dockerfiles/Dockerfile.android +++ b/.circleci/Dockerfiles/Dockerfile.android @@ -14,7 +14,7 @@ # and build a Android application that can be used to run the # tests specified in the scripts/ directory. # -FROM reactnativecommunity/react-native-android:2.1 +FROM reactnativecommunity/react-native-android:4.0 LABEL Description="React Native Android Test Image" LABEL maintainer="Héctor Ramos " @@ -26,6 +26,7 @@ ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8" ADD .buckconfig /app/.buckconfig ADD .buckjavaargs /app/.buckjavaargs +ADD BUCK /app/BUCK ADD Libraries /app/Libraries ADD ReactAndroid /app/ReactAndroid ADD ReactCommon /app/ReactCommon diff --git a/.circleci/config.yml b/.circleci/config.yml index 8d15b406196098..baa53e7220cf91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,10 +15,10 @@ defaults: &defaults environment: - GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1 # The public github tokens are publicly visible by design - - PUBLIC_PULLBOT_GITHUB_TOKEN_A: "a6edf8e8d40ce4e8b11a" - - PUBLIC_PULLBOT_GITHUB_TOKEN_B: "150e1341f4dd9c944d2a" - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_token_a "78a72af35445ca3f8180" - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_token_b "b1a98e0bbd56ff1ccba1" + - PUBLIC_PULLBOT_GITHUB_TOKEN_A: &github_pullbot_token_a "a6edf8e8d40ce4e8b11a" + - PUBLIC_PULLBOT_GITHUB_TOKEN_B: &github_pullbot_token_b "150e1341f4dd9c944d2a" + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_analysisbot_token_a "312d354b5c36f082cfe9" + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_analysisbot_token_b "07973d757026bdd9f196" # ------------------------- # EXECUTORS @@ -27,6 +27,7 @@ executors: nodelts: <<: *defaults docker: + # Note: Version set separately for Windows builds, see below. - image: circleci/node:14 nodeprevlts: <<: *defaults @@ -35,7 +36,7 @@ executors: reactnativeandroid: <<: *defaults docker: - - image: reactnativecommunity/react-native-android:2.1 + - image: reactnativecommunity/react-native-android:4.0 resource_class: "large" environment: - TERM: "dumb" @@ -44,12 +45,14 @@ executors: - GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError"' - BUILD_THREADS: 2 # Repeated here, as the environment key in this executor will overwrite the one in defaults - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_token_a - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_token_b + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_analysisbot_token_a + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_analysisbot_token_b + - PUBLIC_PULLBOT_GITHUB_TOKEN_A: *github_pullbot_token_a + - PUBLIC_PULLBOT_GITHUB_TOKEN_B: *github_pullbot_token_b reactnativeios: <<: *defaults macos: - xcode: &_XCODE_VERSION "12.1.0" + xcode: &_XCODE_VERSION "12.5.0" # ------------------------- # COMMANDS @@ -75,7 +78,6 @@ commands: - restore_cache: keys: - v4-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} - - v4-yarn-cache-{{ arch }} - run: name: "Yarn: Install Dependencies" command: | @@ -94,7 +96,6 @@ commands: - restore_cache: keys: - v3-buck-v2019.01.10.01-{{ checksum "scripts/circleci/buck_fetch.sh" }}} - - v3-buck-v2019.01.10.01- - run: name: Install BUCK command: | @@ -151,20 +152,20 @@ commands: command: cp packages/rn-tester/Podfile.lock packages/rn-tester/Podfile.lock.bak - restore_cache: keys: - - v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }} - - v3-pods-{{ .Environment.CIRCLE_JOB }}- + # The committed lockfile is generated using USE_FRAMEWORKS=0 and USE_HERMES=0 so it could load an outdated cache if a change + # only affects the frameworks or hermes config. To help prevent this also cache based on the content of Podfile. + - v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} - steps: << parameters.steps >> - save_cache: paths: - packages/rn-tester/Pods - key: v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }} + key: v3-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} download_gradle_dependencies: steps: - restore_cache: keys: - v1-gradle-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }} - - v1-gradle- - run: name: Download Dependencies Using Gradle command: ./scripts/circleci/gradle_download_deps.sh @@ -236,17 +237,20 @@ jobs: # Issues will be posted to the PR itself via GitHub bots. # This workflow should only fail if the bots fail to run. analyze_pr: - executor: nodelts + executor: reactnativeandroid steps: - restore_cache_checkout: - checkout_type: node + checkout_type: android - run_yarn - install_github_bot_deps + # Note: The yarn gpg key needs to be refreshed to work around https://github.com/yarnpkg/yarn/issues/7866 - run: name: Install additional GitHub bot dependencies - command: sudo apt update && sudo apt install -y shellcheck jq + command: | + curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - + apt update && apt install -y shellcheck jq - run: name: Run linters against modified files (analysis-bot) @@ -264,10 +268,10 @@ jobs: # JOBS: Analyze Code # ------------------------- analyze_code: - executor: nodelts + executor: reactnativeandroid steps: - restore_cache_checkout: - checkout_type: node + checkout_type: android - setup_artifacts - run_yarn @@ -276,6 +280,11 @@ jobs: command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml when: always + - run: + name: Lint Java + command: scripts/circleci/exec_swallow_error.sh yarn lint-java --check + when: always + - run: name: Check for errors in code using Flow (iOS) command: yarn flow-check-ios @@ -423,7 +432,7 @@ jobs: steps: - run: name: Generate RNTesterPods Workspace - command: cd packages/rn-tester && bundle exec pod install --verbose + command: cd packages/rn-tester && USE_FABRIC=1 bundle exec pod install --verbose # ------------------------- # Runs iOS unit tests @@ -495,12 +504,6 @@ jobs: command: source scripts/android-setup.sh && launchAVD background: true - # Keep configuring Android dependencies while AVD boots up - - - run: - name: Install rsync, zip - command: apt-get update -y && apt-get install rsync zip -y - # Install Buck - install_buck_tooling @@ -606,14 +609,21 @@ jobs: default: false environment: - ANDROID_HOME: "C:\\Android\\android-sdk" - - ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\19.2.5345600" - - ANDROID_BUILD_VERSION: 28 - - ANDROID_TOOLS_VERSION: 29.0.3 + - ANDROID_NDK: "C:\\Android\\android-sdk\\ndk\\20.1.5948944" + - ANDROID_BUILD_VERSION: 30 + - ANDROID_TOOLS_VERSION: 30.0.2 - GRADLE_OPTS: -Dorg.gradle.daemon=false - - NDK_VERSION: 19.2.5345600 + - NDK_VERSION: 21.4.7075529 steps: - checkout + - run: + name: Install Node + # Note: Version set separately for non-Windows builds, see above. + command: | + nvm install 14.17.0 + nvm use 14.17.0 + # Setup Dependencies - run: name: Install Yarn @@ -626,7 +636,6 @@ jobs: - restore_cache: keys: - v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} - - v1-win-yarn-cache-{{ arch }}- - run: name: "Yarn: Install Dependencies" command: yarn install --frozen-lockfile --non-interactive @@ -635,9 +644,11 @@ jobs: paths: - C:\Users\circleci\AppData\Local\Yarn + # Try to install the SDK up to 3 times, since network flakiness can cause install failures + # Using a timeout of 9 mins, as circle ci will timeout if there is no output for 10 mins - run: name: Install Android SDK Tools - command: choco install android-sdk + command: choco install android-sdk --timeout 540; if (!$?) { choco install android-sdk --timeout 540 --force --forcedependencies}; if (!$?) { choco install android-sdk --force --forcedependencies} - run: name: Setup Android SDKs @@ -778,30 +789,34 @@ workflows: run_unit_tests: true requires: - setup_ios - - test_ios: - name: test_ios_unit_frameworks_jsc - use_frameworks: true - run_unit_tests: true - requires: - - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper + # - test_ios: + # name: test_ios_unit_frameworks_jsc + # use_frameworks: true + # run_unit_tests: true + # requires: + # - setup_ios - test_ios: name: test_ios_unit_hermes use_hermes: true run_unit_tests: true requires: - setup_ios - - test_ios: - name: test_ios_unit_frameworks_hermes - use_hermes: true - use_frameworks: true - run_unit_tests: true - requires: - - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper + # - test_ios: + # name: test_ios_unit_frameworks_hermes + # use_hermes: true + # use_frameworks: true + # run_unit_tests: true + # requires: + # - setup_ios + # DISABLED: Detox tests need to be fixed # - test_ios: # name: test_ios_detox # run_detox_tests: true # requires: # - setup_ios + # DISABLED: USE_FRAMEWORKS=1 not supported by Flipper # - test_ios: # name: test_ios_detox_frameworks # use_frameworks: true @@ -856,11 +871,18 @@ workflows: analysis: jobs: - - setup + - setup: + name: setup_js + + - setup: + name: setup_android + checkout_type: android + executor: reactnativeandroid + # Run lints on every commit other than those to the gh-pages branch - analyze_code: requires: - - setup + - setup_android filters: branches: ignore: gh-pages @@ -868,7 +890,7 @@ workflows: # Run code checks on PRs from forks - analyze_pr: requires: - - setup + - setup_android filters: branches: only: /^pull\/.*$/ @@ -876,7 +898,7 @@ workflows: # Gather coverage - js_coverage: requires: - - setup + - setup_js # [TODO(macOS GH#774): disable this test, it fails in the fork due to not being set up for coveralls filters: branches: @@ -891,7 +913,7 @@ workflows: # [TODO(macOS GH#774): disable this release. We never want to release anything from this fork via CCI. ignore: /.*/ # only: - # - master + # - main # ]TODO(macOS GH#774) jobs: - nightly_job diff --git a/.editorconfig b/.editorconfig index 45dc2a9a3fecd4..355a800148a2d9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,5 +13,12 @@ indent_size = 2 [*.gradle] indent_size = 4 +[*.kts] +indent_size = 4 + [BUCK] indent_size = 4 + +# Windows files +[*.bat] +end_of_line = crlf diff --git a/.eslintrc b/.eslintrc index 2c5a51053d8221..f990717831deb2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -21,6 +21,14 @@ "@react-native/codegen/react-native-modules": 2 } }, + { + "files": [ + "flow-typed/**/*.js", + ], + "rules": { + quotes: 0 + } + }, { "files": [ "**/__fixtures__/**/*.js", diff --git a/.flowconfig b/.flowconfig index e45052fc3424cd..f763d569d9486c 100644 --- a/.flowconfig +++ b/.flowconfig @@ -35,6 +35,9 @@ flow/ emoji=true exact_by_default=true +indexed_access=false + +format.bracket_spacing=false module.file_ext=.js module.file_ext=.json @@ -52,15 +55,13 @@ 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 @@ -75,4 +76,4 @@ untyped-import untyped-type-import [version] -^0.137.0 +^0.158.0 diff --git a/.flowconfig.android b/.flowconfig.android index 1fe01b8ea01f8b..ff3d0c92033437 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -35,6 +35,9 @@ flow/ emoji=true exact_by_default=true +indexed_access=false + +format.bracket_spacing=false module.file_ext=.js module.file_ext=.json @@ -55,15 +58,13 @@ 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 @@ -78,4 +79,4 @@ untyped-import untyped-type-import [version] -^0.137.0 +^0.158.0 diff --git a/.flowconfig.macos b/.flowconfig.macos index 46e8755cec24ac..08ffca1b0204e2 100644 --- a/.flowconfig.macos +++ b/.flowconfig.macos @@ -34,9 +34,6 @@ flow/ [options] emoji=true -esproposal.optional_chaining=enable -esproposal.nullish_coalescing=enable - exact_by_default=true module.file_ext=.js @@ -55,8 +52,6 @@ suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState suppress_type=$FlowFixMeEmpty -well_formed_exports=true -types_first=true experimental.abstract_locations=true [lints] @@ -81,4 +76,4 @@ untyped-import untyped-type-import [version] -^0.137.0 +^0.158.0 diff --git a/.gitattributes b/.gitattributes index eaf618cafb2032..7c973903433b65 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,4 @@ *.sh text eol=lf # Windows files should use crlf line endings # https://help.github.com/articles/dealing-with-line-endings/ -*.bat text eol=crlf \ No newline at end of file +*.bat text eol=crlf diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 4e313c997e3094..e597d1e3334e5a 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -27,7 +27,7 @@ If you'd like to discuss topics related to the future of React Native, please ch If you want to participate in casual discussions about the use of React Native, consider participating in one of the following forums: -- [Reactiflux Discord Server](https://www.reactiflux) +- [Reactiflux Discord Server](https://www.reactiflux.com) - [Spectrum Chat](https://spectrum.chat/react-native) - [React Native Community Facebook Group](https://www.facebook.com/groups/react.native.community) diff --git a/.github/label-actions.yml b/.github/respond-to-issue-based-on-label.yml similarity index 96% rename from .github/label-actions.yml rename to .github/respond-to-issue-based-on-label.yml index 8cef0647e0068c..65131ff0840db0 100644 --- a/.github/label-actions.yml +++ b/.github/respond-to-issue-based-on-label.yml @@ -1,4 +1,4 @@ -# Configuration for Label Actions - https://github.com/marketplace/actions/label-actions +# Configuration for Respond To Issue Based on Label https://github.com/marketplace/actions/respond-to-issue-based-on-label "Type: Invalid": close: true diff --git a/.github/workflows/process-label-actions.yml b/.github/workflows/on-issue-labeled.yml similarity index 54% rename from .github/workflows/process-label-actions.yml rename to .github/workflows/on-issue-labeled.yml index 2c63100f6e8392..e68682b2ecb71b 100644 --- a/.github/workflows/process-label-actions.yml +++ b/.github/workflows/on-issue-labeled.yml @@ -1,16 +1,16 @@ -name: Label Actions +name: On Issue Labeled # This workflow is triggered when a label is added to an issue. on: issues: types: labeled jobs: - processLabelAction: - name: Process Label Action + respondToIssueBasedOnLabel: + name: Respond to Issue Based on Label runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Process Label Action - uses: hramos/label-actions@v1 + - name: Respond to Issue Based on Label + uses: hramos/respond-to-issue-based-on-label@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index c9ad5eacf11c52..eebf7dd21c678b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ project.xcworkspace/* # Gradle /build/ /packages/react-native-codegen/android/build/ -/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build +/packages/react-native-gradle-plugin/build/ /packages/rn-tester/android/app/.cxx/ /packages/rn-tester/android/app/build/ /packages/rn-tester/android/app/gradle/ @@ -94,9 +94,9 @@ package-lock.json # Libs that shouldn't have Xcode project /Libraries/FBLazyVector/**/*.xcodeproj -/Libraries/FBReactNativeSpec/**/*.xcodeproj /Libraries/RCTRequired/**/*.xcodeproj /React/CoreModules/**/*.xcodeproj +/React/FBReactNativeSpec/**/*.xcodeproj /packages/react-native-codegen/**/*.xcodeproj # CocoaPods @@ -109,10 +109,10 @@ package-lock.json !/packages/rn-tester/Pods/__offline_mirrors__ # react-native-codegen -/Libraries/FBReactNativeSpec/FBReactNativeSpec +/React/FBReactNativeSpec/FBReactNativeSpec /packages/react-native-codegen/lib -/ReactCommon/fabric/components/rncore/ -/schema-rncore.json +/ReactCommon/react/renderer/components/rncore/ +/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec* # Visual studio .vscode diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index dba04c1e1786b2..00000000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -8.11.3 diff --git a/BUCK b/BUCK new file mode 100644 index 00000000000000..b315295c974f53 --- /dev/null +++ b/BUCK @@ -0,0 +1,1386 @@ +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/apple:config_utils_defs.bzl", "STATIC_LIBRARY_APPLETVOS_CONFIG", "fbobjc_configs") +load("//tools/build_defs/apple:fb_apple_test.bzl", "fb_apple_test") +load("//tools/build_defs/apple:flag_defs.bzl", "get_base_appletvos_flags", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") +load("//tools/build_defs/apple/plugins:plugin_defs.bzl", "plugin") +load("//tools/build_defs/oss:metro_defs.bzl", "rn_library") +load( + "//tools/build_defs/oss:rn_codegen_defs.bzl", + "rn_codegen", + "rn_codegen_components", +) +load( + "//tools/build_defs/oss:rn_defs.bzl", + "APPLETVOS", + "HERMES_BYTECODE_VERSION", + "IOS", + "RCT_IMAGE_DATA_DECODER_SOCKET", + "RCT_IMAGE_URL_LOADER_SOCKET", + "RCT_URL_REQUEST_HANDLER_SOCKET", + "YOGA_CXX_TARGET", + "react_fabric_component_plugin_provider", + "react_module_plugin_providers", + "react_native_root_target", + "react_native_xplat_dep", + "react_native_xplat_target", + "rn_apple_library", + "rn_extra_build_flags", + "rn_xplat_cxx_library2", + "subdir_glob", +) +load("//tools/build_defs/third_party:yarn_defs.bzl", "yarn_workspace") + +RCTCXXBRIDGE_PUBLIC_HEADERS = { + "React/" + x: "React/CxxBridge/" + x + for x in [ + "JSCExecutorFactory.h", + "NSDataBigString.h", + "RCTCxxBridgeDelegate.h", + "RCTMessageThread.h", + ] +} + +fb_native.genrule( + name = "codegen_rn_components_schema_rncore", + srcs = glob( + [ + "Libraries/**/*NativeComponent.js", + "jest/**/*NativeComponent.js", + "packages/**/*NativeComponent.js", + ], + exclude = [ + "**/__*__/**", + + # Subfolders with their own BUCK files, referenced below + "packages/rn-tester/**", + ], + ) + [ + react_native_root_target("packages/rn-tester:nativecomponent-srcs"), + ], + cmd = "$(exe {}) $OUT $SRCS".format(react_native_root_target("packages/react-native-codegen:write_to_json")), + out = "schema-rncore.json", +) + +rn_codegen_components( + name = "rncore", + schema_target = ":codegen_rn_components_schema_rncore", +) + +rn_xplat_cxx_library2( + name = "RCTCxxBridge", + srcs = glob([ + "React/CxxBridge/*.mm", + ]), + headers = subdir_glob( + [ + ( + "React/CxxBridge", + "*.h", + ), + ], + exclude = RCTCXXBRIDGE_PUBLIC_HEADERS.values(), + prefix = "React", + ), + header_namespace = "", + exported_headers = RCTCXXBRIDGE_PUBLIC_HEADERS, + compiler_flags = [ + "-fobjc-arc-exceptions", + ], + contacts = ["oncall+react_native@xmail.facebook.com"], + exported_preprocessor_flags = rn_extra_build_flags(), + fbobjc_enable_exceptions = True, + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + ], + # Used via objc_lookupClass in RCTBridge. Semantics are meant to be "if + # it's linked in your app, transparently use it". + labels = [ + "depslint_never_remove", + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + [ + "-DWITH_FBSYSTRACE=1", + "-DRCT_USE_HERMES=0", # This is the default. + ], + visibility = ["PUBLIC"], + deps = [ + ":RCTCxxModule", + ":RCTCxxUtils", + ":ReactInternal", + "//fbobjc/Libraries/FBReactKit:RCTFBSystrace", + "//xplat/folly:molly", + react_native_root_target("React/CoreModules:CoreModules"), + react_native_xplat_target("cxxreact:bridge"), + react_native_xplat_target("cxxreact:jsbigstring"), + react_native_xplat_target("jsi:JSCRuntime"), + react_native_xplat_target("jsiexecutor:jsiexecutor"), + react_native_xplat_target("reactperflogger:reactperflogger"), + ], +) + +RCTCXXMODULE_PUBLIC_HEADERS = { + "React/" + x: "React/CxxModule/" + x + for x in [ + "RCTCxxMethod.h", + "RCTCxxModule.h", + "RCTCxxUtils.h", + ] +} + +rn_xplat_cxx_library2( + name = "RCTCxxModule", + srcs = glob([ + "React/CxxModule/*.mm", + ]), + headers = subdir_glob( + [ + ( + "React/CxxModule", + "*.h", + ), + ], + exclude = RCTCXXMODULE_PUBLIC_HEADERS.values(), + prefix = "React", + ), + header_namespace = "", + exported_headers = RCTCXXMODULE_PUBLIC_HEADERS, + compiler_flags = [ + "-fobjc-arc-exceptions", + ], + contacts = ["oncall+react_native@xmail.facebook.com"], + fbobjc_enable_exceptions = True, + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + ], + labels = ["supermodule:xplat/default/public.react_native.infra"], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + ["-DWITH_FBSYSTRACE=1"], + visibility = ["PUBLIC"], + deps = [ + ":RCTCxxUtils", + ":ReactInternal", + "//xplat/fbsystrace:fbsystrace", + "//xplat/folly:headers_only", + react_native_xplat_target("cxxreact:module"), + react_native_xplat_target("cxxreact:bridge"), + react_native_xplat_target("reactperflogger:reactperflogger"), + react_native_xplat_dep("jsi:jsi"), + ], +) + +rn_xplat_cxx_library2( + name = "RCTCxxUtils", + srcs = glob([ + "React/CxxUtils/*.mm", + ]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "React/CxxUtils", + "*.h", + ), + ], + exclude = RCTCXXMODULE_PUBLIC_HEADERS.values(), + prefix = "React", + ), + apple_sdks = (IOS, APPLETVOS), + appletvos_configs = fbobjc_configs(STATIC_LIBRARY_APPLETVOS_CONFIG), + appletvos_inherited_buck_flags = get_base_appletvos_flags(), + contacts = ["oncall+react_native@xmail.facebook.com"], + fbobjc_enable_exceptions = True, + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + ], + labels = ["supermodule:xplat/default/public.react_native.infra"], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + "//xplat/folly:molly", + ], +) + +RCTLIB_PATH = "Libraries/" + +RCTBASE_PATH = "React/Base/" + +RCTDEVSUPPORT_PATH = "React/DevSupport/" + +RCTMODULES_PATH = "React/Modules/" + +RCTVIEWS_PATH = "React/Views/" + +REACT_PUBLIC_HEADERS = { + "React/RCTAnimationType.h": RCTVIEWS_PATH + "RCTAnimationType.h", + "React/RCTAssert.h": RCTBASE_PATH + "RCTAssert.h", + "React/RCTAutoInsetsProtocol.h": RCTVIEWS_PATH + "RCTAutoInsetsProtocol.h", + "React/RCTBorderDrawing.h": RCTVIEWS_PATH + "RCTBorderDrawing.h", + "React/RCTBorderStyle.h": RCTVIEWS_PATH + "RCTBorderStyle.h", + "React/RCTBridge+Private.h": RCTBASE_PATH + "RCTBridge+Private.h", + "React/RCTBridge.h": RCTBASE_PATH + "RCTBridge.h", + "React/RCTBridgeDelegate.h": RCTBASE_PATH + "RCTBridgeDelegate.h", + "React/RCTBridgeMethod.h": RCTBASE_PATH + "RCTBridgeMethod.h", + "React/RCTBridgeModule.h": RCTBASE_PATH + "RCTBridgeModule.h", + "React/RCTBundleURLProvider.h": RCTBASE_PATH + "RCTBundleURLProvider.h", + "React/RCTComponent.h": RCTVIEWS_PATH + "RCTComponent.h", + "React/RCTComponentData.h": RCTVIEWS_PATH + "RCTComponentData.h", + "React/RCTComponentEvent.h": RCTBASE_PATH + "RCTComponentEvent.h", + "React/RCTConstants.h": RCTBASE_PATH + "RCTConstants.h", + "React/RCTConvert.h": RCTBASE_PATH + "RCTConvert.h", + "React/RCTCxxConvert.h": RCTBASE_PATH + "RCTCxxConvert.h", + "React/RCTDefines.h": RCTBASE_PATH + "RCTDefines.h", + "React/RCTDevLoadingViewProtocol.h": RCTDEVSUPPORT_PATH + "RCTDevLoadingViewProtocol.h", + "React/RCTDevLoadingViewSetEnabled.h": RCTDEVSUPPORT_PATH + "RCTDevLoadingViewSetEnabled.h", + "React/RCTDisplayLink.h": RCTBASE_PATH + "RCTDisplayLink.h", + "React/RCTErrorCustomizer.h": RCTBASE_PATH + "RCTErrorCustomizer.h", + "React/RCTErrorInfo.h": RCTBASE_PATH + "RCTErrorInfo.h", + # NOTE: RCTEventDispatcher.h is exported from CoreModules:CoreModulesApple + "React/RCTEventDispatcherProtocol.h": RCTBASE_PATH + "RCTEventDispatcherProtocol.h", + "React/RCTEventEmitter.h": RCTMODULES_PATH + "RCTEventEmitter.h", + "React/RCTFont.h": RCTVIEWS_PATH + "RCTFont.h", + "React/RCTFrameUpdate.h": RCTBASE_PATH + "RCTFrameUpdate.h", + "React/RCTI18nUtil.h": RCTMODULES_PATH + "RCTI18nUtil.h", + "React/RCTImageSource.h": RCTBASE_PATH + "RCTImageSource.h", + "React/RCTInitializing.h": RCTBASE_PATH + "RCTInitializing.h", + "React/RCTInspector.h": "React/Inspector/RCTInspector.h", + "React/RCTInspectorDevServerHelper.h": RCTDEVSUPPORT_PATH + "RCTInspectorDevServerHelper.h", + "React/RCTInspectorPackagerConnection.h": "React/Inspector/RCTInspectorPackagerConnection.h", + "React/RCTInvalidating.h": RCTBASE_PATH + "RCTInvalidating.h", + "React/RCTJSScriptLoaderModule.h": RCTBASE_PATH + "RCTJSScriptLoaderModule.h", + "React/RCTJSStackFrame.h": RCTBASE_PATH + "RCTJSStackFrame.h", + "React/RCTJavaScriptExecutor.h": RCTBASE_PATH + "RCTJavaScriptExecutor.h", + "React/RCTJavaScriptLoader.h": RCTBASE_PATH + "RCTJavaScriptLoader.h", + "React/RCTKeyCommands.h": RCTBASE_PATH + "RCTKeyCommands.h", + "React/RCTLayout.h": RCTVIEWS_PATH + "RCTLayout.h", + "React/RCTLayoutAnimation.h": RCTMODULES_PATH + "RCTLayoutAnimation.h", + "React/RCTLayoutAnimationGroup.h": RCTMODULES_PATH + "RCTLayoutAnimationGroup.h", + "React/RCTLog.h": RCTBASE_PATH + "RCTLog.h", + "React/RCTManagedPointer.h": RCTBASE_PATH + "RCTManagedPointer.h", + "React/RCTModalHostViewController.h": RCTVIEWS_PATH + "RCTModalHostViewController.h", + "React/RCTModalHostViewManager.h": RCTVIEWS_PATH + "RCTModalHostViewManager.h", + "React/RCTModalManager.h": RCTVIEWS_PATH + "RCTModalManager.h", + "React/RCTModuleData.h": RCTBASE_PATH + "RCTModuleData.h", + "React/RCTModuleMethod.h": RCTBASE_PATH + "RCTModuleMethod.h", + "React/RCTMultipartStreamReader.h": RCTBASE_PATH + "RCTMultipartStreamReader.h", + "React/RCTNullability.h": RCTBASE_PATH + "RCTNullability.h", + "React/RCTPackagerClient.h": RCTDEVSUPPORT_PATH + "RCTPackagerClient.h", + "React/RCTPackagerConnection.h": RCTDEVSUPPORT_PATH + "RCTPackagerConnection.h", + "React/RCTPerformanceLogger.h": RCTBASE_PATH + "RCTPerformanceLogger.h", + "React/RCTPointerEvents.h": RCTVIEWS_PATH + "RCTPointerEvents.h", + "React/RCTProfile.h": "React/Profiler/RCTProfile.h", + "React/RCTPushNotificationManager.h": RCTLIB_PATH + "PushNotificationIOS/RCTPushNotificationManager.h", + "React/RCTReconnectingWebSocket.h": RCTLIB_PATH + "WebSocket/RCTReconnectingWebSocket.h", + "React/RCTRedBoxExtraDataViewController.h": RCTMODULES_PATH + "RCTRedBoxExtraDataViewController.h", + "React/RCTRedBoxSetEnabled.h": RCTBASE_PATH + "RCTRedBoxSetEnabled.h", + "React/RCTRefreshableProtocol.h": RCTVIEWS_PATH + "RefreshControl/RCTRefreshableProtocol.h", + "React/RCTReloadCommand.h": RCTBASE_PATH + "RCTReloadCommand.h", + "React/RCTRootContentView.h": RCTBASE_PATH + "RCTRootContentView.h", + "React/RCTRootShadowView.h": RCTVIEWS_PATH + "RCTRootShadowView.h", + "React/RCTRootView.h": RCTBASE_PATH + "RCTRootView.h", + "React/RCTRootViewDelegate.h": RCTBASE_PATH + "RCTRootViewDelegate.h", + "React/RCTSRWebSocket.h": RCTLIB_PATH + "WebSocket/RCTSRWebSocket.h", + "React/RCTScrollEvent.h": RCTVIEWS_PATH + "ScrollView/RCTScrollEvent.h", + "React/RCTScrollView.h": RCTVIEWS_PATH + "ScrollView/RCTScrollView.h", + "React/RCTScrollableProtocol.h": RCTVIEWS_PATH + "ScrollView/RCTScrollableProtocol.h", + "React/RCTShadowView+Layout.h": RCTVIEWS_PATH + "RCTShadowView+Layout.h", + "React/RCTShadowView.h": RCTVIEWS_PATH + "RCTShadowView.h", + "React/RCTSurface.h": RCTBASE_PATH + "Surface/RCTSurface.h", + "React/RCTSurfaceDelegate.h": RCTBASE_PATH + "Surface/RCTSurfaceDelegate.h", + "React/RCTSurfaceHostingProxyRootView.h": RCTBASE_PATH + "Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h", + "React/RCTSurfaceHostingView.h": RCTBASE_PATH + "Surface/SurfaceHostingView/RCTSurfaceHostingView.h", + "React/RCTSurfacePresenterStub.h": RCTMODULES_PATH + "RCTSurfacePresenterStub.h", + "React/RCTSurfaceProtocol.h": RCTBASE_PATH + "Surface/RCTSurfaceProtocol.h", + "React/RCTSurfaceRootShadowView.h": RCTBASE_PATH + "Surface/RCTSurfaceRootShadowView.h", + "React/RCTSurfaceRootShadowViewDelegate.h": RCTBASE_PATH + "Surface/RCTSurfaceRootShadowViewDelegate.h", + "React/RCTSurfaceRootView.h": RCTBASE_PATH + "Surface/RCTSurfaceRootView.h", + "React/RCTSurfaceSizeMeasureMode.h": RCTBASE_PATH + "Surface/SurfaceHostingView/RCTSurfaceSizeMeasureMode.h", + "React/RCTSurfaceStage.h": RCTBASE_PATH + "Surface/RCTSurfaceStage.h", + "React/RCTSurfaceView+Internal.h": RCTBASE_PATH + "Surface/RCTSurfaceView+Internal.h", + "React/RCTSurfaceView.h": RCTBASE_PATH + "Surface/RCTSurfaceView.h", + "React/RCTTextDecorationLineType.h": RCTVIEWS_PATH + "RCTTextDecorationLineType.h", + "React/RCTTouchHandler.h": RCTBASE_PATH + "RCTTouchHandler.h", + "React/RCTUIManager.h": RCTMODULES_PATH + "RCTUIManager.h", + "React/RCTUIManagerObserverCoordinator.h": RCTMODULES_PATH + "RCTUIManagerObserverCoordinator.h", + "React/RCTUIManagerUtils.h": RCTMODULES_PATH + "RCTUIManagerUtils.h", + "React/RCTUIUtils.h": "React/UIUtils/RCTUIUtils.h", + "React/RCTURLRequestDelegate.h": RCTBASE_PATH + "RCTURLRequestDelegate.h", + "React/RCTURLRequestHandler.h": RCTBASE_PATH + "RCTURLRequestHandler.h", + "React/RCTUtils.h": RCTBASE_PATH + "RCTUtils.h", + "React/RCTUtilsUIOverride.h": RCTBASE_PATH + "RCTUtilsUIOverride.h", + "React/RCTVersion.h": RCTBASE_PATH + "RCTVersion.h", + "React/RCTView.h": RCTVIEWS_PATH + "RCTView.h", + "React/RCTViewManager.h": RCTVIEWS_PATH + "RCTViewManager.h", + "React/RCTWeakProxy.h": RCTBASE_PATH + "RCTWeakProxy.h", + "React/RCTWeakViewHolder.h": RCTVIEWS_PATH + "RCTWeakViewHolder.h", + "React/RCTWrapperViewController.h": RCTVIEWS_PATH + "RCTWrapperViewController.h", + "React/UIView+React.h": RCTVIEWS_PATH + "UIView+React.h", +} + +REACT_COMPONENTVIEWS_BASE_FILES = [ + "React/Fabric/Mounting/ComponentViews/Image/*.mm", + "React/Fabric/RCTImageResponseObserverProxy.mm", + "React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm", +] + +rn_xplat_cxx_library2( + name = "ReactInternal", + srcs = glob( + [ + "React/Base/**/*.m", + "React/Base/**/*.mm", + "React/DevSupport/**/*.m", + "React/DevSupport/**/*.mm", + "React/Inspector/**/*.m", + "React/Inspector/**/*.mm", + "React/Modules/**/*.m", + "React/Modules/**/*.mm", + "React/Profiler/**/*.m", + "React/Profiler/**/*.mm", + "React/Profiler/**/*.S", + "React/UIUtils/*.m", + "React/Views/**/*.m", + "React/Views/**/*.mm", + "Libraries/ActionSheetIOS/*.m", + "Libraries/WebSocket/*.m", + ], + ), + headers = glob( + [ + "React/Base/**/*.h", + "React/DevSupport/**/*.h", + "React/Inspector/**/*.h", + "React/Modules/**/*.h", + "React/Profiler/**/*.h", + "React/Views/**/*.h", + "React/UIUtils/**/*.h", + "Libraries/ActionSheetIOS/*.h", + "Libraries/WebSocket/*.h", + ], + ), + header_namespace = "", + exported_headers = REACT_PUBLIC_HEADERS, + compiler_flags = [ + "-Wno-error=unguarded-availability-new", + "-Wno-unknown-warning-option", + "-Wno-global-constructors", + ], + contacts = ["oncall+react_native@xmail.facebook.com"], + exported_linker_flags = [ + "-weak_framework", + "UserNotifications", + "-weak_framework", + "WebKit", + ], + exported_preprocessor_flags = rn_extra_build_flags(), + fbobjc_enable_exceptions = True, + frameworks = [ + "$SDKROOT/System/Library/Frameworks/CFNetwork.framework", + "$SDKROOT/System/Library/Frameworks/CoreGraphics.framework", + "$SDKROOT/System/Library/Frameworks/CoreLocation.framework", + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + "$SDKROOT/System/Library/Frameworks/MapKit.framework", + "$SDKROOT/System/Library/Frameworks/QuartzCore.framework", + "$SDKROOT/System/Library/Frameworks/Security.framework", + "$SDKROOT/System/Library/Frameworks/SystemConfiguration.framework", + "$SDKROOT/System/Library/Frameworks/UIKit.framework", + "$SDKROOT/System/Library/Frameworks/UserNotifications.framework", + ], + labels = [ + "depslint_never_add", + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "supermodule:xplat/default/public.react_native.infra", + ], + platform_preprocessor_flags = [( + "linux", + ["-D PIC_MODIFIER=@PLT"], + )], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + [ + "-DHERMES_BYTECODE_VERSION={}".format(HERMES_BYTECODE_VERSION), + ] + rn_extra_build_flags(), + visibility = [ + "//fbobjc/Apps/Internal/SparkLabs/...", + "//fbobjc/Apps/Internal/Venice/...", + "//fbobjc/Apps/Wilde/FBMarketplaceModule/...", + "//fbobjc/Apps/Wilde/FBReactModule2/...", + "//fbobjc/Libraries/FBQPLMetadataProviders/...", + "//fbobjc/Libraries/FBReactKit/...", + "//fbobjc/Libraries/FBiOSSecurityUtils/...", + "//fbobjc/VendorLib/react-native-maps:react-native-maps", + "//xplat/js:", + "//xplat/js/react-native-github/React/...", + "//xplat/js/react-native-github/ReactCommon/react/nativemodule/core:", + "//xplat/js/react-native-github/ReactCommon/react/nativemodule/samples:", + "//xplat/js/react-native-github/packages/rn-tester:", + ], + deps = [ + YOGA_CXX_TARGET, + react_native_xplat_target("cxxreact:bridge"), + react_native_xplat_target("reactperflogger:reactperflogger"), + ], +) + +rn_xplat_cxx_library2( + name = "RCTFabric", + srcs = glob( + [ + "React/Fabric/**/*.cpp", + "React/Fabric/**/*.m", + "React/Fabric/**/*.mm", + ], + exclude = glob(REACT_COMPONENTVIEWS_BASE_FILES), + ), + headers = glob( + [ + "React/Fabric/**/*.h", + ], + ), + header_namespace = "", + exported_headers = { + "React/RCTComponentViewDescriptor.h": "React/Fabric/Mounting/RCTComponentViewDescriptor.h", + "React/RCTComponentViewFactory.h": "React/Fabric/Mounting/RCTComponentViewFactory.h", + "React/RCTComponentViewRegistry.h": "React/Fabric/Mounting/RCTComponentViewRegistry.h", + "React/RCTFabricSurface.h": "React/Fabric/Surface/RCTFabricSurface.h", + "React/RCTFabricSurfaceHostingProxyRootView.h": "React/Fabric/Surface/RCTFabricSurfaceHostingProxyRootView.h", + "React/RCTFabricSurfaceHostingView.h": "React/Fabric/Surface/RCTFabricSurfaceHostingView.h", + "React/RCTGenericDelegateSplitter.h": "React/Fabric/Utils/RCTGenericDelegateSplitter.h", + "React/RCTLegacyViewManagerInteropComponentView.h": "React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.h", + "React/RCTLocalizationProvider.h": "React/Fabric/RCTLocalizationProvider.h", + "React/RCTModalHostViewComponentView.h": "React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h", + "React/RCTMountingManager.h": "React/Fabric/Mounting/RCTMountingManager.h", + "React/RCTMountingManagerDelegate.h": "React/Fabric/Mounting/RCTMountingManagerDelegate.h", + "React/RCTMountingTransactionObserving.h": "React/Fabric/Mounting/RCTMountingTransactionObserving.h", + "React/RCTParagraphComponentAccessibilityProvider.h": "React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentAccessibilityProvider.h", + "React/RCTParagraphComponentView.h": "React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.h", + "React/RCTPrimitives.h": "React/Fabric/RCTPrimitives.h", + "React/RCTRootComponentView.h": "React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h", + "React/RCTScheduler.h": "React/Fabric/RCTScheduler.h", + "React/RCTScrollViewComponentView.h": "React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.h", + "React/RCTSurfacePresenter.h": "React/Fabric/RCTSurfacePresenter.h", + "React/RCTSurfacePresenterBridgeAdapter.h": "React/Fabric/RCTSurfacePresenterBridgeAdapter.h", + "React/RCTSurfaceRegistry.h": "React/Fabric/RCTSurfaceRegistry.h", + "React/RCTSurfaceTouchHandler.h": "React/Fabric/RCTSurfaceTouchHandler.h", + }, + compiler_flags = [ + "-fexceptions", + "-frtti", + "-std=c++17", + "-Wall", + ], + contacts = ["oncall+react_native@xmail.facebook.com"], + fbobjc_enable_exceptions = True, + fbobjc_target_sdk_version = "11.0", + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + "$SDKROOT/System/Library/Frameworks/QuartzCore.framework", + "$SDKROOT/System/Library/Frameworks/UIKit.framework", + ], + header_path_prefix = "React", + labels = [ + "disable_plugins_only_validation", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = [ + react_fabric_component_plugin_provider("SafeAreaView", "RCTSafeAreaViewCls"), + react_fabric_component_plugin_provider("ScrollView", "RCTScrollViewCls"), + react_fabric_component_plugin_provider("PullToRefreshView", "RCTPullToRefreshViewCls"), + react_fabric_component_plugin_provider("ActivityIndicatorView", "RCTActivityIndicatorViewCls"), + react_fabric_component_plugin_provider("Slider", "RCTSliderCls"), + react_fabric_component_plugin_provider("Switch", "RCTSwitchCls"), + react_fabric_component_plugin_provider("UnimplementedNativeView", "RCTUnimplementedNativeViewCls"), + react_fabric_component_plugin_provider("Paragraph", "RCTParagraphCls"), + react_fabric_component_plugin_provider("TextInput", "RCTTextInputCls"), + react_fabric_component_plugin_provider("InputAccessoryView", "RCTInputAccessoryCls"), + react_fabric_component_plugin_provider("View", "RCTViewCls"), + ], + plugins_header = "FBRCTFabricComponentsPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + [ + "-DWITH_FBSYSTRACE=1", + "-DLOG_TAG=\"ReactNative\"", + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ] + rn_extra_build_flags(), + tests = [ + ":MountingTests", + ":TextTests", + ], + visibility = ["PUBLIC"], + deps = [ + ":RCTFabricComponentViewsBase", + "//fbobjc/Libraries/FBReactKit/RCTFabricComponent/RCTFabricComponentPlugin:RCTFabricComponentPlugin", + "//xplat/js/react-native-github:RCTCxxBridge", + "//xplat/js/react-native-github:RCTCxxUtils", + "//xplat/js/react-native-github:RCTImage", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:RCTText", + "//xplat/js/react-native-github:ReactInternal", + react_native_xplat_target("react/renderer/attributedstring:attributedstring"), + react_native_xplat_target("react/renderer/componentregistry:componentregistry"), + react_native_xplat_target("react/renderer/componentregistry/native:native"), + react_native_xplat_target("react/renderer/textlayoutmanager:textlayoutmanager"), + react_native_xplat_target("runtimeexecutor:runtimeexecutor"), + YOGA_CXX_TARGET, + react_native_xplat_target("react/config:config"), + react_native_xplat_target("cxxreact:bridge"), + ], + exported_deps = [ + react_native_xplat_target("react/renderer/animations:animations"), + react_native_xplat_target("react/renderer/components/scrollview:scrollview"), + react_native_xplat_target("react/renderer/components/slider:slider"), + react_native_xplat_target("react/renderer/components/safeareaview:safeareaview"), + react_native_xplat_target("react/renderer/components/modal:modal"), + react_native_xplat_target("react/renderer/components/unimplementedview:unimplementedview"), + react_native_xplat_target("react/renderer/components/text:text"), + react_native_xplat_target("react/renderer/components/legacyviewmanagerinterop:legacyviewmanagerinterop"), + react_native_xplat_target("react/renderer/components/textinput/iostextinput:iostextinput"), + react_native_xplat_target("react/renderer/components/inputaccessory:inputaccessory"), + react_native_xplat_target("react/renderer/core:core"), + react_native_xplat_target("react/renderer/debug:debug"), + react_native_xplat_target("react/renderer/scheduler:scheduler"), + react_native_xplat_target("react/renderer/uimanager:uimanager"), + "//xplat/js/react-native-github:generated_components-rncore", + ], +) + +rn_apple_library( + name = "RCTTypeSafety", + srcs = glob([ + "Libraries/TypeSafety/**/*.mm", + ]), + exported_headers = glob( + [ + "Libraries/TypeSafety/**/*.h", + ], + ), + autoglob = False, + contacts = ["oncall+react_native@xmail.facebook.com"], + extension_api_only = True, + frameworks = [ + "$PLATFORM_DIR/Developer/Library/Frameworks/Foundation.framework", + ], + inherited_buck_flags = get_static_library_ios_flags(), + labels = ["supermodule:xplat/default/public.react_native.infra"], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + reexport_all_header_dependencies = True, + deps = [ + ":ReactInternalApple", + "//xplat/folly:optionalApple", + "//xplat/js/react-native-github/Libraries/FBLazyVector:FBLazyVector", + ], +) + +yarn_workspace( + name = "yarn-workspace", + srcs = [ + "package.json", + ], + visibility = ["PUBLIC"], +) + +fb_apple_test( + name = "TextTestsApple", + srcs = ["React/Tests/Text/RCTParagraphComponentViewTests.mm"], + frameworks = [ + "$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework", + ], + oncall = "react_native", + deps = [ + ":RCTFabricApple", + react_native_xplat_target("react/renderer/element:elementApple"), + "//xplat/js/react-native-github:RCTFabricComponentViewsBaseApple", + "//xplat/js/react-native-github:RCTTextApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/attributedstring:attributedstringApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/componentregistry:componentregistryApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/components/legacyviewmanagerinterop:legacyviewmanagerinteropApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/components/text:textApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/components/textinput/iostextinput:iostextinputApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/scheduler:schedulerApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/textlayoutmanager:textlayoutmanagerApple", + "//xplat/js/react-native-github/ReactCommon/runtimeexecutor:runtimeexecutorApple", + ], +) + +fb_apple_test( + name = "MountingTestsApple", + srcs = ["React/Tests/Mounting/RCTComponentViewRegistryTests.mm"], + frameworks = [ + "$PLATFORM_DIR/Developer/Library/Frameworks/XCTest.framework", + ], + oncall = "react_native", + deps = [ + ":ImageView", + ":RCTFabricApple", + "//xplat/js/react-native-github:RCTFabricComponentViewsBaseApple", + "//xplat/js/react-native-github:RCTTextApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/attributedstring:attributedstringApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/componentregistry:componentregistryApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/components/legacyviewmanagerinterop:legacyviewmanagerinteropApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/components/textinput/iostextinput:iostextinputApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/scheduler:schedulerApple", + "//xplat/js/react-native-github/ReactCommon/react/renderer/textlayoutmanager:textlayoutmanagerApple", + "//xplat/js/react-native-github/ReactCommon/runtimeexecutor:runtimeexecutorApple", + ], +) + +rn_apple_library( + name = "ImageView", + autoglob = False, + compiler_flags = ["-Wall"], + contacts = ["oncall+react_native@xmail.facebook.com"], + labels = [ + "disable_plugins_only_validation", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = [react_fabric_component_plugin_provider("Image", "RCTImageCls")], + visibility = ["PUBLIC"], + exported_deps = [ + ":RCTFabricComponentViewsBaseApple", + ], +) + +# Reduce the RCTFabric target by moving OSS RCTViewComponentViews here, so that +# eventually we can move all of React/Fabric/Mounting/ComponentViews/* here. +# Ideally, each component view gets its own target, and each target uses react_fabric_component_plugin_provider. +# For each component, an app can import the base component view, or an app-specific subclass. +# i.e. Apps depend on "ImageView" target for RCTImageComponentView.h, and "FBReactImageView" target for FBReactImageComponentView.h +rn_xplat_cxx_library2( + name = "RCTFabricComponentViewsBase", + srcs = glob(REACT_COMPONENTVIEWS_BASE_FILES), + header_namespace = "", + exported_headers = { + "React/RCTComponentViewProtocol.h": "React/Fabric/Mounting/RCTComponentViewProtocol.h", + "React/RCTConversions.h": "React/Fabric/RCTConversions.h", + "React/RCTImageComponentView.h": "React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.h", + "React/RCTImageResponseDelegate.h": "React/Fabric/RCTImageResponseDelegate.h", + "React/RCTImageResponseObserverProxy.h": "React/Fabric/RCTImageResponseObserverProxy.h", + "React/RCTTouchableComponentViewProtocol.h": "React/Fabric/RCTTouchableComponentViewProtocol.h", + "React/RCTViewComponentView.h": "React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h", + "React/UIView+ComponentViewProtocol.h": "React/Fabric/Mounting/UIView+ComponentViewProtocol.h", + }, + compiler_flags = ["-Wall"], + contacts = ["oncall+react_native@xmail.facebook.com"], + labels = ["supermodule:xplat/default/public.react_native.infra"], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:RCTImage", + "//xplat/js/react-native-github:RCTLinking", + react_native_xplat_target("react/renderer/imagemanager:imagemanager"), + react_native_xplat_target("react/renderer/components/image:image"), + react_native_xplat_target("react/renderer/components/view:view"), + react_native_xplat_target("react/renderer/componentregistry:componentregistry"), + ], +) + +rn_library( + name = "react-native", + srcs = [ + "package.json", + "index.js", + ] + glob( + [ + "Libraries/**/*.js", + "Libraries/NewAppScreen/**/*.png", + "Libraries/LogBox/**/*.png", + ], + exclude = [ + "**/__*__/**", + "**/gulpfile.js", + "Libraries/Components/Switch/SwitchSchema.js", + ], + ), + labels = ["supermodule:xplat/default/public.react_native.core"], + skip_processors = True, # Don't anticipate routes or fbicon here + visibility = ["PUBLIC"], + deps = [ + "//xplat/js:node_modules__abort_19controller", + "//xplat/js:node_modules__anser", + "//xplat/js:node_modules__base64_19js", + "//xplat/js:node_modules__event_19target_19shim", + "//xplat/js:node_modules__invariant", + "//xplat/js:node_modules__nullthrows", + "//xplat/js:node_modules__pretty_19format", + "//xplat/js:node_modules__promise", + "//xplat/js:node_modules__prop_19types", + "//xplat/js:node_modules__react_19devtools_19core", + "//xplat/js:node_modules__react_19refresh", + "//xplat/js:node_modules__react_19shallow_19renderer", + "//xplat/js:node_modules__regenerator_19runtime", + "//xplat/js:node_modules__stacktrace_19parser", + "//xplat/js:node_modules__use_19subscription", + "//xplat/js:node_modules__whatwg_19fetch", + "//xplat/js/RKJSModules/Libraries/Polyfills:Polyfills", + "//xplat/js/RKJSModules/Libraries/React:React", + "//xplat/js/RKJSModules/vendor/react:react", + "//xplat/js/RKJSModules/vendor/react-test-renderer:react-test-renderer", + "//xplat/js/RKJSModules/vendor/scheduler:scheduler", + "//xplat/js/react-native-github/packages/assets:assets", + "//xplat/js/react-native-github/packages/normalize-color:normalize-color", + "//xplat/js/react-native-github/packages/polyfills:polyfills", + "//xplat/js/tools/metro/packages/metro-runtime/src/modules:modules", + "//xplat/js/tools/metro/packages/metro-runtime/src/polyfills:polyfills", + ], +) + +rn_codegen( + name = "FBReactNativeSpec", + android_package_name = "com.facebook.fbreact.specs", + codegen_modules = True, + ios_assume_nonnull = False, + library_labels = ["supermodule:xplat/default/public.react_native.infra"], + native_module_spec_name = "FBReactNativeSpec", + src_prefix = "Libraries/", +) + +# TODO: Merge this into FBReactNativeSpec +rn_codegen( + name = "FBReactNativeComponentSpec", + codegen_components = True, + ios_assume_nonnull = False, + library_labels = ["supermodule:xplat/default/public.react_native.infra"], + src_prefix = "Libraries/", +) + +rn_apple_library( + name = "RCTAnimationApple", + srcs = glob([ + "Libraries/NativeAnimation/**/*.m", + "Libraries/NativeAnimation/**/*.mm", + ]), + headers = glob( + [ + "Libraries/NativeAnimation/**/*.h", + ], + ), + header_namespace = "", + exported_headers = glob( + [ + "Libraries/NativeAnimation/*.h", + "Libraries/NativeAnimation/Drivers/*.h", + "Libraries/NativeAnimation/Nodes/*.h", + ], + ), + autoglob = False, + frameworks = [ + "Foundation", + "QuartzCore", + "UIKit", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "extension_api_allow_unsafe_unavailable_usages", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "NativeAnimatedModule", + native_class_func = "RCTNativeAnimatedModuleCls", + ) + react_module_plugin_providers( + name = "NativeAnimatedTurboModule", + native_class_func = "RCTNativeAnimatedTurboModuleCls", + ), + plugins_header = "FBRCTAnimationPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + ], +) + +rn_apple_library( + name = "RCTBlobApple", + srcs = glob([ + "Libraries/Blob/*.m", + "Libraries/Blob/*.mm", + ]), + headers = glob( + [ + "Libraries/Blob/*.h", + ], + ), + exported_headers = glob( + [ + "Libraries/Blob/*.h", + ], + ), + autoglob = False, + enable_exceptions = True, + frameworks = [ + "Foundation", + "UIKit", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "FileReaderModule", + native_class_func = "RCTFileReaderModuleCls", + ) + react_module_plugin_providers( + name = "BlobModule", + native_class_func = "RCTBlobManagerCls", + ) + [ + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "BlobModule", + ), + ], + plugins_header = "FBRCTBlobPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + ":RCTNetworkApple", + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + "//xplat/js/react-native-github/React/CoreModules:CoreModulesApple", + "//xplat/jsi:jsiApple", + ], +) + +rn_apple_library( + name = "RCTLinkingApple", + srcs = glob([ + "Libraries/LinkingIOS/*.m", + "Libraries/LinkingIOS/*.mm", + ]), + headers = glob( + [ + "Libraries/LinkingIOS/*.h", + ], + ), + exported_headers = glob( + [ + "Libraries/LinkingIOS/*.h", + ], + ), + autoglob = False, + enable_exceptions = True, + frameworks = [ + "Foundation", + "UIKit", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "extension_api_allow_unsafe_unavailable_usages", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "LinkingManager", + native_class_func = "RCTLinkingManagerCls", + ), + plugins_header = "FBRCTLinkingPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + "//xplat/jsi:jsiApple", + ], +) + +rn_apple_library( + name = "RCTPushNotificationApple", + srcs = glob([ + "Libraries/PushNotificationIOS/*.m", + "Libraries/PushNotificationIOS/*.mm", + ]), + headers = glob( + [ + "Libraries/PushNotificationIOS/*.h", + ], + ), + exported_headers = glob( + [ + "Libraries/PushNotificationIOS/*.h", + ], + ), + autoglob = False, + enable_exceptions = True, + frameworks = [ + "Foundation", + "UIKit", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "extension_api_allow_unsafe_unavailable_usages", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "PushNotificationManager", + native_class_func = "RCTPushNotificationManagerCls", + ), + plugins_header = "FBRCTPushNotificationPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:ReactInternalApple", + "//xplat/jsi:jsiApple", + ], +) + +rn_apple_library( + name = "RCTImageApple", + srcs = glob([ + "Libraries/Image/*.m", + "Libraries/Image/*.mm", + ]), + headers = glob( + [ + "Libraries/Image/*.h", + ], + ), + exported_headers = glob( + [ + "Libraries/Image/*.h", + ], + ), + autoglob = False, + frameworks = [ + "AVFoundation", + "Accelerate", + "CoreMedia", + "Foundation", + "ImageIO", + "MobileCoreServices", + "QuartzCore", + "UIKit", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "extension_api_allow_unsafe_unavailable_usages", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "GIFImageDecoder", + native_class_func = "RCTGIFImageDecoderCls", + ) + react_module_plugin_providers( + name = "ImageEditingManager", + native_class_func = "RCTImageEditingManagerCls", + ) + react_module_plugin_providers( + name = "ImageLoader", + native_class_func = "RCTImageLoaderCls", + ) + react_module_plugin_providers( + name = "ImageStoreManager", + native_class_func = "RCTImageStoreManagerCls", + ) + react_module_plugin_providers( + name = "LocalAssetImageLoader", + native_class_func = "RCTLocalAssetImageLoaderCls", + ) + [ + plugin( + RCT_IMAGE_DATA_DECODER_SOCKET, + name = "GIFImageDecoder", + ), + plugin( + RCT_IMAGE_URL_LOADER_SOCKET, + name = "LocalAssetImageLoader", + ), + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "ImageLoader", + ), + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "ImageStoreManager", + ), + ], + plugins_header = "FBRCTImagePlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + ":RCTNetworkApple", + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + ], +) + +RCTNETWORK_PUBLIC_HEADERS = [ + "Libraries/Network/RCTNetworkTask.h", + "Libraries/Network/RCTNetworking.h", +] + +rn_apple_library( + name = "RCTNetworkApple", + srcs = glob([ + "Libraries/Network/*.m", + "Libraries/Network/*.mm", + ]), + headers = glob( + [ + "Libraries/Network/*.h", + ], + exclude = RCTNETWORK_PUBLIC_HEADERS, + ), + exported_headers = RCTNETWORK_PUBLIC_HEADERS, + autoglob = False, + enable_exceptions = True, + frameworks = [ + "CoreTelephony", + "Foundation", + "MobileCoreServices", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + "extension_api_allow_unsafe_unavailable_usages", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = + react_module_plugin_providers( + name = "Networking", + native_class_func = "RCTNetworkingCls", + ) + react_module_plugin_providers( + name = "DataRequestHandler", + native_class_func = "RCTDataRequestHandlerCls", + ) + react_module_plugin_providers( + name = "FileRequestHandler", + native_class_func = "RCTFileRequestHandlerCls", + ) + react_module_plugin_providers( + name = "HTTPRequestHandler", + native_class_func = "RCTHTTPRequestHandlerCls", + ) + [ + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "DataRequestHandler", + ), + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "FileRequestHandler", + ), + plugin( + RCT_URL_REQUEST_HANDLER_SOCKET, + name = "HTTPRequestHandler", + ), + ], + plugins_header = "FBRCTNetworkPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + ], +) + +rn_apple_library( + name = "RCTSettingsApple", + srcs = glob([ + "Libraries/Settings/*.m", + "Libraries/Settings/*.mm", + ]), + exported_headers = glob( + [ + "Libraries/Settings/*.h", + ], + ), + autoglob = False, + frameworks = [ + "Foundation", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "disable_plugins_only_validation", + ], + plugins = react_module_plugin_providers( + name = "SettingsManager", + native_class_func = "RCTSettingsManagerCls", + ), + plugins_header = "FBRCTSettingsPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + ], +) + +rn_xplat_cxx_library2( + name = "RCTText", + srcs = glob([ + "Libraries/Text/**/*.m", + "Libraries/Text/**/*.mm", + ]), + headers = glob( + [ + "Libraries/Text/**/*.h", + ], + ), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "Libraries/Text", + "*.h", + ), + ( + "Libraries/Text/BaseText", + "*.h", + ), + ( + "Libraries/Text/RawText", + "*.h", + ), + ( + "Libraries/Text/Text", + "*.h", + ), + ( + "Libraries/Text/TextInput", + "*.h", + ), + ( + "Libraries/Text/TextInput/Multiline", + "*.h", + ), + ( + "Libraries/Text/TextInput/Singleline", + "*.h", + ), + ( + "Libraries/Text/VirtualText", + "*.h", + ), + ], + prefix = "React", + ), + frameworks = [ + "$SDKROOT/System/Library/Frameworks/UIKit.framework", + ], + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:RCTLinking", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:ReactInternal", + YOGA_CXX_TARGET, + ], +) + +rn_apple_library( + name = "RCTVibrationApple", + srcs = glob([ + "Libraries/Vibration/**/*.m", + "Libraries/Vibration/**/*.mm", + ]), + exported_headers = glob( + [ + "Libraries/Vibration/*.h", + ], + ), + autoglob = False, + frameworks = [ + "AudioToolbox", + "Foundation", + ], + header_path_prefix = "React", + labels = [ + "depslint_never_remove", + "disable_plugins_only_validation", + "supermodule:xplat/default/public.react_native.infra", + ], + plugins = react_module_plugin_providers( + name = "Vibration", + native_class_func = "RCTVibrationCls", + ), + plugins_header = "FBRCTVibrationPlugins.h", + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [ + "-DRN_DISABLE_OSS_PLUGIN_HEADER", + ], + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:FBReactNativeSpecApple", + "//xplat/js/react-native-github:RCTLinkingApple", + "//xplat/js/react-native-github:RCTPushNotificationApple", + "//xplat/js/react-native-github:ReactInternalApple", + ], +) + +rn_xplat_cxx_library2( + name = "RCTWrapper", + srcs = glob([ + "Libraries/Wrapper/*.m", + "Libraries/Wrapper/*.mm", + ]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "Libraries/Wrapper", + "*.h", + ), + ], + prefix = "RCTWrapper", + ), + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + ], + labels = [ + "depslint_never_remove", # Some old NativeModule still relies on +load unfortunately. + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + "//xplat/js/react-native-github:RCTLinking", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:ReactInternal", + ], +) + +rn_xplat_cxx_library2( + name = "RCTWrapperExample", + srcs = glob([ + "Libraries/Wrapper/Example/*.m", + "Libraries/Wrapper/Example/*.mm", + ]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "Libraries/Wrapper/Example", + "*.h", + ), + ], + prefix = "RCTWrapperExample", + ), + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + ], + labels = [ + "depslint_never_remove", + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + ":RCTWrapper", + "//xplat/js/react-native-github:RCTLinking", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:ReactInternal", + ], +) + +rn_xplat_cxx_library2( + name = "RCTSurfaceHostingComponent", + srcs = glob([ + "Libraries/SurfaceHostingComponent/**/*.m", + "Libraries/SurfaceHostingComponent/**/*.mm", + ]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "Libraries/SurfaceHostingComponent", + "*.h", + ), + ], + prefix = "RCTSurfaceHostingComponent", + ), + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + "$SDKROOT/System/Library/Frameworks/UIKit.framework", + ], + labels = [ + "depslint_never_remove", + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + "//fbobjc/Libraries/MobileUI/ComponentKit:ComponentKit", + "//xplat/js/react-native-github:RCTLinking", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:ReactInternal", + ], +) + +rn_xplat_cxx_library2( + name = "RCTSurfaceBackedComponent", + srcs = glob([ + "Libraries/SurfaceBackedComponent/**/*.m", + "Libraries/SurfaceBackedComponent/**/*.mm", + ]), + header_namespace = "", + exported_headers = subdir_glob( + [ + ( + "Libraries/SurfaceBackedComponent", + "*.h", + ), + ], + prefix = "RCTSurfaceBackedComponent", + ), + frameworks = [ + "$SDKROOT/System/Library/Frameworks/Foundation.framework", + "$SDKROOT/System/Library/Frameworks/UIKit.framework", + ], + labels = [ + "depslint_never_remove", + "supermodule:xplat/default/public.react_native.infra", + ], + preprocessor_flags = get_objc_arc_preprocessor_flags() + get_preprocessor_flags_for_build_mode(), + visibility = ["PUBLIC"], + deps = [ + ":RCTSurfaceHostingComponent", + "//fbobjc/Libraries/MobileUI/ComponentKit:ComponentKit", + "//xplat/js/react-native-github:RCTLinking", + "//xplat/js/react-native-github:RCTPushNotification", + "//xplat/js/react-native-github:ReactInternal", + ], +) + +rn_xplat_cxx_library2( + name = "RCTMapView_RNHeader", + header_namespace = "", + exported_headers = { + "React/RCTConvert+CoreLocation.h": RCTVIEWS_PATH + "RCTConvert+CoreLocation.h", + }, + labels = [ + "supermodule:xplat/default/public.react_native.infra", + ], + visibility = [ + "//fbobjc/Libraries/FBReactKit:RCTMapView", + "//fbobjc/VendorLib/react-native-maps:react-native-maps", + ], +) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54af9968ff92a5..4944366f7b5ce3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,10 +21,19 @@ If you wish to contribute changes back to the **microsoft/react-native-macos** r git clone https://github.com/johndoe/react-native-macos.git ``` +### [Code of Conduct](https://github.com/facebook/react-native/blob/HEAD/CODE_OF_CONDUCT.md) + +As a reminder, all contributors are expected to adhere to the [Code of Conduct](https://github.com/facebook/react-native/blob/HEAD/CODE_OF_CONDUCT.md). + ### Setting up the upstream repository Before starting to contribute changes, please setup your upstream repository to the primary **microsoft/react-native-macos** repository. + +1. **Replying and handling open issues.** We get a lot of issues every day, and some of them may lack necessary information. You can help out by guiding people through the process of filling out the issue template, asking for clarifying information, or pointing them to existing issues that match their description of the problem. We cover more about this process in the [Issue Triage wiki](https://github.com/facebook/react-native/wiki/Triaging-GitHub-Issues). +2. **Reviewing pull requests for the docs.** Reviewing [documentation updates](https://github.com/facebook/react-native-website/pulls) can be as simple as checking for spelling and grammar. If you encounter situations that can be explained better in the docs, click **Edit** at the top of most docs pages to get started with your own contribution. +3. **Help people write test plans.** Some pull requests sent to the main repository may lack a proper test plan. These help reviewers understand how the change was tested, and can speed up the time it takes for a contribution to be accepted. + - When you run `git remote -v`, you should see only your fork in the output list ```bash @@ -42,6 +51,9 @@ git remote add upstream https://github.com/microsoft/react-native-macos.git - Now running `git remote -v` should show the upstream repository also +* [Issues](https://github.com/facebook/react-native/wiki/Triaging-GitHub-Issues) +* [Pull Requests](https://github.com/facebook/react-native/wiki/Managing-Pull-Requests) + ```bash git remote -v @@ -57,12 +69,19 @@ git remote -v For each bug or task you complete, it is recommended that you start with a fresh branch. If you have any lingering changes in your current branch that you want to save, go ahead and commit them. If you are just beginning, then you are good to go. On github, navigate to your repository which should be forked from **microsoft/react-native-macos** as described in the above sections. Above the list of files is a dropdown that should say master. Use the dropdown to create a new branch and name is according to what you will be working on. (I.e. DropdownHighlight, CleanUpExamples, etc). Now you have created a new branch. +* **React Native website** which contains the source code for the website, including the documentation, located at +* **Releases** are coordinated through the repository. This includes important documents such as the Changelog. +* **Discussions** about the future of React Native take place in the repository. +* **High-quality plugins** for React Native can be found throughout the [React Native Community GitHub Organization](http://github.com/react-native-community/). + **SourceTree:** If you are using SourceTree you will want your branch to show up in SourceTree so you can commit changes to your branch. It takes time for it to show up automatically, so you can make it show by running `git pull --all` in your command prompt from the root. Once you see your new branch in SourceTree under Remotes on the left navigation pane, double click on your branch to check it out locally. A dialog will come up and the default settings should be fine, click Ok. **Git Command Line** If you are using the command line, you will want to make sure you have your branch locally. It takes time for it to show up automatically, so you can make it show by running `git pull --all` in your command prompt from the root. Run `git branch -a` to see if your new branch shows up. Now you will want to check out your branch locally. You can do this with `git checkout -b branch-name`. Confirm you are now working out of the branch with `git branch`. +We use GitHub issues to track bugs exclusively. We have documented our issue handling processes in the [Issues wiki](https://github.com/facebook/react-native/wiki/Triaging-GitHub-Issues). + ### Merging upstream master into your fork master From time to time, your fork will get out of sync with the upstream remote. Use the following commands to get the master branch of your fork up up to date. @@ -102,6 +121,8 @@ sudo xcode-select -s /Applications/Xcode.app arch -x86_64 pod install ``` +The React Native blog is generated [from the Markdown sources for the blog](https://github.com/facebook/react-native-website/tree/HEAD/website/blog). + ### Make the fix Now that your branch is set up and ready for commits, go ahead and fix the bug you are working on or make some small change that you want to check in. @@ -114,6 +135,8 @@ yarn lint # run eslint on JavaScript yarn flow-check-macos # run Flow checks on JavaScript ``` +We recommend referring to the [CONTRIBUTING](https://github.com/facebook/react-native-website/blob/HEAD/CONTRIBUTING.md) document for the `react-native-website` repository to learn more about contributing to the website in general. + ### Commit your changes **SourceTree:** @@ -127,7 +150,18 @@ You can commit multiple times until you are ready to make a pull request. You sh ### Provide changelog information Run `yarn change` in the root of the repo. -### Create a Pull Request +1. Fork the React Native repository and create your branch from `main`. +2. Make the desired changes to React Native sources. Use the `packages/rn-tester` app to test them out. +3. If you've added code that should be tested, add tests. +4. If you've changed APIs, update the documentation, which lives in [another repo](https://github.com/facebook/react-native-website/). +5. Ensure the test suite passes, either locally or on CI once you opened a pull request. +6. Make sure your code lints (for example via `yarn lint --fix`). +7. Push the changes to your fork. +8. Create a pull request to the React Native repository. +9. Review and address comments on your pull request. + 1. A bot may comment with suggestions. Generally we ask you to resolve these first before a maintainer will review your code. + 2. If changes are requested and addressed, please [request review](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) to notify reviewers to take another look. +10. If you haven't already, please complete the [Contributor License Agreement](https://github.com/facebook/react-native/wiki/Contributor-License-Agreement) ("CLA"). **[Complete your CLA here.](https://code.facebook.com/cla)** **SourceTree:** In SourceTree click Push. @@ -135,13 +169,11 @@ In SourceTree click Push. **Git Command Line** Run `git push`. -This will push any staged files you have in your branch. - -Now go back to your fork on github. You should see a yellow bar at the top with your change and a button that says "Compare & Pull Request". Click that button. +Whenever you are ready to contribute code, check out our [step-by-step guide to sending your first pull request](https://github.com/facebook/react-native/wiki/How-to-Open-a-Pull-Request), or read the [How to Contribute Code](https://github.com/facebook/react-native/wiki/How-to-Contribute-Code) wiki for more details. Click "Create Pull Request". -A bunch of tests will automatically kick off to verify your PR. The tests marked as `required` must pass before a PR can be merged. +Tests help us prevent regressions from being introduced to the codebase. The GitHub repository is continuously tested using Circle and Appveyor, the results of which are available through the Checks functionality on [commits](https://github.com/facebook/react-native/commits/HEAD) and pull requests. You can learn more about running and writing tests in the [Tests wiki](http://github.com/facebook/react-native/wiki/Tests). Someone will also have to review your change before the change is allowed to be merged in. They may ask questions for more information or ask you to change things. Be sure to respond to their comments and push additional changes to the branch if they ask you to modify things before they sign off. diff --git a/Folly/folly/portability/Time.h b/Folly/folly/portability/Time.h index 0f024aab82f5d2..d4688ef8249900 100644 --- a/Folly/folly/portability/Time.h +++ b/Folly/folly/portability/Time.h @@ -28,8 +28,8 @@ // then enable our implementation on the source side so that // gets linked in instead. #if __MACH__ && \ - (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 || \ - __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0) + (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0 || \ // TODO(macOS GH#774): Upgrade min allowed version to fix type redefinition bug with clock_t + __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_12_0) // TODO(macOS GH#774): Upgrade min allowed version to fix type redefinition bug with clock_t #ifdef FOLLY_HAVE_CLOCK_GETTIME #undef FOLLY_HAVE_CLOCK_GETTIME diff --git a/IntegrationTests/AccessibilityManagerTest.js b/IntegrationTests/AccessibilityManagerTest.js index 7501170f3acf89..a6f4c0d93bb64c 100644 --- a/IntegrationTests/AccessibilityManagerTest.js +++ b/IntegrationTests/AccessibilityManagerTest.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import invariant from 'invariant'; import NativeAccessibilityManager from 'react-native/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager'; import {DeviceEventEmitter, NativeModules, View} from 'react-native'; diff --git a/IntegrationTests/AsyncStorageTest.js b/IntegrationTests/AsyncStorageTest.js index 12d9f3d620f331..51ce374556e90b 100644 --- a/IntegrationTests/AsyncStorageTest.js +++ b/IntegrationTests/AsyncStorageTest.js @@ -16,6 +16,7 @@ const {AsyncStorage, Text, View, StyleSheet} = ReactNative; const {TestModule} = ReactNative.NativeModules; const deepDiffer = require('react-native/Libraries/Utilities/differ/deepDiffer'); +const nullthrows = require('nullthrows'); const DEBUG = false; @@ -43,15 +44,32 @@ function expectTrue(condition: boolean, message: string) { } } +// Type-safe wrapper around JSON.stringify +function stringify( + value: + | void + | null + | string + | number + | boolean + | {...} + | $ReadOnlyArray, +): string { + if (typeof value === 'undefined') { + return 'undefined'; + } + return JSON.stringify(value); +} + function expectEqual(lhs, rhs, testname: string) { expectTrue( !deepDiffer(lhs, rhs), 'Error in test ' + testname + ': expected\n' + - JSON.stringify(rhs) + + stringify(rhs) + '\ngot\n' + - JSON.stringify(lhs), + stringify(lhs), ); } @@ -61,7 +79,7 @@ function expectAsyncNoError(place, err) { } expectTrue( err === null, - 'Unexpected error in ' + place + ': ' + JSON.stringify(err), + 'Unexpected error in ' + place + ': ' + stringify(err), ); } @@ -71,7 +89,7 @@ function testSetAndGet() { AsyncStorage.getItem(KEY_1, (err2, result) => { expectAsyncNoError('testSetAndGet/getItem', err2); expectEqual(result, VAL_1, 'testSetAndGet setItem'); - updateMessage('get(key_1) correctly returned ' + result); + updateMessage('get(key_1) correctly returned ' + String(result)); runTestCase('should get null for missing key', testMissingGet); }); }); @@ -81,7 +99,7 @@ function testMissingGet() { AsyncStorage.getItem(KEY_2, (err, result) => { expectAsyncNoError('testMissingGet/setItem', err); expectEqual(result, null, 'testMissingGet'); - updateMessage('missing get(key_2) correctly returned ' + result); + updateMessage('missing get(key_2) correctly returned ' + String(result)); runTestCase('check set twice results in a single key', testSetTwice); }); } @@ -105,8 +123,9 @@ function testRemoveItem() { AsyncStorage.getAllKeys((err, result) => { expectAsyncNoError('testRemoveItem/getAllKeys', err); expectTrue( - result.indexOf(KEY_1) >= 0 && result.indexOf(KEY_2) >= 0, - 'Missing KEY_1 or KEY_2 in ' + '(' + result + ')', + nullthrows(result).indexOf(KEY_1) >= 0 && + nullthrows(result).indexOf(KEY_2) >= 0, + 'Missing KEY_1 or KEY_2 in ' + '(' + nullthrows(result).join() + ')', ); updateMessage('testRemoveItem - add two items'); AsyncStorage.removeItem(KEY_1, err2 => { @@ -123,8 +142,8 @@ function testRemoveItem() { AsyncStorage.getAllKeys((err4, result3) => { expectAsyncNoError('testRemoveItem/getAllKeys', err4); expectTrue( - result3.indexOf(KEY_1) === -1, - 'Unexpected: KEY_1 present in ' + result3, + nullthrows(result3).indexOf(KEY_1) === -1, + 'Unexpected: KEY_1 present in ' + nullthrows(result3).join(), ); updateMessage('proper length returned.'); runTestCase('should merge values', testMerge); @@ -137,13 +156,17 @@ function testRemoveItem() { } function testMerge() { - AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), err1 => { + AsyncStorage.setItem(KEY_MERGE, stringify(VAL_MERGE_1), err1 => { expectAsyncNoError('testMerge/setItem', err1); - AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), err2 => { + AsyncStorage.mergeItem(KEY_MERGE, stringify(VAL_MERGE_2), err2 => { expectAsyncNoError('testMerge/mergeItem', err2); AsyncStorage.getItem(KEY_MERGE, (err3, result) => { expectAsyncNoError('testMerge/setItem', err3); - expectEqual(JSON.parse(result), VAL_MERGE_EXPECT, 'testMerge'); + expectEqual( + JSON.parse(nullthrows(result)), + VAL_MERGE_EXPECT, + 'testMerge', + ); updateMessage('objects deeply merged\nDone!'); runTestCase('multi set and get', testOptimizedMultiGet); }); @@ -165,8 +188,7 @@ function testOptimizedMultiGet() { expectAsyncNoError(`${i} testOptimizedMultiGet/multiGet`, err2); expectEqual(result, batch, `${i} testOptimizedMultiGet multiGet`); updateMessage( - 'multiGet([key_1, key_2]) correctly returned ' + - JSON.stringify(result), + 'multiGet([key_1, key_2]) correctly returned ' + stringify(result), ); done(); }); @@ -196,9 +218,10 @@ class AsyncStorageTest extends React.Component<{...}, $FlowFixMeState> { return ( - {/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This - * comment suppresses an error found when Flow v0.54 was deployed. - * To see the error delete this comment and run Flow. */ + {/* $FlowFixMe[incompatible-type] (>=0.54.0 site=react_native_fb,react_ + * native_oss) This comment suppresses an error found when Flow v0.54 + * was deployed. To see the error delete this comment and run Flow. + */ this.constructor.displayName + ': '} {this.state.done ? 'Done' : 'Testing...'} {'\n\n' + this.state.messages} diff --git a/IntegrationTests/BUCK b/IntegrationTests/BUCK new file mode 100644 index 00000000000000..61e3de6466aaa5 --- /dev/null +++ b/IntegrationTests/BUCK @@ -0,0 +1,30 @@ +load("@fbsource//tools/build_defs:js_glob.bzl", "js_glob") +load("@fbsource//tools/build_defs/oss:metro_defs.bzl", "rn_library") + +# This file was generated by running +# js1 build buckfiles + +rn_library( + name = "IntegrationTests", + srcs = js_glob( + [ + "**/*", + ], + excludes = [ + "**/__*__/**", + "**/*.command", + "**/*.md", + "websocket_integration_test_server.js", + ], + ), + labels = ["supermodule:xplat/default/public.react_native.tests"], + skip_processors = True, + visibility = ["PUBLIC"], + deps = [ + "//xplat/js:node_modules__invariant", + "//xplat/js:node_modules__nullthrows", + "//xplat/js/RKJSModules/vendor/react:react", + "//xplat/js/react-native-github:react-native", + "//xplat/js/react-native-github/packages/assets:assets", + ], +) diff --git a/IntegrationTests/GlobalEvalWithSourceUrlTest.js b/IntegrationTests/GlobalEvalWithSourceUrlTest.js index fca7bfbc2170c7..a69ee3728c48b0 100644 --- a/IntegrationTests/GlobalEvalWithSourceUrlTest.js +++ b/IntegrationTests/GlobalEvalWithSourceUrlTest.js @@ -10,7 +10,7 @@ 'use strict'; -import type {ExtendedError} from 'react-native/Libraries/Core/Devtools/parseErrorStack'; +import type {ExtendedError} from 'react-native/Libraries/Core/ExtendedError'; const React = require('react'); const ReactNative = require('react-native'); diff --git a/IntegrationTests/ImageCachePolicyTest.js b/IntegrationTests/ImageCachePolicyTest.js index 03857091072cf6..00d65fb736d119 100644 --- a/IntegrationTests/ImageCachePolicyTest.js +++ b/IntegrationTests/ImageCachePolicyTest.js @@ -64,7 +64,7 @@ class ImageCachePolicyTest extends React.Component { { { { { return ( - {/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This - * comment suppresses an error found when Flow v0.54 was deployed. - * To see the error delete this comment and run Flow. */ + {/* $FlowFixMe[incompatible-type] (>=0.54.0 site=react_native_fb,react_ + * native_oss) This comment suppresses an error found when Flow v0.54 + * was deployed. To see the error delete this comment and run Flow. + */ this.constructor.displayName + ': '} {this.state.done ? 'Done' : 'Testing...'} diff --git a/IntegrationTests/IntegrationTestsApp.js b/IntegrationTests/IntegrationTestsApp.js index 1e52877b7b9908..af41da151c47de 100644 --- a/IntegrationTests/IntegrationTestsApp.js +++ b/IntegrationTests/IntegrationTestsApp.js @@ -40,9 +40,9 @@ const TESTS = [ ]; TESTS.forEach( - /* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error found when Flow v0.54 was deployed. To see the error - * delete this comment and run Flow. */ + /* $FlowFixMe[incompatible-call] (>=0.54.0 site=react_native_fb,react_native_ + * oss) This comment suppresses an error found when Flow v0.54 was deployed. + * To see the error delete this comment and run Flow. */ test => AppRegistry.registerComponent(test.displayName, () => test), ); @@ -60,9 +60,10 @@ class IntegrationTestsApp extends React.Component<{...}, $FlowFixMeState> { if (this.state.test) { return ( - {/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This - * comment suppresses an error when upgrading Flow's support for - * React. To see the error delete this comment and run Flow. */} + {/* $FlowFixMe[type-as-value] (>=0.53.0 site=react_native_fb,react_ + * native_oss) This comment suppresses an error when upgrading + * Flow's support for React. To see the error delete this comment + * and run Flow. */} ); @@ -79,9 +80,10 @@ class IntegrationTestsApp extends React.Component<{...}, $FlowFixMeState> { {TESTS.map(test => [ this.setState({test})} - /* $FlowFixMe(>=0.115.0 site=react_native_fb) This comment - * suppresses an error found when Flow v0.115 was deployed. To - * see the error, delete this comment and run Flow. */ + /* $FlowFixMe[incompatible-type] (>=0.115.0 site=react_native_fb) + * This comment suppresses an error found when Flow v0.115 was + * deployed. To see the error, delete this comment and run Flow. + */ style={styles.row}> {test.displayName} , diff --git a/IntegrationTests/LayoutEventsTest.js b/IntegrationTests/LayoutEventsTest.js index d0c784ca545021..3993a6dcca5e09 100644 --- a/IntegrationTests/LayoutEventsTest.js +++ b/IntegrationTests/LayoutEventsTest.js @@ -203,4 +203,5 @@ const styles = StyleSheet.create({ }, }); +LayoutEventsTest.displayName = 'LayoutEventsTest'; module.exports = LayoutEventsTest; diff --git a/IntegrationTests/ReactContentSizeUpdateTest.js b/IntegrationTests/ReactContentSizeUpdateTest.js index 7abcc4fb8b4627..9c826d9f4f5328 100644 --- a/IntegrationTests/ReactContentSizeUpdateTest.js +++ b/IntegrationTests/ReactContentSizeUpdateTest.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - const RCTNativeAppEventEmitter = require('react-native/Libraries/EventEmitter/RCTNativeAppEventEmitter'); const React = require('react'); const ReactNative = require('react-native'); diff --git a/IntegrationTests/SizeFlexibilityUpdateTest.js b/IntegrationTests/SizeFlexibilityUpdateTest.js index b2e4952b102c70..3577a5363b5339 100644 --- a/IntegrationTests/SizeFlexibilityUpdateTest.js +++ b/IntegrationTests/SizeFlexibilityUpdateTest.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - const RCTNativeAppEventEmitter = require('react-native/Libraries/EventEmitter/RCTNativeAppEventEmitter'); const React = require('react'); const ReactNative = require('react-native'); diff --git a/IntegrationTests/TimersTest.js b/IntegrationTests/TimersTest.js index 8550c6f00eec6b..30473e3b8e752c 100644 --- a/IntegrationTests/TimersTest.js +++ b/IntegrationTests/TimersTest.js @@ -97,36 +97,46 @@ class TimersTest extends React.Component { } componentDidMount() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testSetTimeout0, 1000); } testSetTimeout0() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testSetTimeout1, 0); } testSetTimeout1() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testSetTimeout50, 1); } testSetTimeout50() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testRequestAnimationFrame, 50); } testRequestAnimationFrame() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.requestAnimationFrame(this.testSetInterval0); } testSetInterval0() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._nextTest = this.testSetInterval20; + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._interval = this.setInterval(this._incrementInterval, 0); } testSetInterval20() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._nextTest = this.testSetImmediate; + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._interval = this.setInterval(this._incrementInterval, 20); } testSetImmediate() { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setImmediate(this.testClearTimeout0); } @@ -139,6 +149,7 @@ class TimersTest extends React.Component { testClearTimeout30() { const timeout = this.setTimeout(() => this._fail('testClearTimeout30'), 30); this.clearTimeout(timeout); + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testClearMulti, 50); } @@ -156,6 +167,7 @@ class TimersTest extends React.Component { fails.forEach(timeout => this.clearTimeout(timeout)); this.setTimeout(() => this.clearTimeout(delayClear), 20); + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.testOrdering, 50); } @@ -191,6 +203,7 @@ class TimersTest extends React.Component { ), 25, ); + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.setTimeout(this.done, 50); } @@ -249,6 +262,7 @@ class TimersTest extends React.Component { this.clearInterval(this._interval); this._interval = null; } + // $FlowFixMe[method-unbinding] this.setState({count: 0}, this._nextTest); return; } @@ -267,4 +281,5 @@ const styles = StyleSheet.create({ }, }); +TimersTest.displayName = 'TimersTest'; module.exports = TimersTest; diff --git a/Libraries/ActionSheetIOS/ActionSheetIOS.js b/Libraries/ActionSheetIOS/ActionSheetIOS.js index bc3a935dee298b..786839498f334f 100644 --- a/Libraries/ActionSheetIOS/ActionSheetIOS.js +++ b/Libraries/ActionSheetIOS/ActionSheetIOS.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import RCTActionSheetManager from './NativeActionSheetManager'; const invariant = require('invariant'); @@ -33,6 +31,7 @@ const ActionSheetIOS = { * - `destructiveButtonIndex` (int or array of ints) - index or indices of destructive buttons in `options` * - `title` (string) - a title to show above the action sheet * - `message` (string) - a message to show below the title + * - `disabledButtonIndices` (array of numbers) - a list of button indices which should be disabled * * The 'callback' function takes one parameter, the zero-based index * of the selected item. @@ -49,6 +48,7 @@ const ActionSheetIOS = { +anchor?: ?number, +tintColor?: ColorValue | ProcessedColorValue, +userInterfaceStyle?: string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) { diff --git a/Libraries/ActionSheetIOS/NativeActionSheetManager.js b/Libraries/ActionSheetIOS/NativeActionSheetManager.js index 063d9147e1d69b..7c48f8e2d4bbc3 100644 --- a/Libraries/ActionSheetIOS/NativeActionSheetManager.js +++ b/Libraries/ActionSheetIOS/NativeActionSheetManager.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; @@ -25,6 +23,7 @@ export interface Spec extends TurboModule { +anchor?: ?number, +tintColor?: ?number, +userInterfaceStyle?: ?string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) => void; diff --git a/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec b/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec index c43897e0a3c877..c6554c3d7ec534 100644 --- a/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec +++ b/Libraries/ActionSheetIOS/React-RCTActionSheet.podspec @@ -11,7 +11,7 @@ version = package['version'] source = { :git => 'https://github.com/facebook/react-native.git' } if version == '1000.0.0' # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. - source[:commit] = `git rev-parse HEAD`.strip + source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") else source[:tag] = "v#{version}" end @@ -24,7 +24,7 @@ Pod::Spec.new do |s| s.documentation_url = "https://reactnative.dev/docs/actionsheetios" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :osx => "10.14" } # TODO(macOS GH#214) + s.platforms = { :ios => "11.0", :osx => "10.15" } # TODO(macOS GH#214) s.source = source s.source_files = "*.{m}" s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" diff --git a/Libraries/Alert/Alert.js b/Libraries/Alert/Alert.js index 17d306e9e985f3..cfa4cd80b9e983 100644 --- a/Libraries/Alert/Alert.js +++ b/Libraries/Alert/Alert.js @@ -8,13 +8,9 @@ * @flow */ -'use strict'; - import AlertMacOS from './AlertMacOS'; // TODO(macOS GH#774) import Platform from '../Utilities/Platform'; -import NativeDialogManagerAndroid, { - type DialogOptions, -} from '../NativeModules/specs/NativeDialogManagerAndroid'; +import type {DialogOptions} from '../NativeModules/specs/NativeDialogManagerAndroid'; import RCTAlertManager from './RCTAlertManager'; export type AlertType = @@ -54,6 +50,8 @@ class Alert { ) { Alert.prompt(title, message, buttons, 'default'); } else if (Platform.OS === 'android') { + const NativeDialogManagerAndroid = require('../NativeModules/specs/NativeDialogManagerAndroid') + .default; if (!NativeDialogManagerAndroid) { return; } diff --git a/Libraries/Alert/NativeAlertManager.js b/Libraries/Alert/NativeAlertManager.js index 929c165f32e584..c9f9327096bfd2 100644 --- a/Libraries/Alert/NativeAlertManager.js +++ b/Libraries/Alert/NativeAlertManager.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; import type {DefaultInputsArray} from './AlertMacOS'; // TODO(macOS GH#774) diff --git a/Libraries/Alert/RCTAlertManager.android.js b/Libraries/Alert/RCTAlertManager.android.js index 43f49a94e50bb1..366692bd906d04 100644 --- a/Libraries/Alert/RCTAlertManager.android.js +++ b/Libraries/Alert/RCTAlertManager.android.js @@ -7,8 +7,6 @@ * @format */ -'use strict'; - import NativeDialogManagerAndroid from '../NativeModules/specs/NativeDialogManagerAndroid'; function emptyCallback() {} diff --git a/Libraries/Alert/RCTAlertManager.ios.js b/Libraries/Alert/RCTAlertManager.ios.js index 8ededddf4b463c..a5dbdac5daf7dc 100644 --- a/Libraries/Alert/RCTAlertManager.ios.js +++ b/Libraries/Alert/RCTAlertManager.ios.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import NativeAlertManager from './NativeAlertManager'; import type {Args} from './NativeAlertManager'; diff --git a/Libraries/Animated/Animated.js b/Libraries/Animated/Animated.js index 323f8d38afc3e9..2f6ee99ae6b04e 100644 --- a/Libraries/Animated/Animated.js +++ b/Libraries/Animated/Animated.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import Platform from '../Utilities/Platform'; import typeof AnimatedFlatList from './components/AnimatedFlatList'; import typeof AnimatedImage from './components/AnimatedImage'; diff --git a/Libraries/Animated/AnimatedEvent.js b/Libraries/Animated/AnimatedEvent.js index 98ff42eb197071..b6de725948a961 100644 --- a/Libraries/Animated/AnimatedEvent.js +++ b/Libraries/Animated/AnimatedEvent.js @@ -74,6 +74,7 @@ function attachNativeEvent( NativeAnimatedHelper.API.removeAnimatedEventFromView( viewTag, eventName, + // $FlowFixMe[incompatible-call] mapping.animatedValueTag, ); }); @@ -210,9 +211,9 @@ class AnimatedEvent { } } else if (typeof recMapping === 'object') { for (const mappingKey in recMapping) { - /* $FlowFixMe(>=0.120.0) This comment suppresses an error found - * when Flow v0.120 was deployed. To see the error, delete this - * comment and run Flow. */ + /* $FlowFixMe[prop-missing] (>=0.120.0) This comment suppresses an + * error found when Flow v0.120 was deployed. To see the error, + * delete this comment and run Flow. */ traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey); } } diff --git a/Libraries/Animated/AnimatedImplementation.js b/Libraries/Animated/AnimatedImplementation.js index 12b225abab0616..706b87ea01e9e1 100644 --- a/Libraries/Animated/AnimatedImplementation.js +++ b/Libraries/Animated/AnimatedImplementation.js @@ -706,6 +706,4 @@ module.exports = { * Expose Event class, so it can be used as a type for type checkers. */ Event: AnimatedEvent, - - __PropsOnlyForTests: AnimatedProps, }; diff --git a/Libraries/Animated/AnimatedMock.js b/Libraries/Animated/AnimatedMock.js index eecfbb884ec42b..ca6741719482d9 100644 --- a/Libraries/Animated/AnimatedMock.js +++ b/Libraries/Animated/AnimatedMock.js @@ -14,7 +14,6 @@ const {AnimatedEvent, attachNativeEvent} = require('./AnimatedEvent'); const AnimatedImplementation = require('./AnimatedImplementation'); const AnimatedInterpolation = require('./nodes/AnimatedInterpolation'); const AnimatedNode = require('./nodes/AnimatedNode'); -const AnimatedProps = require('./nodes/AnimatedProps'); const AnimatedValue = require('./nodes/AnimatedValue'); const AnimatedValueXY = require('./nodes/AnimatedValueXY'); @@ -24,7 +23,6 @@ import type {EndCallback} from './animations/Animation'; import type {TimingAnimationConfig} from './animations/TimingAnimation'; import type {DecayAnimationConfig} from './animations/DecayAnimation'; import type {SpringAnimationConfig} from './animations/SpringAnimation'; -import type {Mapping, EventConfig} from './AnimatedEvent'; /** * Animations are a source of flakiness in snapshot testing. This mock replaces @@ -58,7 +56,12 @@ const spring = function( return { ...emptyAnimation, start: (callback?: ?EndCallback): void => { - anyValue.setValue(config.toValue); + // TODO(macOS GH#774) - setValue can't handle AnimatedNodes + if (config.toValue instanceof AnimatedNode) { + anyValue.setValue(config.toValue.__getValue()); + } else { + anyValue.setValue(config.toValue); + } callback && callback({finished: true}); }, }; @@ -123,10 +126,6 @@ const loop = function( return emptyAnimation; }; -const event = function(argMapping: Array, config: EventConfig): any { - return null; -}; - module.exports = { Value: AnimatedValue, ValueXY: AnimatedValueXY, @@ -146,11 +145,10 @@ module.exports = { parallel, stagger, loop, - event, + event: AnimatedImplementation.event, createAnimatedComponent, attachNativeEvent, forkEvent: AnimatedImplementation.forkEvent, unforkEvent: AnimatedImplementation.unforkEvent, Event: AnimatedEvent, - __PropsOnlyForTests: AnimatedProps, }; diff --git a/Libraries/Animated/AnimatedWeb.js b/Libraries/Animated/AnimatedWeb.js index 3f3313fe6c69e2..513f322b709d08 100644 --- a/Libraries/Animated/AnimatedWeb.js +++ b/Libraries/Animated/AnimatedWeb.js @@ -14,10 +14,13 @@ const AnimatedImplementation = require('./AnimatedImplementation'); module.exports = { ...AnimatedImplementation, - // $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this + /* $FlowFixMe[incompatible-call] createAnimatedComponent expects to receive + * types. Plain intrinsic components can't be typed like this */ div: (AnimatedImplementation.createAnimatedComponent('div'): $FlowFixMe), - // $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this + /* $FlowFixMe[incompatible-call] createAnimatedComponent expects to receive + * types. Plain intrinsic components can't be typed like this */ span: (AnimatedImplementation.createAnimatedComponent('span'): $FlowFixMe), - // $FlowFixMe createAnimatedComponent expects to receive types. Plain intrinsic components can't be typed like this + /* $FlowFixMe[incompatible-call] createAnimatedComponent expects to receive + * types. Plain intrinsic components can't be typed like this */ img: (AnimatedImplementation.createAnimatedComponent('img'): $FlowFixMe), }; diff --git a/Libraries/Animated/NativeAnimatedHelper.js b/Libraries/Animated/NativeAnimatedHelper.js index af78a8d0987591..536b44c1cbdba5 100644 --- a/Libraries/Animated/NativeAnimatedHelper.js +++ b/Libraries/Animated/NativeAnimatedHelper.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import NativeAnimatedNonTurboModule from './NativeAnimatedModule'; import NativeAnimatedTurboModule from './NativeAnimatedTurboModule'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; @@ -49,9 +47,9 @@ const API = { saveValueCallback: (value: number) => void, ): void { invariant(NativeAnimatedModule, 'Native animated module is not available'); - if (NativeAnimatedModule.getValue) { + API.queueOperation(() => { NativeAnimatedModule.getValue(tag, saveValueCallback); - } + }); }, setWaitingForIdentifier: function(id: string): void { waitingForQueuedOperations.add(id); @@ -395,10 +393,17 @@ module.exports = { assertNativeAnimatedModule, shouldUseNativeDriver, transformDataType, - // $FlowExpectedError - unsafe getter lint suppresion + // $FlowExpectedError[unsafe-getters-setters] - unsafe getter lint suppresion + // $FlowExpectedError[missing-type-arg] - unsafe getter lint suppresion get nativeEventEmitter(): NativeEventEmitter { if (!nativeEventEmitter) { - nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule); + nativeEventEmitter = new NativeEventEmitter( + // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior + // If you want to use the native module on other platforms, please remove this condition and test its behavior + Platform.OS !== 'ios' && Platform.OS !== 'macos' // TODO(macOS GH#774): Also use this parameter on macOS + ? null + : NativeAnimatedModule, + ); } return nativeEventEmitter; }, diff --git a/Libraries/Animated/NativeAnimatedModule.js b/Libraries/Animated/NativeAnimatedModule.js index be8ceb140fc31c..d126bfdaff96eb 100644 --- a/Libraries/Animated/NativeAnimatedModule.js +++ b/Libraries/Animated/NativeAnimatedModule.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Animated/NativeAnimatedTurboModule.js b/Libraries/Animated/NativeAnimatedTurboModule.js index b19fbde5f9b0f3..03ff0f26116560 100644 --- a/Libraries/Animated/NativeAnimatedTurboModule.js +++ b/Libraries/Animated/NativeAnimatedTurboModule.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Animated/__tests__/Animated-test.js b/Libraries/Animated/__tests__/Animated-test.js index aa32306b7f5985..2b2ffe04dfdfb8 100644 --- a/Libraries/Animated/__tests__/Animated-test.js +++ b/Libraries/Animated/__tests__/Animated-test.js @@ -8,8 +8,7 @@ * @emails oncall+react_native */ -'use strict'; - +import AnimatedProps from '../nodes/AnimatedProps'; import TestRenderer from 'react-test-renderer'; import * as React from 'react'; @@ -23,6 +22,7 @@ jest.mock('../../BatchedBridge/NativeModules', () => ({ })); let Animated = require('../Animated'); + describe('Animated tests', () => { beforeEach(() => { jest.resetModules(); @@ -34,7 +34,7 @@ describe('Animated tests', () => { const callback = jest.fn(); - const node = new Animated.__PropsOnlyForTests( + const node = new AnimatedProps( { style: { backgroundColor: 'red', @@ -57,8 +57,6 @@ describe('Animated tests', () => { callback, ); - expect(anim.__getChildren().length).toBe(3); - expect(node.__getValue()).toEqual({ style: { backgroundColor: 'red', @@ -71,6 +69,12 @@ describe('Animated tests', () => { }, }); + expect(anim.__getChildren().length).toBe(0); + + node.__attach(); + + expect(anim.__getChildren().length).toBe(3); + anim.setValue(0.5); expect(callback).toBeCalled(); @@ -788,7 +792,7 @@ describe('Animated tests', () => { const callback = jest.fn(); - const node = new Animated.__PropsOnlyForTests( + const node = new AnimatedProps( { style: { opacity: vec.x.interpolate({ @@ -811,6 +815,10 @@ describe('Animated tests', () => { }, }); + node.__attach(); + + expect(callback.mock.calls.length).toBe(0); + vec.setValue({x: 42, y: 1492}); expect(callback.mock.calls.length).toBe(2); // once each for x, y @@ -892,7 +900,7 @@ describe('Animated tests', () => { const value3 = new Animated.Value(0); const value4 = Animated.add(value3, Animated.multiply(value1, value2)); const callback = jest.fn(); - const view = new Animated.__PropsOnlyForTests( + const view = new AnimatedProps( { style: { transform: [ @@ -904,6 +912,7 @@ describe('Animated tests', () => { }, callback, ); + view.__attach(); const listener = jest.fn(); const id = value4.addListener(listener); value3.setValue(137); diff --git a/Libraries/Animated/__tests__/AnimatedNative-test.js b/Libraries/Animated/__tests__/AnimatedNative-test.js index ceb93dccd332fe..e5ecec1fb7d648 100644 --- a/Libraries/Animated/__tests__/AnimatedNative-test.js +++ b/Libraries/Animated/__tests__/AnimatedNative-test.js @@ -8,8 +8,6 @@ * @emails oncall+react_native */ -'use strict'; - jest .clearAllMocks() .mock('../../BatchedBridge/NativeModules', () => ({ diff --git a/Libraries/Animated/__tests__/createAnimatedComponentInjection-test.js b/Libraries/Animated/__tests__/createAnimatedComponentInjection-test.js new file mode 100644 index 00000000000000..e82ea170a3eb95 --- /dev/null +++ b/Libraries/Animated/__tests__/createAnimatedComponentInjection-test.js @@ -0,0 +1,67 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails oncall+react_native + * @flow strict-local + * @format + */ + +'use strict'; + +const createAnimatedComponent = require('../createAnimatedComponent'); +const createAnimatedComponentInjection = require('../createAnimatedComponentInjection'); +const React = require('react'); + +function injected( + Component: React.AbstractComponent, +): React.AbstractComponent { + return createAnimatedComponent(Component); +} + +beforeEach(() => { + jest.resetModules(); + jest.resetAllMocks(); +}); + +test('does nothing without injection', () => { + expect(typeof createAnimatedComponent).toBe('function'); + expect(createAnimatedComponent).not.toBe(injected); +}); + +test('injection overrides `createAnimatedComponent`', () => { + createAnimatedComponentInjection.inject(injected); + + expect(createAnimatedComponent).toBe(injected); +}); + +test('injection errors if called too late', () => { + jest.spyOn(console, 'error').mockReturnValue(undefined); + + // Causes `createAnimatedComponent` to be initialized. + createAnimatedComponent; + + createAnimatedComponentInjection.inject(injected); + + expect(createAnimatedComponent).not.toBe(injected); + expect(console.error).toBeCalledWith( + 'createAnimatedComponentInjection: Must be called before `createAnimatedComponent`.', + ); +}); + +test('injection errors if called more than once', () => { + jest.spyOn(console, 'error').mockReturnValue(undefined); + + createAnimatedComponentInjection.inject(injected); + + expect(createAnimatedComponent).toBe(injected); + expect(console.error).not.toBeCalled(); + + createAnimatedComponentInjection.inject(injected); + + expect(console.error).toBeCalledWith( + 'createAnimatedComponentInjection: Cannot be called more than once.', + ); +}); diff --git a/Libraries/Animated/animations/Animation.js b/Libraries/Animated/animations/Animation.js index 53967d96f9e109..3555bf2cc2665a 100644 --- a/Libraries/Animated/animations/Animation.js +++ b/Libraries/Animated/animations/Animation.js @@ -71,6 +71,7 @@ class Animation { this.__nativeId, animatedValue.__getNativeTag(), this.__getNativeAnimationConfig(), + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.__debouncedOnEnd.bind(this), ); } catch (e) { diff --git a/Libraries/Animated/animations/DecayAnimation.js b/Libraries/Animated/animations/DecayAnimation.js index c3dce534f84baa..b04b911e7600c7 100644 --- a/Libraries/Animated/animations/DecayAnimation.js +++ b/Libraries/Animated/animations/DecayAnimation.js @@ -84,6 +84,7 @@ class DecayAnimation extends Animation { if (this._useNativeDriver) { this.__startNativeAnimation(animatedValue); } else { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); } } @@ -105,6 +106,7 @@ class DecayAnimation extends Animation { this._lastValue = value; if (this.__active) { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); } } diff --git a/Libraries/Animated/animations/SpringAnimation.js b/Libraries/Animated/animations/SpringAnimation.js index aec87e5cecb732..e09db93b7c5340 100644 --- a/Libraries/Animated/animations/SpringAnimation.js +++ b/Libraries/Animated/animations/SpringAnimation.js @@ -344,6 +344,7 @@ class SpringAnimation extends Animation { this.__debouncedOnEnd({finished: true}); return; } + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); } diff --git a/Libraries/Animated/animations/TimingAnimation.js b/Libraries/Animated/animations/TimingAnimation.js index ffe8c8313be2f7..7f239ce0102faf 100644 --- a/Libraries/Animated/animations/TimingAnimation.js +++ b/Libraries/Animated/animations/TimingAnimation.js @@ -48,6 +48,7 @@ let _easeInOut; function easeInOut() { if (!_easeInOut) { const Easing = require('../Easing'); + // $FlowFixMe[method-unbinding] _easeInOut = Easing.inOut(Easing.ease); } return _easeInOut; @@ -117,6 +118,7 @@ class TimingAnimation extends Animation { this.__startNativeAnimation(animatedValue); } else { this._animationFrame = requestAnimationFrame( + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.onUpdate.bind(this), ); } @@ -149,6 +151,7 @@ class TimingAnimation extends Animation { (this._toValue - this._fromValue), ); if (this.__active) { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); } } diff --git a/Libraries/Animated/components/AnimatedFlatList.js b/Libraries/Animated/components/AnimatedFlatList.js index 64ba6c200beea0..49a1ebcbd19b37 100644 --- a/Libraries/Animated/components/AnimatedFlatList.js +++ b/Libraries/Animated/components/AnimatedFlatList.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; const FlatList = require('../../Lists/FlatList'); diff --git a/Libraries/Animated/components/AnimatedImage.js b/Libraries/Animated/components/AnimatedImage.js index 56cdb7d18f7908..107d601f50c91e 100644 --- a/Libraries/Animated/components/AnimatedImage.js +++ b/Libraries/Animated/components/AnimatedImage.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; const Image = require('../../Image/Image'); @@ -17,9 +15,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent( - (Image: $FlowFixMe), -): AnimatedComponentType< +module.exports = (createAnimatedComponent((Image: $FlowFixMe), { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedScrollView.js b/Libraries/Animated/components/AnimatedScrollView.js index 259cbb81b0ee2f..488e9d12041534 100644 --- a/Libraries/Animated/components/AnimatedScrollView.js +++ b/Libraries/Animated/components/AnimatedScrollView.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; const ScrollView = require('../../Components/ScrollView/ScrollView'); @@ -24,9 +22,9 @@ const ScrollViewWithEventThrottle = React.forwardRef((props, ref) => ( )); -module.exports = (createAnimatedComponent( - ScrollViewWithEventThrottle, -): AnimatedComponentType< +module.exports = (createAnimatedComponent(ScrollViewWithEventThrottle, { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedSectionList.js b/Libraries/Animated/components/AnimatedSectionList.js index 9beef55e879488..98ccd918460bc6 100644 --- a/Libraries/Animated/components/AnimatedSectionList.js +++ b/Libraries/Animated/components/AnimatedSectionList.js @@ -8,11 +8,9 @@ * @format */ -'use strict'; - import * as React from 'react'; -const SectionList = require('../../Lists/SectionList'); +import SectionList from '../../Lists/SectionList'; const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; diff --git a/Libraries/Animated/components/AnimatedText.js b/Libraries/Animated/components/AnimatedText.js index 5a184e0626fe17..dd4fb0b02378fb 100644 --- a/Libraries/Animated/components/AnimatedText.js +++ b/Libraries/Animated/components/AnimatedText.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; const Text = require('../../Text/Text'); @@ -17,9 +15,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent( - (Text: $FlowFixMe), -): AnimatedComponentType< +module.exports = (createAnimatedComponent((Text: $FlowFixMe), { + collapsable: false, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/components/AnimatedView.js b/Libraries/Animated/components/AnimatedView.js index 0ce54601fe9990..79ebe1a0ea97cb 100644 --- a/Libraries/Animated/components/AnimatedView.js +++ b/Libraries/Animated/components/AnimatedView.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; const View = require('../../Components/View/View'); @@ -17,7 +15,9 @@ const createAnimatedComponent = require('../createAnimatedComponent'); import type {AnimatedComponentType} from '../createAnimatedComponent'; -module.exports = (createAnimatedComponent(View): AnimatedComponentType< +module.exports = (createAnimatedComponent(View, { + collapsable: true, +}): AnimatedComponentType< React.ElementConfig, React.ElementRef, >); diff --git a/Libraries/Animated/createAnimatedComponent.js b/Libraries/Animated/createAnimatedComponent.js index 230aa164203606..1154557c407908 100644 --- a/Libraries/Animated/createAnimatedComponent.js +++ b/Libraries/Animated/createAnimatedComponent.js @@ -10,6 +10,8 @@ 'use strict'; +import * as createAnimatedComponentInjection from './createAnimatedComponentInjection'; + const View = require('../Components/View/View'); const {AnimatedEvent} = require('./AnimatedEvent'); const AnimatedProps = require('./nodes/AnimatedProps'); @@ -37,8 +39,13 @@ export type AnimatedComponentType< Instance, >; +type AnimatedComponentOptions = { + collapsable?: boolean, +}; + function createAnimatedComponent( Component: React.AbstractComponent, + options?: AnimatedComponentOptions, ): AnimatedComponentType { invariant( typeof Component !== 'function' || @@ -79,6 +86,11 @@ function createAnimatedComponent( } _isFabric = (): boolean => { + // When called during the first render, `_component` is always null. + // Therefore, even if a component is rendered in Fabric, we can't detect + // that until ref is set, which happens sometime after the first render. + // In cases where this value switching between "false" and "true" on Fabric + // causes issues, add an additional check for _component nullity. if (this._component == null) { return false; } @@ -164,14 +176,11 @@ function createAnimatedComponent( _attachProps(nextProps) { const oldPropsAnimated = this._propsAnimated; - if (nextProps === oldPropsAnimated) { - return; - } - this._propsAnimated = new AnimatedProps( nextProps, this._animatedPropsCallback, ); + this._propsAnimated.__attach(); // When you call detach, it removes the element from the parent list // of children. If it goes to 0, then the parent also detaches itself @@ -192,19 +201,6 @@ function createAnimatedComponent( setLocalRef: ref => { this._prevComponent = this._component; this._component = ref; - - // TODO: Delete this in a future release. - if (ref != null && ref.getNode == null) { - ref.getNode = () => { - console.warn( - '%s: Calling `getNode()` on the ref of an Animated component ' + - 'is no longer necessary. You can now directly use the ref ' + - 'instead. This method will be removed in a future release.', - ref.constructor.name ?? '<>', - ); - return ref; - }; - } }, }); @@ -213,23 +209,42 @@ function createAnimatedComponent( const {style: passthruStyle = {}, ...passthruProps} = this.props.passthroughAnimatedPropExplicitValues || {}; const mergedStyle = {...style, ...passthruStyle}; + + // On Fabric, we always want to ensure the container Animated View is *not* + // flattened. + // Because we do not get a host component ref immediately and thus cannot + // do a proper Fabric vs non-Fabric detection immediately, we default to assuming + // that Fabric *is* enabled until we know otherwise. + // Thus, in Fabric, this view will never be flattened. In non-Fabric, the view will + // not be flattened during the initial render but may be flattened in the second render + // and onwards. + const forceNativeIdFabric = + (this._component == null && + (options?.collapsable === false || props.collapsable !== true)) || + this._isFabric(); + + const forceNativeId = + props.collapsable ?? + (this._propsAnimated.__isNative || + forceNativeIdFabric || + options?.collapsable === false); + // The native driver updates views directly through the UI thread so we + // have to make sure the view doesn't get optimized away because it cannot + // go through the NativeViewHierarchyManager since it operates on the shadow + // thread. TODO: T68258846 + const collapsableProps = forceNativeId + ? { + nativeID: props.nativeID ?? 'animatedComponent', + collapsable: false, + } + : {}; return ( ); } @@ -270,6 +285,8 @@ function createAnimatedComponent( this._propsAnimated && this._propsAnimated.__detach(); this._detachNativeEvents(); this._markUpdateComplete(); + this._component = null; + this._prevComponent = null; } } @@ -283,4 +300,6 @@ function createAnimatedComponent( }); } -module.exports = createAnimatedComponent; +// $FlowIgnore[incompatible-cast] - Will be compatible after refactors. +module.exports = (createAnimatedComponentInjection.recordAndRetrieve() ?? + createAnimatedComponent: typeof createAnimatedComponent); diff --git a/Libraries/Animated/createAnimatedComponentInjection.js b/Libraries/Animated/createAnimatedComponentInjection.js new file mode 100644 index 00000000000000..5a1727e959a9b7 --- /dev/null +++ b/Libraries/Animated/createAnimatedComponentInjection.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import * as React from 'react'; + +type createAnimatedComponent = ( + Component: React.AbstractComponent, +) => React.AbstractComponent; + +// This can be undefined, null, or the experimental implementation. If this is +// null, that means `createAnimatedComponent` has already been initialized and +// it is too late to call `inject`. +let injected: ?createAnimatedComponent; + +/** + * Call during bundle initialization to opt-in to new `createAnimatedComponent`. + */ +export function inject(newInjected: createAnimatedComponent): void { + if (injected !== undefined) { + if (__DEV__) { + console.error( + 'createAnimatedComponentInjection: ' + + (injected == null + ? 'Must be called before `createAnimatedComponent`.' + : 'Cannot be called more than once.'), + ); + } + return; + } + injected = newInjected; +} + +/** + * Only called by `createAnimatedComponent.js`. + */ +export function recordAndRetrieve(): createAnimatedComponent | null { + if (injected === undefined) { + injected = null; + } + return injected; +} diff --git a/Libraries/Animated/createAnimatedComponent_EXPERIMENTAL.js b/Libraries/Animated/createAnimatedComponent_EXPERIMENTAL.js new file mode 100644 index 00000000000000..a7d5f8169e5636 --- /dev/null +++ b/Libraries/Animated/createAnimatedComponent_EXPERIMENTAL.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import useAnimatedProps from './useAnimatedProps'; +import useMergeRefs from '../Utilities/useMergeRefs'; +import StyleSheet from '../StyleSheet/StyleSheet'; +import * as React from 'react'; + +/** + * Experimental implementation of `createAnimatedComponent` that is intended to + * be compatible with concurrent rendering. + */ +export default function createAnimatedComponent( + Component: React.AbstractComponent, +): React.AbstractComponent { + return React.forwardRef((props, forwardedRef) => { + const [reducedProps, callbackRef] = useAnimatedProps( + props, + ); + const ref = useMergeRefs(callbackRef, forwardedRef); + + // Some components require explicit passthrough values for animation + // to work properly. For example, if an animated component is + // transformed and Pressable, onPress will not work after transform + // without these passthrough values. + // $FlowFixMe[prop-missing] + const {passthroughAnimatedPropExplicitValues, style} = reducedProps; + const {style: passthroughStyle, ...passthroughProps} = + passthroughAnimatedPropExplicitValues ?? {}; + const mergedStyle = StyleSheet.compose(style, passthroughStyle); + + return ( + + ); + }); +} diff --git a/Libraries/Animated/nodes/AnimatedInterpolation.js b/Libraries/Animated/nodes/AnimatedInterpolation.js index 63dfa670f1705e..ce06272b5c6d79 100644 --- a/Libraries/Animated/nodes/AnimatedInterpolation.js +++ b/Libraries/Animated/nodes/AnimatedInterpolation.js @@ -205,14 +205,12 @@ function createInterpolationFromStringOutputRange( // [200, 250], // [0, 0.5], // ] - /* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need to - * guard against this possibility. - */ + /* $FlowFixMe[incompatible-use] (>=0.18.0): `outputRange[0].match()` can + * return `null`. Need to guard against this possibility. */ const outputRanges = outputRange[0].match(stringShapeRegex).map(() => []); outputRange.forEach(value => { - /* $FlowFixMe(>=0.18.0): `value.match()` can return `null`. Need to guard - * against this possibility. - */ + /* $FlowFixMe[incompatible-use] (>=0.18.0): `value.match()` can return + * `null`. Need to guard against this possibility. */ value.match(stringShapeRegex).forEach((number, i) => { outputRanges[i].push(+number); }); @@ -220,8 +218,10 @@ function createInterpolationFromStringOutputRange( const interpolations = outputRange[0] .match(stringShapeRegex) - /* $FlowFixMe(>=0.18.0): `outputRange[0].match()` can return `null`. Need - * to guard against this possibility. */ + /* $FlowFixMe[incompatible-use] (>=0.18.0): `outputRange[0].match()` can + * return `null`. Need to guard against this possibility. */ + /* $FlowFixMe[incompatible-call] (>=0.18.0): `outputRange[0].match()` can + * return `null`. Need to guard against this possibility. */ .map((value, i) => { return createInterpolation({ ...config, @@ -277,12 +277,11 @@ function checkValidInputRange(arr: $ReadOnlyArray) { for (let i = 1; i < arr.length; ++i) { invariant( arr[i] >= arr[i - 1], - /* $FlowFixMe(>=0.13.0) - In the addition expression below this comment, - * one or both of the operands may be something that doesn't cleanly - * convert to a string, like undefined, null, and object, etc. If you really - * mean this implicit string conversion, you can do something like - * String(myThing) - */ + /* $FlowFixMe[incompatible-type] (>=0.13.0) - In the addition expression + * below this comment, one or both of the operands may be something that + * doesn't cleanly convert to a string, like undefined, null, and object, + * etc. If you really mean this implicit string conversion, you can do + * something like String(myThing) */ 'inputRange must be monotonically non-decreasing ' + arr, ); } @@ -292,12 +291,11 @@ function checkInfiniteRange(name: string, arr: $ReadOnlyArray) { invariant(arr.length >= 2, name + ' must have at least 2 elements'); invariant( arr.length !== 2 || arr[0] !== -Infinity || arr[1] !== Infinity, - /* $FlowFixMe(>=0.13.0) - In the addition expression below this comment, - * one or both of the operands may be something that doesn't cleanly convert - * to a string, like undefined, null, and object, etc. If you really mean - * this implicit string conversion, you can do something like - * String(myThing) - */ + /* $FlowFixMe[incompatible-type] (>=0.13.0) - In the addition expression + * below this comment, one or both of the operands may be something that + * doesn't cleanly convert to a string, like undefined, null, and object, + * etc. If you really mean this implicit string conversion, you can do + * something like String(myThing) */ name + 'cannot be ]-infinity;+infinity[ ' + arr, ); } @@ -358,8 +356,9 @@ class AnimatedInterpolation extends AnimatedWithChildren { return { inputRange: this._config.inputRange, // Only the `outputRange` can contain strings so we don't need to transform `inputRange` here - /* $FlowFixMe(>=0.38.0) - Flow error detected during the deployment of - * v0.38.0. To see the error, remove this comment and run flow */ + /* $FlowFixMe[incompatible-call] (>=0.38.0) - Flow error detected during + * the deployment of v0.38.0. To see the error, remove this comment and + * run flow */ outputRange: this.__transformDataType(this._config.outputRange), extrapolateLeft: this._config.extrapolateLeft || this._config.extrapolate || 'extend', diff --git a/Libraries/Animated/nodes/AnimatedProps.js b/Libraries/Animated/nodes/AnimatedProps.js index 578ed6718d213f..6f915bb5b8fd1d 100644 --- a/Libraries/Animated/nodes/AnimatedProps.js +++ b/Libraries/Animated/nodes/AnimatedProps.js @@ -33,7 +33,6 @@ class AnimatedProps extends AnimatedNode { } this._props = props; this._callback = callback; - this.__attach(); } __getValue(): Object { diff --git a/Libraries/Animated/nodes/AnimatedValue.js b/Libraries/Animated/nodes/AnimatedValue.js index 1be77112eef6f5..92baefb2cc8e07 100644 --- a/Libraries/Animated/nodes/AnimatedValue.js +++ b/Libraries/Animated/nodes/AnimatedValue.js @@ -46,9 +46,9 @@ const NativeAnimatedAPI = NativeAnimatedHelper.API; function _flush(rootNode: AnimatedValue): void { const animatedStyles = new Set(); function findAnimatedStyles(node) { - /* $FlowFixMe(>=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. */ + /* $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. */ if (typeof node.update === 'function') { animatedStyles.add(node); } else { @@ -56,10 +56,21 @@ function _flush(rootNode: AnimatedValue): void { } } findAnimatedStyles(rootNode); - /* $FlowFixMe */ + // $FlowFixMe[prop-missing] animatedStyles.forEach(animatedStyle => animatedStyle.update()); } +/** + * Some operations are executed only on batch end, which is _mostly_ scheduled when + * Animated component props change. For some of the changes which require immediate execution + * (e.g. setValue), we create a separate batch in case none is scheduled. + */ +function _executeAsAnimatedBatch(id: string, operation: () => void) { + NativeAnimatedAPI.setWaitingForIdentifier(id); + operation(); + NativeAnimatedAPI.unsetWaitingForIdentifier(id); +} + /** * Standard value for driving animations. One `Animated.Value` can drive * multiple properties in a synchronized fashion, but can only be driven by one @@ -115,7 +126,9 @@ class AnimatedValue extends AnimatedWithChildren { !this.__isNative /* don't perform a flush for natively driven values */, ); if (this.__isNative) { - NativeAnimatedAPI.setAnimatedNodeValue(this.__getNativeTag(), value); + _executeAsAnimatedBatch(this.__getNativeTag().toString(), () => { + NativeAnimatedAPI.setAnimatedNodeValue(this.__getNativeTag(), value); + }); } } diff --git a/Libraries/Animated/nodes/AnimatedWithChildren.js b/Libraries/Animated/nodes/AnimatedWithChildren.js index e46dbf2f629762..5f4ff1c6de1f91 100644 --- a/Libraries/Animated/nodes/AnimatedWithChildren.js +++ b/Libraries/Animated/nodes/AnimatedWithChildren.js @@ -76,6 +76,7 @@ class AnimatedWithChildren extends AnimatedNode { super.__callListeners(value); if (!this.__isNative) { for (const child of this._children) { + // $FlowFixMe[method-unbinding] added when improving typing for this parameters if (child.__getValue) { child.__callListeners(child.__getValue()); } diff --git a/Libraries/Animated/useAnimatedProps.js b/Libraries/Animated/useAnimatedProps.js new file mode 100644 index 00000000000000..142faedb1b2396 --- /dev/null +++ b/Libraries/Animated/useAnimatedProps.js @@ -0,0 +1,211 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +import AnimatedProps from './nodes/AnimatedProps'; +import {AnimatedEvent} from './AnimatedEvent'; +import useRefEffect from '../Utilities/useRefEffect'; +import NativeAnimatedHelper from './NativeAnimatedHelper'; +import { + useCallback, + useEffect, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, +} from 'react'; + +type ReducedProps = { + ...TProps, + collapsable: boolean, + ... +}; +type CallbackRef = T => mixed; + +let animatedComponentNextId = 1; + +export default function useAnimatedProps( + props: TProps, +): [ReducedProps, CallbackRef] { + const [, scheduleUpdate] = useReducer(count => count + 1, 0); + const onUpdateRef = useRef void>(null); + + // TODO: Only invalidate `node` if animated props or `style` change. In the + // previous implementation, we permitted `style` to override props with the + // same name property name as styles, so we can probably continue doing that. + // The ordering of other props *should* not matter. + const node = useMemo( + () => new AnimatedProps(props, () => onUpdateRef.current?.()), + [props], + ); + useAnimatedPropsLifecycle(node); + + // TODO: This "effect" does three things: + // + // 1) Call `setNativeView`. + // 2) Update `onUpdateRef`. + // 3) Update listeners for `AnimatedEvent` props. + // + // Ideally, each of these would be separat "effects" so that they are not + // unnecessarily re-run when irrelevant dependencies change. For example, we + // should be able to hoist all `AnimatedEvent` props and only do #3 if either + // the `AnimatedEvent` props change or `instance` changes. + // + // But there is no way to transparently compose three separate callback refs, + // so we just combine them all into one for now. + const refEffect = useCallback( + instance => { + // NOTE: This may be called more often than necessary (e.g. when `props` + // changes), but `setNativeView` already optimizes for that. + node.setNativeView(instance); + + // NOTE: This callback is only used by the JavaScript animation driver. + onUpdateRef.current = () => { + if ( + process.env.NODE_ENV === 'test' || + typeof instance !== 'object' || + typeof instance?.setNativeProps !== 'function' || + isFabricInstance(instance) + ) { + // Schedule an update for this component to update `reducedProps`, + // but do not compute it immediately. If a parent also updated, we + // need to merge those new props in before updating. + scheduleUpdate(); + } else if (!node.__isNative) { + // $FlowIgnore[not-a-function] - Assume it's still a function. + instance.setNativeProps(node.__getAnimatedValue()); + } else { + throw new Error( + 'Attempting to run JS driven animation on animated node ' + + 'that has been moved to "native" earlier by starting an ' + + 'animation with `useNativeDriver: true`', + ); + } + }; + + const target = getEventTarget(instance); + const events = []; + + for (const propName in props) { + const propValue = props[propName]; + if (propValue instanceof AnimatedEvent && propValue.__isNative) { + propValue.__attach(target, propName); + events.push([propName, propValue]); + } + } + + return () => { + onUpdateRef.current = null; + + for (const [propName, propValue] of events) { + propValue.__detach(target, propName); + } + }; + }, + [props, node], + ); + const callbackRef = useRefEffect(refEffect); + + return [reduceAnimatedProps(node), callbackRef]; +} + +function reduceAnimatedProps( + node: AnimatedProps, +): ReducedProps { + // Force `collapsable` to be false so that the native view is not flattened. + // Flattened views cannot be accurately referenced by the native driver. + return { + ...node.__getValue(), + collapsable: false, + }; +} + +/** + * Manages the lifecycle of the supplied `AnimatedProps` by invoking `__attach` + * and `__detach`. However, this is more complicated because `AnimatedProps` + * uses reference counting to determine when to recursively detach its children + * nodes. So in order to optimize this, we avoid detaching until the next attach + * unless we are unmounting. + */ +function useAnimatedPropsLifecycle(node: AnimatedProps): void { + const prevNodeRef = useRef(null); + const isUnmountingRef = useRef(false); + + const [animatedComponentId] = useState( + () => `${animatedComponentNextId++}:animatedComponent`, + ); + + useLayoutEffect(() => { + NativeAnimatedHelper.API.setWaitingForIdentifier(animatedComponentId); + }); + + useEffect(() => { + NativeAnimatedHelper.API.unsetWaitingForIdentifier(animatedComponentId); + }); + + useLayoutEffect(() => { + isUnmountingRef.current = false; + return () => { + isUnmountingRef.current = true; + }; + }, []); + + useLayoutEffect(() => { + node.__attach(); + if (prevNodeRef.current != null) { + const prevNode = prevNodeRef.current; + // TODO: Stop restoring default values (unless `reset` is called). + prevNode.__restoreDefaultValues(); + prevNode.__detach(); + prevNodeRef.current = null; + } + return () => { + if (isUnmountingRef.current) { + // NOTE: Do not restore default values on unmount, see D18197735. + node.__detach(); + } else { + prevNodeRef.current = node; + } + }; + }, [node]); +} + +function getEventTarget(instance: TInstance): TInstance { + return typeof instance === 'object' && + typeof instance?.getScrollableNode === 'function' + ? // $FlowFixMe[incompatible-use] - Legacy instance assumptions. + instance.getScrollableNode() + : instance; +} + +// $FlowFixMe[unclear-type] - Legacy instance assumptions. +function isFabricInstance(instance: any): boolean { + return ( + hasFabricHandle(instance) || + // Some components have a setNativeProps function but aren't a host component + // such as lists like FlatList and SectionList. These should also use + // forceUpdate in Fabric since setNativeProps doesn't exist on the underlying + // host component. This crazy hack is essentially special casing those lists and + // ScrollView itself to use forceUpdate in Fabric. + // If these components end up using forwardRef then these hacks can go away + // as instance would actually be the underlying host component and the above check + // would be sufficient. + hasFabricHandle(instance?.getNativeScrollRef?.()) || + hasFabricHandle(instance?.getScrollResponder?.()?.getNativeScrollRef?.()) + ); +} + +// $FlowFixMe[unclear-type] - Legacy instance assumptions. +function hasFabricHandle(instance: any): boolean { + // eslint-disable-next-line dot-notation + return instance?.['_internalInstanceHandle']?.stateNode?.canonical != null; +} diff --git a/Libraries/AppState/AppState.js b/Libraries/AppState/AppState.js index cc8a62a381ff8e..04492206127d79 100644 --- a/Libraries/AppState/AppState.js +++ b/Libraries/AppState/AppState.js @@ -4,17 +4,30 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ -'use strict'; - +import {type EventSubscription} from '../vendor/emitter/EventEmitter'; import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; import logError from '../Utilities/logError'; -import EventEmitter from '../vendor/emitter/EventEmitter'; import NativeAppState from './NativeAppState'; -import invariant from 'invariant'; +import Platform from '../Utilities/Platform'; + +export type AppStateValues = 'inactive' | 'background' | 'active'; + +type AppStateEventDefinitions = { + change: [AppStateValues], + memoryWarning: [], + blur: [], + focus: [], +}; + +type NativeAppStateEventDefinitions = { + appStateDidChange: [{app_state: AppStateValues}], + appStateFocusChange: [boolean], + memoryWarning: [], +}; /** * `AppState` can tell you if the app is in the foreground or background, @@ -22,44 +35,52 @@ import invariant from 'invariant'; * * See https://reactnative.dev/docs/appstate.html */ -class AppState extends NativeEventEmitter { - _eventHandlers: Object; - _supportedEvents = ['change', 'memoryWarning', 'blur', 'focus']; - currentState: ?string; +class AppState { + currentState: ?string = null; isAvailable: boolean; - constructor() { - super(NativeAppState); - - this.isAvailable = true; - this._eventHandlers = this._supportedEvents.reduce((handlers, key) => { - handlers[key] = new Map(); - return handlers; - }, {}); - - this.currentState = NativeAppState.getConstants().initialAppState; - - let eventUpdated = false; + _emitter: ?NativeEventEmitter; - // TODO: this is a terrible solution - in order to ensure `currentState` - // prop is up to date, we have to register an observer that updates it - // whenever the state changes, even if nobody cares. We should just - // deprecate the `currentState` property and get rid of this. - this.addListener('appStateDidChange', appStateData => { - eventUpdated = true; - this.currentState = appStateData.app_state; - }); - - // TODO: see above - this request just populates the value of `currentState` - // when the module is first initialized. Would be better to get rid of the - // prop and expose `getCurrentAppState` method directly. - NativeAppState.getCurrentAppState(appStateData => { - // It's possible that the state will have changed here & listeners need to be notified - if (!eventUpdated && this.currentState !== appStateData.app_state) { + constructor() { + if (NativeAppState == null) { + this.isAvailable = false; + } else { + this.isAvailable = true; + + const emitter: NativeEventEmitter = new NativeEventEmitter( + // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior + // If you want to use the native module on other platforms, please remove this condition and test its behavior + Platform.OS !== 'ios' && Platform.OS !== 'macos' // TODO(macOS GH#774): Also use this parameter on macOS + ? null + : NativeAppState, + ); + this._emitter = emitter; + + this.currentState = NativeAppState.getConstants().initialAppState; + + let eventUpdated = false; + + // TODO: this is a terrible solution - in order to ensure `currentState` + // prop is up to date, we have to register an observer that updates it + // whenever the state changes, even if nobody cares. We should just + // deprecate the `currentState` property and get rid of this. + emitter.addListener('appStateDidChange', appStateData => { + eventUpdated = true; this.currentState = appStateData.app_state; - this.emit('appStateDidChange', appStateData); - } - }, logError); + }); + + // TODO: see above - this request just populates the value of `currentState` + // when the module is first initialized. Would be better to get rid of the + // prop and expose `getCurrentAppState` method directly. + // $FlowExpectedError[incompatible-call] + NativeAppState.getCurrentAppState(appStateData => { + // It's possible that the state will have changed here & listeners need to be notified + if (!eventUpdated && this.currentState !== appStateData.app_state) { + this.currentState = appStateData.app_state; + emitter.emit('appStateDidChange', appStateData); + } + }, logError); + } } // TODO: now that AppState is a subclass of NativeEventEmitter, we could @@ -73,107 +94,72 @@ class AppState extends NativeEventEmitter { * * See https://reactnative.dev/docs/appstate.html#addeventlistener */ - addEventListener(type: string, handler: Function) { - invariant( - this._supportedEvents.indexOf(type) !== -1, - 'Trying to subscribe to unknown event: "%s"', - type, - ); - + addEventListener>( + type: K, + handler: (...$ElementType) => void, + ): EventSubscription { + const emitter = this._emitter; + if (emitter == null) { + throw new Error('Cannot use AppState when `isAvailable` is false.'); + } switch (type) { - case 'change': { - this._eventHandlers[type].set( - handler, - this.addListener('appStateDidChange', appStateData => { - handler(appStateData.app_state); - }), - ); - break; - } - case 'memoryWarning': { - this._eventHandlers[type].set( - handler, - this.addListener('memoryWarning', handler), - ); - break; - } - + case 'change': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const changeHandler: AppStateValues => void = handler; + return emitter.addListener('appStateDidChange', appStateData => { + changeHandler(appStateData.app_state); + }); + case 'memoryWarning': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const memoryWarningHandler: () => void = handler; + return emitter.addListener('memoryWarning', memoryWarningHandler); case 'blur': - case 'focus': { - this._eventHandlers[type].set( - handler, - this.addListener('appStateFocusChange', hasFocus => { - if (type === 'blur' && !hasFocus) { - handler(); - } - if (type === 'focus' && hasFocus) { - handler(); - } - }), - ); - } + case 'focus': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + const focusOrBlurHandler: () => void = handler; + return emitter.addListener('appStateFocusChange', hasFocus => { + if (type === 'blur' && !hasFocus) { + focusOrBlurHandler(); + } + if (type === 'focus' && hasFocus) { + focusOrBlurHandler(); + } + }); } + throw new Error('Trying to subscribe to unknown event: ' + type); } /** - * Remove a handler by passing the `change` event type and the handler. - * - * See https://reactnative.dev/docs/appstate.html#removeeventlistener + * @deprecated Use `remove` on the EventSubscription from `addEventListener`. */ - removeEventListener(type: string, handler: Function) { - invariant( - this._supportedEvents.indexOf(type) !== -1, - 'Trying to remove listener for unknown event: "%s"', - type, - ); - if (!this._eventHandlers[type].has(handler)) { - return; + removeEventListener>( + type: K, + listener: (...$ElementType) => mixed, + ): void { + const emitter = this._emitter; + if (emitter == null) { + throw new Error('Cannot use AppState when `isAvailable` is false.'); } - this._eventHandlers[type].get(handler).remove(); - this._eventHandlers[type].delete(handler); - } -} - -function throwMissingNativeModule() { - invariant( - false, - 'Cannot use AppState module when native RCTAppState is not included in the build.\n' + - 'Either include it, or check AppState.isAvailable before calling any methods.', - ); -} - -class MissingNativeAppStateShim extends EventEmitter { - // AppState - isAvailable: boolean = false; - currentState: ?string = null; - - addEventListener(type: string, handler: Function) { - throwMissingNativeModule(); - } - - removeEventListener(type: string, handler: Function) { - throwMissingNativeModule(); - } - - // EventEmitter - addListener() { - throwMissingNativeModule(); - } - - removeAllListeners() { - throwMissingNativeModule(); - } - - removeSubscription() { - throwMissingNativeModule(); + // NOTE: This will report a deprecation notice via `console.error`. + switch (type) { + case 'change': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + // $FlowIssue[incompatible-call] + emitter.removeListener('appStateDidChange', listener); + return; + case 'memoryWarning': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + emitter.removeListener('memoryWarning', listener); + return; + case 'blur': + case 'focus': + // $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type + // $FlowIssue[incompatible-call] + emitter.addListener('appStateFocusChange', listener); + return; + } + throw new Error('Trying to unsubscribe from unknown event: ' + type); } } -// This module depends on the native `RCTAppState` module. If you don't include it, -// `AppState.isAvailable` will return `false`, and any method calls will throw. -// We reassign the class variable to keep the autodoc generator happy. -const AppStateInstance: AppState | MissingNativeAppStateShim = NativeAppState - ? new AppState() - : new MissingNativeAppStateShim(); - -module.exports = AppStateInstance; +module.exports = (new AppState(): AppState); diff --git a/Libraries/AppState/NativeAppState.js b/Libraries/AppState/NativeAppState.js index 76f3b71619ef2c..b08fe5ca81a5c4 100644 --- a/Libraries/AppState/NativeAppState.js +++ b/Libraries/AppState/NativeAppState.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/BUCK b/Libraries/BUCK deleted file mode 100644 index 0993fce3acf8fe..00000000000000 --- a/Libraries/BUCK +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load( - "//tools/build_defs/oss:rn_codegen_defs.bzl", - "rn_codegen_modules", -) -load( - "//tools/build_defs/oss:rn_defs.bzl", - "react_native_root_target", -) - -fb_native.genrule( - name = "react_native_codegen_schema", - srcs = glob( - [ - "**/*.js", - ], - exclude = [ - "**/__tests__/**/*", - ], - ), - cmd = "$(exe {}) $OUT $SRCS".format(react_native_root_target("packages/react-native-codegen:write_to_json")), - out = "schema.json", - labels = ["codegen_rule"], -) - -rn_codegen_modules( - name = "FBReactNativeSpec", - library_labels = ["supermodule:xplat/default/public.react_native.infra"], - native_module_spec_name = "FBReactNativeSpec", - schema_target = ":react_native_codegen_schema", -) diff --git a/Libraries/BatchedBridge/MessageQueue.js b/Libraries/BatchedBridge/MessageQueue.js index fa2147b540d299..c01bbb14749ccb 100644 --- a/Libraries/BatchedBridge/MessageQueue.js +++ b/Libraries/BatchedBridge/MessageQueue.js @@ -47,7 +47,7 @@ class MessageQueue { _callID: number; _lastFlush: number; _eventLoopStartTime: number; - _immediatesCallback: ?() => void; + _reactNativeMicrotasksCallback: ?() => void; _debugInfo: {[number]: [number, number], ...}; _remoteModuleTable: {[number]: string, ...}; @@ -63,7 +63,7 @@ class MessageQueue { this._callID = 0; this._lastFlush = 0; this._eventLoopStartTime = Date.now(); - this._immediatesCallback = null; + this._reactNativeMicrotasksCallback = null; if (__DEV__) { this._debugInfo = {}; @@ -72,13 +72,16 @@ class MessageQueue { } // $FlowFixMe[cannot-write] + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.callFunctionReturnFlushedQueue = this.callFunctionReturnFlushedQueue.bind( this, ); // $FlowFixMe[cannot-write] + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.flushedQueue = this.flushedQueue.bind(this); // $FlowFixMe[cannot-write] + // $FlowFixMe[method-unbinding] added when improving typing for this parameters this.invokeCallbackAndReturnFlushedQueue = this.invokeCallbackAndReturnFlushedQueue.bind( this, ); @@ -129,7 +132,7 @@ class MessageQueue { flushedQueue(): null | [Array, Array, Array, number] { this.__guard(() => { - this.__callImmediates(); + this.__callReactNativeMicrotasks(); }); const queue = this._queue; @@ -145,14 +148,16 @@ class MessageQueue { this._lazyCallableModules[name] = () => module; } - registerLazyCallableModule(name: string, factory: void => {...}) { - let module: {...}; - let getValue: ?(void) => {...} = factory; + registerLazyCallableModule(name: string, factory: void => interface {}) { + let module: interface {}; + let getValue: ?(void) => interface {} = factory; this._lazyCallableModules[name] = () => { if (getValue) { module = getValue(); getValue = null; } + /* $FlowFixMe[class-object-subtyping] added when improving typing for + * this parameters */ return module; }; } @@ -349,8 +354,8 @@ class MessageQueue { // For JSTimers to register its callback. Otherwise a circular dependency // between modules is introduced. Note that only one callback may be // registered at a time. - setImmediatesCallback(fn: () => void) { - this._immediatesCallback = fn; + setReactNativeMicrotasksCallback(fn: () => void) { + this._reactNativeMicrotasksCallback = fn; } /** @@ -376,16 +381,16 @@ class MessageQueue { // can be configured by the VM or any Inspector __shouldPauseOnThrow(): boolean { return ( - // $FlowFixMe + // $FlowFixMe[cannot-resolve-name] typeof DebuggerInternal !== 'undefined' && DebuggerInternal.shouldPauseOnThrow === true // eslint-disable-line no-undef ); } - __callImmediates() { - Systrace.beginEvent('JSTimers.callImmediates()'); - if (this._immediatesCallback != null) { - this._immediatesCallback(); + __callReactNativeMicrotasks() { + Systrace.beginEvent('JSTimers.callReactNativeMicrotasks()'); + if (this._reactNativeMicrotasksCallback != null) { + this._reactNativeMicrotasksCallback(); } Systrace.endEvent(); } @@ -404,7 +409,7 @@ class MessageQueue { const moduleMethods = this.getCallableModule(module); invariant( !!moduleMethods, - `Module ${module} is not a registered callable module (calling ${method}). A frequent cause of the error is that the application entry file path is incorrect. + `Module ${module} is not a registered callable module (calling ${method}). A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.`, ); invariant( diff --git a/Libraries/BatchedBridge/NativeModules.js b/Libraries/BatchedBridge/NativeModules.js index 4f764463738d9f..257436199d3484 100644 --- a/Libraries/BatchedBridge/NativeModules.js +++ b/Libraries/BatchedBridge/NativeModules.js @@ -14,7 +14,7 @@ const BatchedBridge = require('./BatchedBridge'); const invariant = require('invariant'); -import type {ExtendedError} from '../Core/Devtools/parseErrorStack'; +import type {ExtendedError} from '../Core/ExtendedError'; export type ModuleConfig = [ string /* name */, @@ -101,6 +101,8 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) { if (type === 'promise') { fn = function promiseMethodWrapper(...args: Array) { // In case we reject, capture a useful stack trace here. + /* $FlowFixMe[class-object-subtyping] added when improving typing for + * this parameters */ const enqueueingFrameError: ExtendedError = new Error(); return new Promise((resolve, reject) => { BatchedBridge.enqueueNativeCall( @@ -166,6 +168,8 @@ function updateErrorWithErrorData( errorData: {message: string, ...}, error: ExtendedError, ): ExtendedError { + /* $FlowFixMe[class-object-subtyping] added when improving typing for this + * parameters */ return Object.assign(error, errorData || {}); } diff --git a/Libraries/BatchedBridge/__tests__/MessageQueue-test.js b/Libraries/BatchedBridge/__tests__/MessageQueue-test.js index e1b7fd84d32411..9c63238d8a099a 100644 --- a/Libraries/BatchedBridge/__tests__/MessageQueue-test.js +++ b/Libraries/BatchedBridge/__tests__/MessageQueue-test.js @@ -108,7 +108,7 @@ describe('MessageQueue', function() { const unknownModule = 'UnknownModule', unknownMethod = 'UnknownMethod'; expect(() => queue.__callFunction(unknownModule, unknownMethod)).toThrow( - `Module ${unknownModule} is not a registered callable module (calling ${unknownMethod}). A frequent cause of the error is that the application entry file path is incorrect. + `Module ${unknownModule} is not a registered callable module (calling ${unknownMethod}). A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.`, ); }); diff --git a/Libraries/Blob/BlobManager.js b/Libraries/Blob/BlobManager.js index e12512392a3e78..4f4310adddb582 100644 --- a/Libraries/Blob/BlobManager.js +++ b/Libraries/Blob/BlobManager.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - const Blob = require('./Blob'); const BlobRegistry = require('./BlobRegistry'); diff --git a/Libraries/Blob/FileReader.js b/Libraries/Blob/FileReader.js index 15a8b44d0bb522..a71d10fc562d3d 100644 --- a/Libraries/Blob/FileReader.js +++ b/Libraries/Blob/FileReader.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - const Blob = require('./Blob'); const EventTarget = require('event-target-shim'); @@ -48,7 +46,7 @@ class FileReader extends (EventTarget(...READER_EVENTS): any) { _error: ?Error; _result: ?ReaderResult; _aborted: boolean = false; - _subscriptions: Array<*> = []; + _subscriptions: Array = []; constructor() { super(); diff --git a/Libraries/Blob/NativeBlobModule.js b/Libraries/Blob/NativeBlobModule.js index d58aeeab6ebd4f..d43c8bc3e3b21f 100644 --- a/Libraries/Blob/NativeBlobModule.js +++ b/Libraries/Blob/NativeBlobModule.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Blob/NativeFileReaderModule.js b/Libraries/Blob/NativeFileReaderModule.js index ac135db7394d19..a33d5d9b7754dd 100644 --- a/Libraries/Blob/NativeFileReaderModule.js +++ b/Libraries/Blob/NativeFileReaderModule.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Blob/RCTBlobManager.h b/Libraries/Blob/RCTBlobManager.h index 96c8f0722f02c9..04b905ccb92a24 100755 --- a/Libraries/Blob/RCTBlobManager.h +++ b/Libraries/Blob/RCTBlobManager.h @@ -8,8 +8,9 @@ #import #import #import +#import -@interface RCTBlobManager : NSObject +@interface RCTBlobManager : NSObject - (NSString *)store:(NSData *)data; diff --git a/Libraries/Blob/RCTBlobManager.mm b/Libraries/Blob/RCTBlobManager.mm index a75844ed6ae1ed..425dc73fb6c077 100755 --- a/Libraries/Blob/RCTBlobManager.mm +++ b/Libraries/Blob/RCTBlobManager.mm @@ -37,13 +37,11 @@ @implementation RCTBlobManager RCT_EXPORT_MODULE(BlobModule) @synthesize bridge = _bridge; +@synthesize moduleRegistry = _moduleRegistry; @synthesize methodQueue = _methodQueue; -@synthesize turboModuleRegistry = _turboModuleRegistry; -- (void)setBridge:(RCTBridge *)bridge +- (void)initialize { - _bridge = bridge; - std::lock_guard lock(_blobsMutex); _blobs = [NSMutableDictionary new]; @@ -140,9 +138,9 @@ - (void)remove:(NSString *)blobId RCT_EXPORT_METHOD(addNetworkingHandler) { - RCTNetworking *const networking = _bridge ? _bridge.networking : [_turboModuleRegistry moduleForName:"RCTNetworking"]; + RCTNetworking *const networking = [_moduleRegistry moduleForName:"Networking"]; - // TODO(T63516227): Why can methodQueue be nil here? + // TODO(T63516227): Why can methodQueue be nil here? // We don't want to do anything when methodQueue is nil. if (!networking.methodQueue) { return; @@ -156,23 +154,23 @@ - (void)remove:(NSString *)blobId RCT_EXPORT_METHOD(addWebSocketHandler:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule setContentHandler:self forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] setContentHandler:self forSocketID:[NSNumber numberWithDouble:socketID]]; }); } RCT_EXPORT_METHOD(removeWebSocketHandler:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule setContentHandler:nil forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] setContentHandler:nil forSocketID:[NSNumber numberWithDouble:socketID]]; }); } // @lint-ignore FBOBJCUNTYPEDCOLLECTION1 RCT_EXPORT_METHOD(sendOverSocket:(NSDictionary *)blob socketID:(double)socketID) { - dispatch_async(_bridge.webSocketModule.methodQueue, ^{ - [self->_bridge.webSocketModule sendData:[self resolve:blob] forSocketID:[NSNumber numberWithDouble:socketID]]; + dispatch_async(((RCTWebSocketModule *)[_moduleRegistry moduleForName:"WebSocketModule"]).methodQueue, ^{ + [[self->_moduleRegistry moduleForName:"WebSocketModule"] sendData:[self resolve:blob] forSocketID:[NSNumber numberWithDouble:socketID]]; }); } diff --git a/Libraries/Blob/RCTBlobPlugins.mm b/Libraries/Blob/RCTBlobPlugins.mm index d06f40e5d21120..289094f35d43a0 100644 --- a/Libraries/Blob/RCTBlobPlugins.mm +++ b/Libraries/Blob/RCTBlobPlugins.mm @@ -17,13 +17,14 @@ #import Class RCTBlobClassProvider(const char *name) { - static std::unordered_map sCoreModuleClassMap = { + // Intentionally leak to avoid crashing after static destructors are run. + static const auto sCoreModuleClassMap = new const std::unordered_map{ {"FileReaderModule", RCTFileReaderModuleCls}, {"BlobModule", RCTBlobManagerCls}, }; - auto p = sCoreModuleClassMap.find(name); - if (p != sCoreModuleClassMap.end()) { + auto p = sCoreModuleClassMap->find(name); + if (p != sCoreModuleClassMap->end()) { auto classFunc = p->second; return classFunc(); } diff --git a/Libraries/Blob/RCTFileReaderModule.mm b/Libraries/Blob/RCTFileReaderModule.mm index 315605acc1174d..2525de0c201b2b 100644 --- a/Libraries/Blob/RCTFileReaderModule.mm +++ b/Libraries/Blob/RCTFileReaderModule.mm @@ -23,15 +23,14 @@ @implementation RCTFileReaderModule RCT_EXPORT_MODULE(FileReaderModule) -@synthesize bridge = _bridge; -@synthesize turboModuleRegistry = _turboModuleRegistry; +@synthesize moduleRegistry = _moduleRegistry; RCT_EXPORT_METHOD(readAsText:(NSDictionary *)blob encoding:(NSString *)encoding resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - RCTBlobManager *blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]]; + RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"]; NSData *data = [blobManager resolve:blob]; if (data == nil) { @@ -56,12 +55,7 @@ @implementation RCTFileReaderModule resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - RCTBlobManager *blobManager = nil; - if ([self bridge]) { - blobManager = [[self bridge] moduleForClass:[RCTBlobManager class]]; - } else { - blobManager = [[self turboModuleRegistry] moduleForName:[NSStringFromClass([RCTBlobManager class]) UTF8String]]; - } + RCTBlobManager *blobManager = [_moduleRegistry moduleForName:"BlobModule"]; NSData *data = [blobManager resolve:blob]; if (data == nil) { diff --git a/Libraries/Blob/React-RCTBlob.podspec b/Libraries/Blob/React-RCTBlob.podspec index 8522ca699905cb..7edd6d980a7d66 100644 --- a/Libraries/Blob/React-RCTBlob.podspec +++ b/Libraries/Blob/React-RCTBlob.podspec @@ -11,13 +11,13 @@ version = package['version'] source = { :git => 'https://github.com/facebook/react-native.git' } if version == '1000.0.0' # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. - source[:commit] = `git rev-parse HEAD`.strip + source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") else source[:tag] = "v#{version}" end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2020.01.13.00' +folly_version = '2021.06.28.00-v2' Pod::Spec.new do |s| s.name = "React-RCTBlob" @@ -26,7 +26,7 @@ Pod::Spec.new do |s| s.homepage = "https://reactnative.dev/" s.license = package["license"] s.author = "Facebook, Inc. and its affiliates" - s.platforms = { :ios => "10.0", :osx => "10.14" } # TODO(macOS GH#214) + s.platforms = { :ios => "11.0", :osx => "10.15" } # TODO(macOS GH#214) s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' s.source = source s.source_files = "*.{h,m,mm}" diff --git a/Libraries/Blob/URL.js b/Libraries/Blob/URL.js index bf9ab01bf1a786..3e63ff753fa179 100644 --- a/Libraries/Blob/URL.js +++ b/Libraries/Blob/URL.js @@ -7,8 +7,6 @@ * @format */ -'use strict'; - const Blob = require('./Blob'); import NativeBlobModule from './NativeBlobModule'; @@ -51,7 +49,7 @@ if ( * ``` */ -// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/lib +// Small subset from whatwg-url: https://github.com/jsdom/whatwg-url/tree/master/src // The reference code bloat comes from Unicode issues with URLs, so those won't work here. export class URLSearchParams { _searchParams = []; @@ -67,27 +65,27 @@ export class URLSearchParams { } delete(name) { - throw new Error('not implemented'); + throw new Error('URLSearchParams.delete is not implemented'); } get(name) { - throw new Error('not implemented'); + throw new Error('URLSearchParams.get is not implemented'); } getAll(name) { - throw new Error('not implemented'); + throw new Error('URLSearchParams.getAll is not implemented'); } has(name) { - throw new Error('not implemented'); + throw new Error('URLSearchParams.has is not implemented'); } set(name, value) { - throw new Error('not implemented'); + throw new Error('URLSearchParams.set is not implemented'); } sort() { - throw new Error('not implemented'); + throw new Error('URLSearchParams.sort is not implemented'); } [Symbol.iterator]() { @@ -107,7 +105,7 @@ export class URLSearchParams { function validateBaseUrl(url: string) { // from this MIT-licensed gist: https://gist.github.com/dperini/729294 - return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( + return /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)*(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/.test( url, ); } @@ -156,15 +154,15 @@ export class URL { } get hash() { - throw new Error('not implemented'); + throw new Error('URL.hash is not implemented'); } get host() { - throw new Error('not implemented'); + throw new Error('URL.host is not implemented'); } get hostname() { - throw new Error('not implemented'); + throw new Error('URL.hostname is not implemented'); } get href(): string { @@ -172,27 +170,27 @@ export class URL { } get origin() { - throw new Error('not implemented'); + throw new Error('URL.origin is not implemented'); } get password() { - throw new Error('not implemented'); + throw new Error('URL.password is not implemented'); } get pathname() { - throw new Error('not implemented'); + throw new Error('URL.pathname not implemented'); } get port() { - throw new Error('not implemented'); + throw new Error('URL.port is not implemented'); } get protocol() { - throw new Error('not implemented'); + throw new Error('URL.protocol is not implemented'); } get search() { - throw new Error('not implemented'); + throw new Error('URL.search is not implemented'); } get searchParams(): URLSearchParams { @@ -215,6 +213,6 @@ export class URL { } get username() { - throw new Error('not implemented'); + throw new Error('URL.username is not implemented'); } } diff --git a/Libraries/BugReporting/BugReporting.js b/Libraries/BugReporting/BugReporting.js index d2f3c4a442a4c9..d0f8dc2b18c73e 100644 --- a/Libraries/BugReporting/BugReporting.js +++ b/Libraries/BugReporting/BugReporting.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter'; import NativeRedBox from '../NativeModules/specs/NativeRedBox'; import {type EventSubscription} from '../vendor/emitter/EventEmitter'; @@ -45,6 +43,7 @@ class BugReporting { if (!BugReporting._subscription) { BugReporting._subscription = RCTDeviceEventEmitter.addListener( 'collectBugExtraData', + // $FlowFixMe[method-unbinding] BugReporting.collectExtraData, null, ); @@ -54,6 +53,7 @@ class BugReporting { if (!BugReporting._redboxSubscription) { BugReporting._redboxSubscription = RCTDeviceEventEmitter.addListener( 'collectRedBoxExtraData', + // $FlowFixMe[method-unbinding] BugReporting.collectExtraData, null, ); diff --git a/Libraries/BugReporting/getReactData.js b/Libraries/BugReporting/getReactData.js index cc9bc55f0cc394..c851f76f993f6a 100644 --- a/Libraries/BugReporting/getReactData.js +++ b/Libraries/BugReporting/getReactData.js @@ -14,7 +14,7 @@ * Convert a react internal instance to a sanitized data object. * * This is shamelessly stolen from react-devtools: - * https://github.com/facebook/react-devtools/blob/master/backend/getData.js + * https://github.com/facebook/react-devtools/blob/HEAD/backend/getData.js */ function getData(element: Object): Object { let children = null; @@ -162,7 +162,7 @@ function copyWithSetImpl(obj, path, idx, value) { } const key = path[idx]; const updated = Array.isArray(obj) ? obj.slice() : {...obj}; - // $FlowFixMe number or string is fine here + // $FlowFixMe[incompatible-use] number or string is fine here updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); return updated; } diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js deleted file mode 100644 index 138912dcf14ac7..00000000000000 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.android.js +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; -import UIManager from '../../ReactNative/UIManager'; -import NativeAccessibilityInfo from './NativeAccessibilityInfo'; - -const REDUCE_MOTION_EVENT = 'reduceMotionDidChange'; -const TOUCH_EXPLORATION_EVENT = 'touchExplorationDidChange'; - -type ChangeEventName = $Keys<{ - change: string, - reduceMotionChanged: string, - screenReaderChanged: string, - ... -}>; - -const _subscriptions = new Map(); - -/** - * Sometimes it's useful to know whether or not the device has a screen reader - * that is currently active. The `AccessibilityInfo` API is designed for this - * purpose. You can use it to query the current state of the screen reader as - * well as to register to be notified when the state of the screen reader - * changes. - * - * See https://reactnative.dev/docs/accessibilityinfo.html - */ - -const AccessibilityInfo = { - /** - * iOS only - */ - isBoldTextEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * iOS only - */ - isGrayscaleEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * macOS only - */ - isHighContrastEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * iOS only - */ - isInvertColorsEnabled: function(): Promise { - return Promise.resolve(false); - }, - - isReduceMotionEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityInfo) { - NativeAccessibilityInfo.isReduceMotionEnabled(resolve); - } else { - reject(false); - } - }); - }, - - /** - * iOS only - */ - isReduceTransparencyEnabled: function(): Promise { - return Promise.resolve(false); - }, - - isScreenReaderEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityInfo) { - NativeAccessibilityInfo.isTouchExplorationEnabled(resolve); - } else { - reject(false); - } - }); - }, - - /** - * Deprecated - * - * Same as `isScreenReaderEnabled` - */ - // $FlowFixMe[unsafe-getters-setters] - get fetch(): () => Promise { - console.warn( - 'AccessibilityInfo.fetch is deprecated, call AccessibilityInfo.isScreenReaderEnabled instead', - ); - return this.isScreenReaderEnabled; - }, - - addEventListener: function(eventName: ChangeEventName, handler: T): void { - let listener; - - if (eventName === 'change' || eventName === 'screenReaderChanged') { - listener = RCTDeviceEventEmitter.addListener( - TOUCH_EXPLORATION_EVENT, - handler, - ); - } else if (eventName === 'reduceMotionChanged') { - listener = RCTDeviceEventEmitter.addListener( - REDUCE_MOTION_EVENT, - handler, - ); - } - - // $FlowFixMe[escaped-generic] - _subscriptions.set(handler, listener); - }, - - removeEventListener: function( - eventName: ChangeEventName, - handler: T, - ): void { - // $FlowFixMe[escaped-generic] - const listener = _subscriptions.get(handler); - if (!listener) { - return; - } - listener.remove(); - // $FlowFixMe[escaped-generic] - _subscriptions.delete(handler); - }, - - /** - * Set accessibility focus to a react component. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus - */ - setAccessibilityFocus: function(reactTag: number): void { - UIManager.sendAccessibilityEvent( - reactTag, - UIManager.getConstants().AccessibilityEventTypes.typeViewFocused, - ); - }, - - /** - * Post a string to be announced by the screen reader. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#announceforaccessibility - */ - announceForAccessibility: function(announcement: string): void { - if (NativeAccessibilityInfo) { - NativeAccessibilityInfo.announceForAccessibility(announcement); - } - }, -}; - -module.exports = AccessibilityInfo; diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js deleted file mode 100644 index fa73f4d692151a..00000000000000 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.ios.js +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; -import NativeAccessibilityManager from './NativeAccessibilityManager'; - -const CHANGE_EVENT_NAME = { - announcementFinished: 'announcementFinished', - boldTextChanged: 'boldTextChanged', - grayscaleChanged: 'grayscaleChanged', - invertColorsChanged: 'invertColorsChanged', - reduceMotionChanged: 'reduceMotionChanged', - reduceTransparencyChanged: 'reduceTransparencyChanged', - screenReaderChanged: 'screenReaderChanged', -}; - -type ChangeEventName = $Keys<{ - announcementFinished: string, - boldTextChanged: string, - change: string, - grayscaleChanged: string, - invertColorsChanged: string, - reduceMotionChanged: string, - reduceTransparencyChanged: string, - screenReaderChanged: string, - ... -}>; - -const _subscriptions = new Map(); - -/** - * Sometimes it's useful to know whether or not the device has a screen reader - * that is currently active. The `AccessibilityInfo` API is designed for this - * purpose. You can use it to query the current state of the screen reader as - * well as to register to be notified when the state of the screen reader - * changes. - * - * See https://reactnative.dev/docs/accessibilityinfo.html - */ -const AccessibilityInfo = { - /** - * Query whether bold text is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when bold text is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isBoldTextEnabled - */ - isBoldTextEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentBoldTextState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether grayscale is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when grayscale is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isGrayscaleEnabled - */ - isGrayscaleEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentGrayscaleState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * macOS only - */ - isHighContrastEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * Query whether inverted colors are currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when invert color is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isInvertColorsEnabled - */ - isInvertColorsEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentInvertColorsState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether reduced motion is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a reduce motion is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceMotionEnabled - */ - isReduceMotionEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentReduceMotionState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether reduced transparency is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a reduce transparency is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceTransparencyEnabled - */ - isReduceTransparencyEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentReduceTransparencyState( - resolve, - reject, - ); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether a screen reader is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a screen reader is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#isScreenReaderEnabled - */ - isScreenReaderEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Deprecated - * - * Same as `isScreenReaderEnabled` - */ - // $FlowFixMe[unsafe-getters-setters] - get fetch(): $FlowFixMe { - console.warn( - 'AccessibilityInfo.fetch is deprecated, call AccessibilityInfo.isScreenReaderEnabled instead', - ); - return this.isScreenReaderEnabled; - }, - - /** - * Add an event handler. Supported events: - * - * - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a bold text - * is enabled and `false` otherwise. - * - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a gray scale - * is enabled and `false` otherwise. - * - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle - * changes. The argument to the event handler is a boolean. The boolean is `true` when a invert - * colors is enabled and `false` otherwise. - * - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a reduce - * motion is enabled (or when "Transition Animation Scale" in "Developer options" is - * "Animation off") and `false` otherwise. - * - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency - * toggle changes. The argument to the event handler is a boolean. The boolean is `true` - * when a reduce transparency is enabled and `false` otherwise. - * - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument - * to the event handler is a boolean. The boolean is `true` when a screen - * reader is enabled and `false` otherwise. - * - `announcementFinished`: iOS-only event. Fires when the screen reader has - * finished making an announcement. The argument to the event handler is a - * dictionary with these keys: - * - `announcement`: The string announced by the screen reader. - * - `success`: A boolean indicating whether the announcement was - * successfully made. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#addeventlistener - */ - addEventListener: function( - eventName: ChangeEventName, - handler: T, - ): {remove: () => void} { - let listener; - - if (eventName === 'change') { - listener = RCTDeviceEventEmitter.addListener( - CHANGE_EVENT_NAME.screenReaderChanged, - handler, - ); - } else if (CHANGE_EVENT_NAME[eventName]) { - listener = RCTDeviceEventEmitter.addListener(eventName, handler); - } - - // $FlowFixMe[escaped-generic] - _subscriptions.set(handler, listener); - return { - remove: AccessibilityInfo.removeEventListener.bind( - null, - eventName, - handler, - ), - }; - }, - - /** - * Set accessibility focus to a react component. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus - */ - setAccessibilityFocus: function(reactTag: number): void { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.setAccessibilityFocus(reactTag); - } - }, - - /** - * Post a string to be announced by the screen reader. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#announceforaccessibility - */ - announceForAccessibility: function(announcement: string): void { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.announceForAccessibility(announcement); - } - }, - - /** - * Remove an event handler. - * - * See https://reactnative.dev/docs/accessibilityinfo.html#removeeventlistener - */ - removeEventListener: function( - eventName: ChangeEventName, - handler: T, - ): void { - // $FlowFixMe[escaped-generic] - const listener = _subscriptions.get(handler); - if (!listener) { - return; - } - listener.remove(); - // $FlowFixMe[escaped-generic] - _subscriptions.delete(handler); - }, -}; - -module.exports = AccessibilityInfo; diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js new file mode 100644 index 00000000000000..8c3f38204d12fa --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -0,0 +1,372 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; +import {sendAccessibilityEvent} from '../../Renderer/shims/ReactNative'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import Platform from '../../Utilities/Platform'; +import type EventEmitter from '../../vendor/emitter/EventEmitter'; +import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; +import NativeAccessibilityInfoAndroid from './NativeAccessibilityInfo'; +import NativeAccessibilityManagerApple from './NativeAccessibilityManager'; +import legacySendAccessibilityEvent from './legacySendAccessibilityEvent'; +import type {ElementRef} from 'react'; + +// Events that are only supported on iOS. +type AccessibilityEventDefinitionsIOS = { + announcementFinished: [{announcement: string, success: boolean}], + boldTextChanged: [boolean], + grayscaleChanged: [boolean], + invertColorsChanged: [boolean], + reduceTransparencyChanged: [boolean], +}; + +type AccessibilityEventDefinitions = { + ...AccessibilityEventDefinitionsIOS, + highContrastChanged: [boolean], // TODO(macOS GH#774) - highContrastChanged is used on macOS + change: [boolean], // screenReaderChanged + reduceMotionChanged: [boolean], + screenReaderChanged: [boolean], +}; + +type AccessibilityEventTypes = 'click' | 'focus'; + +// Mapping of public event names to platform-specific event names. +const EventNames: Map<$Keys, string> = + Platform.OS === 'android' + ? new Map([ + ['change', 'touchExplorationDidChange'], + ['reduceMotionChanged', 'reduceMotionDidChange'], + ['screenReaderChanged', 'touchExplorationDidChange'], + ]) + : new Map([ + ['announcementFinished', 'announcementFinished'], + ['boldTextChanged', 'boldTextChanged'], + ['change', 'screenReaderChanged'], + ['grayscaleChanged', 'grayscaleChanged'], + ['highContrastChanged', 'highContrastChanged'], + ['invertColorsChanged', 'invertColorsChanged'], + ['reduceMotionChanged', 'reduceMotionChanged'], + ['reduceTransparencyChanged', 'reduceTransparencyChanged'], + ['screenReaderChanged', 'screenReaderChanged'], + ]); + +/** + * Sometimes it's useful to know whether or not the device has a screen reader + * that is currently active. The `AccessibilityInfo` API is designed for this + * purpose. You can use it to query the current state of the screen reader as + * well as to register to be notified when the state of the screen reader + * changes. + * + * See https://reactnative.dev/docs/accessibilityinfo.html + */ +const AccessibilityInfo = { + /** + * Query whether bold text is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when bold text is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isBoldTextEnabled + */ + isBoldTextEnabled(): Promise { + if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { + return new Promise((resolve, reject) => { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentBoldTextState( + resolve, + reject, + ); + } else { + reject(null); + } + }); + } + }, + + /** + * Query whether grayscale is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when grayscale is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isGrayscaleEnabled + */ + isGrayscaleEnabled(): Promise { + if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { + return new Promise((resolve, reject) => { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentGrayscaleState( + resolve, + reject, + ); + } else { + reject(null); + } + }); + } + }, + + /** + * macOS only + */ + isHighContrastEnabled: function(): Promise { + if (Platform.OS === 'macos') { + return new Promise((resolve, reject) => { + if (NativeAccessibilityManagerApple) { + NativeAccessibilityManagerApple.getCurrentHighContrastState( + resolve, + reject, + ); + } else { + reject(reject); + } + }); + } else { + return Promise.resolve(false); + } + }, + + /** + * Query whether inverted colors are currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when invert color is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isInvertColorsEnabled + */ + isInvertColorsEnabled(): Promise { + if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { + return new Promise((resolve, reject) => { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentInvertColorsState( + resolve, + reject, + ); + } else { + reject(null); + } + }); + } + }, + + /** + * Query whether reduced motion is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when a reduce motion is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceMotionEnabled + */ + isReduceMotionEnabled(): Promise { + return new Promise((resolve, reject) => { + if (Platform.OS === 'android') { + if (NativeAccessibilityInfoAndroid != null) { + NativeAccessibilityInfoAndroid.isReduceMotionEnabled(resolve); + } else { + reject(null); + } + } else { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentReduceMotionState( + resolve, + reject, + ); + } else { + reject(null); + } + } + }); + }, + + /** + * Query whether reduced transparency is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when a reduce transparency is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isReduceTransparencyEnabled + */ + isReduceTransparencyEnabled(): Promise { + if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { + return new Promise((resolve, reject) => { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentReduceTransparencyState( + resolve, + reject, + ); + } else { + reject(null); + } + }); + } + }, + + /** + * Query whether a screen reader is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when a screen reader is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#isScreenReaderEnabled + */ + isScreenReaderEnabled(): Promise { + return new Promise((resolve, reject) => { + if (Platform.OS === 'android') { + if (NativeAccessibilityInfoAndroid != null) { + NativeAccessibilityInfoAndroid.isTouchExplorationEnabled(resolve); + } else { + reject(null); + } + } else { + if (NativeAccessibilityManagerApple != null) { + NativeAccessibilityManagerApple.getCurrentVoiceOverState( + resolve, + reject, + ); + } else { + reject(null); + } + } + }); + }, + + /** + * Add an event handler. Supported events: + * + * - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a reduce + * motion is enabled (or when "Transition Animation Scale" in "Developer options" is + * "Animation off") and `false` otherwise. + * - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument + * to the event handler is a boolean. The boolean is `true` when a screen + * reader is enabled and `false` otherwise. + * + * These events are only supported on iOS: + * + * - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a bold text + * is enabled and `false` otherwise. + * - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a gray scale + * is enabled and `false` otherwise. + * - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle + * changes. The argument to the event handler is a boolean. The boolean is `true` when a invert + * colors is enabled and `false` otherwise. + * - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency + * toggle changes. The argument to the event handler is a boolean. The boolean is `true` + * when a reduce transparency is enabled and `false` otherwise. + * - `announcementFinished`: iOS-only event. Fires when the screen reader has + * finished making an announcement. The argument to the event handler is a + * dictionary with these keys: + * - `announcement`: The string announced by the screen reader. + * - `success`: A boolean indicating whether the announcement was + * successfully made. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#addeventlistener + */ + addEventListener>( + eventName: K, + handler: (...$ElementType) => void, + ): EventSubscription { + const deviceEventName = EventNames.get(eventName); + return deviceEventName == null + ? {remove(): void {}} + : RCTDeviceEventEmitter.addListener(deviceEventName, handler); + }, + + /** + * Set accessibility focus to a React component. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#setaccessibilityfocus + */ + setAccessibilityFocus(reactTag: number): void { + legacySendAccessibilityEvent(reactTag, 'focus'); + }, + + /** + * Send a named accessibility event to a HostComponent. + */ + sendAccessibilityEvent_unstable( + handle: ElementRef>, + eventType: AccessibilityEventTypes, + ) { + // iOS only supports 'focus' event types + if (Platform.OS === 'ios' && eventType === 'click') { + return; + } + // route through React renderer to distinguish between Fabric and non-Fabric handles + sendAccessibilityEvent(handle, eventType); + }, + + /** + * Post a string to be announced by the screen reader. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#announceforaccessibility + */ + announceForAccessibility(announcement: string): void { + if (Platform.OS === 'android') { + NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement); + } else { + NativeAccessibilityManagerApple?.announceForAccessibility(announcement); + } + }, + + /** + * @deprecated Use `remove` on the EventSubscription from `addEventListener`. + */ + removeEventListener>( + eventName: K, + handler: (...$ElementType) => void, + ): void { + // NOTE: This will report a deprecation notice via `console.error`. + const deviceEventName = EventNames.get(eventName); + if (deviceEventName != null) { + // $FlowIgnore[incompatible-cast] + (RCTDeviceEventEmitter: EventEmitter<$FlowFixMe>).removeListener( + 'deviceEventName', + // $FlowFixMe[invalid-tuple-arity] + handler, + ); + } + }, + + /** + * Get the recommended timeout for changes to the UI needed by this user. + * + * See https://reactnative.dev/docs/accessibilityinfo.html#getrecommendedtimeoutmillis + */ + getRecommendedTimeoutMillis(originalTimeout: number): Promise { + if (Platform.OS === 'android') { + return new Promise((resolve, reject) => { + if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis) { + NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis( + originalTimeout, + resolve, + ); + } else { + resolve(originalTimeout); + } + }); + } else { + return Promise.resolve(originalTimeout); + } + }, +}; + +export default AccessibilityInfo; diff --git a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js b/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js deleted file mode 100644 index 910fbc1f047e5d..00000000000000 --- a/Libraries/Components/AccessibilityInfo/AccessibilityInfo.macos.js +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -// TODO(macOS GH#774) - -'use strict'; - -const Promise = require('../../Promise'); -import RCTDeviceEventEmitter from '../../EventEmitter/RCTDeviceEventEmitter'; - -import NativeAccessibilityManager from './NativeAccessibilityManager'; - -const CHANGE_EVENT_NAME = { - highContrastChanged: 'highContrastChanged', - invertColorsChanged: 'invertColorsChanged', - reduceMotionChanged: 'reduceMotionChanged', - reduceTransparencyChanged: 'reduceTransparencyChanged', - screenReaderChanged: 'screenReaderChanged', -}; - -type ChangeEventName = $Keys<{ - change: string, - highContrastChanged: string, - invertColorsChanged: string, - reduceMotionChanged: string, - reduceTransparencyChanged: string, - screenReaderChanged: string, -}>; - -const _subscriptions = new Map(); - -/** - * Sometimes it's useful to know whether or not the device has a screen reader - * that is currently active. The `AccessibilityInfo` API is designed for this - * purpose. You can use it to query the current state of the screen reader as - * well as to register to be notified when the state of the screen reader - * changes. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html - */ -const AccessibilityInfo = { - /** - * iOS only - */ - isBoldTextEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * iOS only - */ - isGrayscaleEnabled: function(): Promise { - return Promise.resolve(false); - }, - - /** - * Query whether high contrast is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when invert color is enabled and `false` otherwise. - */ - isHighContrastEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentHighContrastState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether inverted colors are currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when invert color is enabled and `false` otherwise. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isInvertColorsEnabled - */ - isInvertColorsEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentInvertColorsState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether reduced motion is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a reduce motion is enabled and `false` otherwise. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceMotionEnabled - */ - isReduceMotionEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentReduceMotionState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether reduced transparency is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a reduce transparency is enabled and `false` otherwise. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isReduceTransparencyEnabled - */ - isReduceTransparencyEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentReduceTransparencyState( - resolve, - reject, - ); - } else { - reject(reject); - } - }); - }, - - /** - * Query whether a screen reader is currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when a screen reader is enabled and `false` otherwise. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#isScreenReaderEnabled - */ - isScreenReaderEnabled: function(): Promise { - return new Promise((resolve, reject) => { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.getCurrentVoiceOverState(resolve, reject); - } else { - reject(reject); - } - }); - }, - - /** - * Deprecated - * - * Same as `isScreenReaderEnabled` - */ - get fetch(): $FlowFixMe { - console.warn( - 'AccessibilityInfo.fetch is deprecated, call Accessibility.isScreenReaderEnabled instead', - ); - return this.isScreenReaderEnabled; - }, - - addEventListener: function( - eventName: ChangeEventName, - handler: Function, - ): Object { - let listener; - - if (eventName === 'change') { - listener = RCTDeviceEventEmitter.addListener( - CHANGE_EVENT_NAME.screenReaderChanged, - handler, - ); - } else if (CHANGE_EVENT_NAME[eventName]) { - listener = RCTDeviceEventEmitter.addListener(eventName, handler); - } - - _subscriptions.set(handler, listener); - return { - remove: AccessibilityInfo.removeEventListener.bind( - null, - eventName, - handler, - ), - }; - }, - - /** - * Set accessibility focus to a react component. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#setaccessibilityfocus - */ - setAccessibilityFocus: function(reactTag: number): void { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.setAccessibilityFocus(reactTag); - } - }, - - /** - * Post a string to be announced by the screen reader. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#announceforaccessibility - */ - announceForAccessibility: function(announcement: string): void { - if (NativeAccessibilityManager) { - NativeAccessibilityManager.announceForAccessibility(announcement); - } - }, - - /** - * Remove an event handler. - * - * See http://facebook.github.io/react-native/docs/accessibilityinfo.html#removeeventlistener - */ - removeEventListener: function( - eventName: ChangeEventName, - handler: Function, - ): void { - const listener = _subscriptions.get(handler); - if (!listener) { - return; - } - listener.remove(); - _subscriptions.delete(handler); - }, -}; - -module.exports = AccessibilityInfo; diff --git a/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js b/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js index 03484f2158c10d..916667aa5c2c0a 100644 --- a/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js +++ b/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry'; @@ -22,6 +20,10 @@ export interface Spec extends TurboModule { ) => void; +setAccessibilityFocus: (reactTag: number) => void; +announceForAccessibility: (announcement: string) => void; + +getRecommendedTimeoutMillis?: ( + mSec: number, + onSuccess: (recommendedTimeoutMillis: number) => void, + ) => void; } export default (TurboModuleRegistry.get('AccessibilityInfo'): ?Spec); diff --git a/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js b/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js index 6fc0f56e13e7cd..e8e95f22c3abc3 100644 --- a/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js +++ b/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js new file mode 100644 index 00000000000000..3bb1c554950d50 --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.android.js @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +import UIManager from '../../ReactNative/UIManager'; + +/** + * This is a function exposed to the React Renderer that can be used by the + * pre-Fabric renderer to emit accessibility events to pre-Fabric nodes. + */ +function legacySendAccessibilityEvent( + reactTag: number, + eventType: string, +): void { + if (eventType === 'focus') { + UIManager.sendAccessibilityEvent( + reactTag, + UIManager.getConstants().AccessibilityEventTypes.typeViewFocused, + ); + } + if (eventType === 'click') { + UIManager.sendAccessibilityEvent( + reactTag, + UIManager.getConstants().AccessibilityEventTypes.typeViewClicked, + ); + } +} + +module.exports = legacySendAccessibilityEvent; diff --git a/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js new file mode 100644 index 00000000000000..950336d1101c44 --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.ios.js @@ -0,0 +1,26 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +import NativeAccessibilityManager from './NativeAccessibilityManager'; + +/** + * This is a function exposed to the React Renderer that can be used by the + * pre-Fabric renderer to emit accessibility events to pre-Fabric nodes. + */ +function legacySendAccessibilityEvent( + reactTag: number, + eventType: string, +): void { + if (eventType === 'focus' && NativeAccessibilityManager) { + NativeAccessibilityManager.setAccessibilityFocus(reactTag); + } +} + +module.exports = legacySendAccessibilityEvent; diff --git a/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.macos.js b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.macos.js new file mode 100644 index 00000000000000..831db39d1336c1 --- /dev/null +++ b/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.macos.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +// TODO(macOS GH#774) + +/* $FlowFixMe allow macOS to share iOS file */ +const legacySendAccessibilityEvent = require('./legacySendAccessibilityEvent.ios'); + +module.exports = legacySendAccessibilityEvent; diff --git a/Libraries/Components/ActivityIndicator/ActivityIndicator.js b/Libraries/Components/ActivityIndicator/ActivityIndicator.js index 52cbda4a7312e2..9100cf6483de2a 100644 --- a/Libraries/Components/ActivityIndicator/ActivityIndicator.js +++ b/Libraries/Components/ActivityIndicator/ActivityIndicator.js @@ -10,14 +10,12 @@ */ 'use strict'; - -const Platform = require('../../Utilities/Platform'); -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const View = require('../View/View'); +import * as React from 'react'; +import Platform from '../../Utilities/Platform'; +import StyleSheet, {type ColorValue} from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {ViewProps} from '../View/ViewPropTypes'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; const PlatformActivityIndicator = Platform.OS === 'android' @@ -62,8 +60,18 @@ type Props = $ReadOnly<{| size?: ?IndicatorSize, |}>; -const ActivityIndicator = (props: Props, forwardedRef?: any) => { - const {onLayout, style, size, ...restProps} = props; +const ActivityIndicator = ( + { + animating = true, + color = Platform.OS === 'ios' ? GRAY : null, + hidesWhenStopped = true, + onLayout, + size = 'small', + style, + ...restProps + }: Props, + forwardedRef?: any, +) => { let sizeStyle; let sizeProp; @@ -77,11 +85,14 @@ const ActivityIndicator = (props: Props, forwardedRef?: any) => { sizeProp = 'large'; break; default: - sizeStyle = {height: props.size, width: props.size}; + sizeStyle = {height: size, width: size}; break; } const nativeProps = { + animating, + color, + hidesWhenStopped, ...restProps, ref: forwardedRef, style: sizeStyle, @@ -98,10 +109,10 @@ const ActivityIndicator = (props: Props, forwardedRef?: any) => { onLayout={onLayout} style={StyleSheet.compose(styles.container, style)}> {Platform.OS === 'android' ? ( - // $FlowFixMe Flow doesn't know when this is the android component + // $FlowFixMe[prop-missing] Flow doesn't know when this is the android component ) : ( - /* $FlowFixMe(>=0.106.0 site=react_native_android_fb) This comment + /* $FlowFixMe[prop-missing] (>=0.106.0 site=react_native_android_fb) This comment * suppresses an error found when Flow v0.106 was deployed. To see the * error, delete this comment and run Flow. */ @@ -178,16 +189,6 @@ const ActivityIndicatorWithRef: React.AbstractComponent< > = React.forwardRef(ActivityIndicator); ActivityIndicatorWithRef.displayName = 'ActivityIndicator'; -/* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an error - * found when Flow v0.89 was deployed. To see the error, delete this comment - * and run Flow. */ -ActivityIndicatorWithRef.defaultProps = { - animating: true, - color: Platform.OS === 'ios' ? GRAY : null, - hidesWhenStopped: true, - size: 'small', -}; - const styles = StyleSheet.create({ container: { alignItems: 'center', diff --git a/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js b/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js index a7a95da5943c1d..3475cebeddeabd 100644 --- a/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js +++ b/Libraries/Components/ActivityIndicator/ActivityIndicatorViewNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {WithDefault} from '../../Types/CodegenTypes'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; diff --git a/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap b/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap index d8316e939d13d1..4326d7f8ae20f3 100644 --- a/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap +++ b/Libraries/Components/ActivityIndicator/__tests__/__snapshots__/ActivityIndicator-test.js.snap @@ -2,9 +2,7 @@ exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` `; @@ -35,18 +33,14 @@ exports[` should render as expected: should deep render whe exports[` should render as expected: should shallow render as when mocked 1`] = ` `; exports[` should render as expected: should shallow render as when not mocked 1`] = ` `; diff --git a/Libraries/Components/Button.js b/Libraries/Components/Button.js index 9c712d492fc5fd..d47fbfb938c887 100644 --- a/Libraries/Components/Button.js +++ b/Libraries/Components/Button.js @@ -11,24 +11,24 @@ 'use strict'; -const Platform = require('../Utilities/Platform'); -const React = require('react'); -const StyleSheet = require('../StyleSheet/StyleSheet'); -const Text = require('../Text/Text'); -const TouchableNativeFeedback = require('./Touchable/TouchableNativeFeedback'); -const TouchableOpacity = require('./Touchable/TouchableOpacity'); -const View = require('./View/View'); - -const invariant = require('invariant'); - -import type {PressEvent, KeyEvent} from '../Types/CoreEventTypes'; +import * as React from 'react'; +import Platform from '../Utilities/Platform'; +import StyleSheet, {type ColorValue} from '../StyleSheet/StyleSheet'; +import Text from '../Text/Text'; +import TouchableNativeFeedback from './Touchable/TouchableNativeFeedback'; +import TouchableOpacity from './Touchable/TouchableOpacity'; +import View from './View/View'; +import invariant from 'invariant'; +import type {KeyEvent} from '../Types/CoreEventTypes'; // TODO(OSS Candidate ISS#2710739) import type {FocusEvent, BlurEvent} from './TextInput/TextInput'; // TODO(OSS Candidate ISS#2710739) -import type {ColorValue} from '../StyleSheet/StyleSheet'; + import type { AccessibilityActionEvent, AccessibilityActionInfo, AccessibilityRole, + AccessibilityState, } from './View/ViewAccessibility'; +import type {PressEvent} from '../Types/CoreEventTypes'; type ButtonProps = $ReadOnly<{| /** @@ -143,7 +143,6 @@ type ButtonProps = $ReadOnly<{| /** * Accessibility action handlers */ - accessibilityActions?: ?$ReadOnlyArray, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, /** @@ -196,6 +195,14 @@ type ButtonProps = $ReadOnly<{| */ tooltip?: string, // ]TODO(OSS Candidate ISS#2710739) + + /** + * Accessibility props. + */ + accessible?: ?boolean, + accessibilityActions?: ?$ReadOnlyArray, + onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, + accessibilityState?: ?AccessibilityState, |}>; /** @@ -210,7 +217,7 @@ type ButtonProps = $ReadOnly<{| [button:examples]. [button:source]: - https://github.com/facebook/react-native/blob/master/Libraries/Components/Button.js + https://github.com/facebook/react-native/blob/HEAD/Libraries/Components/Button.js [button:examples]: https://js.coach/?menu%5Bcollections%5D=React%20Native&page=1&query=button @@ -313,10 +320,6 @@ class Button extends React.Component { render(): React.Node { const { accessibilityLabel, - accessibilityHint, // TODO(OSS Candidate ISS#2710739) - accessibilityRole, // TODO(OSS Candidate ISS#2710739) - accessibilityActions, // TODO(OSS Candidate ISS#2710739) - onAccessibilityAction, // TODO(OSS Candidate ISS#2710739) color, onPress, touchSoundDisabled, @@ -327,15 +330,19 @@ class Button extends React.Component { nextFocusLeft, nextFocusRight, nextFocusUp, - disabled, testID, onFocus, // TODO(OSS Candidate ISS#2710739) onBlur, // TODO(OSS Candidate ISS#2710739) - onKeyDown, - onKeyUp, - validKeysDown, - validKeysUp, + onKeyDown, // TODO(OSS Candidate ISS#2710739) + onKeyUp, // TODO(OSS Candidate ISS#2710739) + validKeysDown, // TODO(OSS Candidate ISS#2710739) + validKeysUp, // TODO(OSS Candidate ISS#2710739) tooltip, + accessible, + accessibilityActions, + accessibilityHint, // TODO(OSS Candidate ISS#2710739) + accessibilityRole, // TODO(OSS Candidate ISS#2710739) + onAccessibilityAction, } = this.props; const buttonStyles = [styles.button]; const textStyles = [styles.text]; @@ -349,12 +356,22 @@ class Button extends React.Component { buttonStyles.push({backgroundColor: color}); } } - const accessibilityState = {}; + + const disabled = + this.props.disabled != null + ? this.props.disabled + : this.props.accessibilityState?.disabled; + + const accessibilityState = + disabled !== this.props.accessibilityState?.disabled + ? {...this.props.accessibilityState, disabled} + : this.props.accessibilityState; + if (disabled) { buttonStyles.push(styles.buttonDisabled); textStyles.push(styles.textDisabled); - accessibilityState.disabled = true; } + invariant( typeof title === 'string', 'The title prop of a Button must be a string', @@ -363,14 +380,16 @@ class Button extends React.Component { Platform.OS === 'android' ? title.toUpperCase() : title; const Touchable = Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity; + return ( ; /** @@ -149,7 +153,7 @@ class DatePickerIOS extends React.Component { ref={picker => { this._picker = picker; }} - style={styles.datePickerIOS} + style={getHeight(props.pickerStyle, props.mode)} date={ props.date ? props.date.getTime() @@ -174,16 +178,51 @@ class DatePickerIOS extends React.Component { onChange={this._onChange} onStartShouldSetResponder={() => true} onResponderTerminationRequest={() => false} + pickerStyle={props.pickerStyle} /> ); } } +const inlineHeightForDatePicker = 318.5; +const inlineHeightForTimePicker = 49.5; +const compactHeight = 40; +const spinnerHeight = 216; + const styles = StyleSheet.create({ datePickerIOS: { - height: 216, + height: spinnerHeight, + }, + datePickerIOSCompact: { + height: compactHeight, + }, + datePickerIOSInline: { + height: inlineHeightForDatePicker + inlineHeightForTimePicker * 2, + }, + datePickerIOSInlineDate: { + height: inlineHeightForDatePicker + inlineHeightForTimePicker, + }, + datePickerIOSInlineTime: { + height: inlineHeightForTimePicker, }, }); +function getHeight(pickerStyle, mode) { + if (pickerStyle === 'compact') { + return styles.datePickerIOSCompact; + } + if (pickerStyle === 'inline') { + switch (mode) { + case 'date': + return styles.datePickerIOSInlineDate; + case 'time': + return styles.datePickerIOSInlineTime; + default: + return styles.datePickerIOSInline; + } + } + return styles.datePickerIOS; +} + module.exports = DatePickerIOS; diff --git a/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js b/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js index 99e5d92c051e17..e577f3ee37b4d9 100644 --- a/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js +++ b/Libraries/Components/DatePicker/RCTDatePickerNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {ViewProps} from '../View/ViewPropTypes'; import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; @@ -39,6 +37,7 @@ type NativeProps = $ReadOnly<{| mode?: WithDefault<'date' | 'time' | 'datetime', 'date'>, onChange?: ?BubblingEventHandler, timeZoneOffsetInMinutes?: ?Float, + pickerStyle?: WithDefault<'compact' | 'spinner' | 'inline', 'spinner'>, |}>; type ComponentType = HostComponent; diff --git a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js b/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js index 4f9358e21a88ef..9f29433e1e1898 100644 --- a/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js +++ b/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {Options, DatePickerOpenAction} from './DatePickerAndroidTypes'; import NativeDatePickerAndroid from './NativeDatePickerAndroid'; diff --git a/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js b/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js index 778befa4ebc84a..c8c157a2f8ecfa 100644 --- a/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js +++ b/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js b/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js index aff340c6f748ab..7efb3491e0e337 100644 --- a/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js +++ b/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; import type { diff --git a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js index 1537250d9b097f..deebd5102e05a3 100644 --- a/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +++ b/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import Platform from '../../Utilities/Platform'; import * as React from 'react'; import StatusBar from '../StatusBar/StatusBar'; diff --git a/Libraries/Components/Keyboard/Keyboard.js b/Libraries/Components/Keyboard/Keyboard.js index a9e0a29771ddfd..e204e00b6c3881 100644 --- a/Libraries/Components/Keyboard/Keyboard.js +++ b/Libraries/Components/Keyboard/Keyboard.js @@ -8,24 +8,14 @@ * @flow strict-local */ -'use strict'; - import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter'; import LayoutAnimation from '../../LayoutAnimation/LayoutAnimation'; import dismissKeyboard from '../../Utilities/dismissKeyboard'; +import Platform from '../../Utilities/Platform'; import NativeKeyboardObserver from './NativeKeyboardObserver'; -import invariant from 'invariant'; -const KeyboardEventEmitter: NativeEventEmitter = new NativeEventEmitter( - NativeKeyboardObserver, -); - -export type KeyboardEventName = - | 'keyboardWillShow' - | 'keyboardDidShow' - | 'keyboardWillHide' - | 'keyboardDidHide' - | 'keyboardWillChangeFrame' - | 'keyboardDidChangeFrame'; +import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; + +export type KeyboardEventName = $Keys; export type KeyboardEventEasing = | 'easeIn' @@ -61,11 +51,14 @@ export type IOSKeyboardEvent = $ReadOnly<{| isEventFromThisApp: boolean, |}>; -type KeyboardEventListener = (e: KeyboardEvent) => void; - -// The following object exists for documentation purposes -// Actual work happens in -// https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/NativeEventEmitter.js +type KeyboardEventDefinitions = { + keyboardWillShow: [KeyboardEvent], + keyboardDidShow: [KeyboardEvent], + keyboardWillHide: [KeyboardEvent], + keyboardDidHide: [KeyboardEvent], + keyboardWillChangeFrame: [KeyboardEvent], + keyboardDidChangeFrame: [KeyboardEvent], +}; /** * `Keyboard` module to control keyboard events. @@ -109,7 +102,15 @@ type KeyboardEventListener = (e: KeyboardEvent) => void; *``` */ -const Keyboard = { +class Keyboard { + _emitter: NativeEventEmitter = new NativeEventEmitter( + // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior + // If you want to use the native module on other platforms, please remove this condition and test its behavior + Platform.OS !== 'ios' && Platform.OS !== 'macos' // TODO(macOS GH#774): Also use this parameter on macOS + ? null + : NativeKeyboardObserver, + ); + /** * The `addListener` function connects a JavaScript function to an identified native * keyboard notification event. @@ -133,61 +134,57 @@ const Keyboard = { * * @param {function} callback function to be called when the event fires. */ - addListener(eventName: KeyboardEventName, callback: KeyboardEventListener) { - invariant(false, 'Dummy method used for documentation'); - }, + addListener>( + eventType: K, + listener: (...$ElementType) => mixed, + context?: mixed, + ): EventSubscription { + return this._emitter.addListener(eventType, listener); + } /** - * Removes a specific listener. - * - * @param {string} eventName The `nativeEvent` is the string that identifies the event you're listening for. - * @param {function} callback function to be called when the event fires. + * @deprecated Use `remove` on the EventSubscription from `addEventListener`. */ - removeListener( - eventName: KeyboardEventName, - callback: KeyboardEventListener, - ) { - invariant(false, 'Dummy method used for documentation'); - }, + removeEventListener>( + eventType: K, + listener: (...$ElementType) => mixed, + ): void { + // NOTE: This will report a deprecation notice via `console.error`. + this._emitter.removeListener(eventType, listener); + } /** * Removes all listeners for a specific event type. * * @param {string} eventType The native event string listeners are watching which will be removed. */ - removeAllListeners(eventName: KeyboardEventName) { - invariant(false, 'Dummy method used for documentation'); - }, + removeAllListeners>(eventType: ?K): void { + this._emitter.removeAllListeners(eventType); + } /** * Dismisses the active keyboard and removes focus. */ - dismiss() { - invariant(false, 'Dummy method used for documentation'); - }, + dismiss(): void { + dismissKeyboard(); + } /** * Useful for syncing TextInput (or other keyboard accessory view) size of * position changes with keyboard movements. */ - scheduleLayoutAnimation(event: KeyboardEvent) { - invariant(false, 'Dummy method used for documentation'); - }, -}; - -// Throw away the dummy object and reassign it to original module -KeyboardEventEmitter.dismiss = dismissKeyboard; -KeyboardEventEmitter.scheduleLayoutAnimation = function(event: KeyboardEvent) { - const {duration, easing} = event; - if (duration != null && duration !== 0) { - LayoutAnimation.configureNext({ - duration: duration, - update: { + scheduleLayoutAnimation(event: KeyboardEvent): void { + const {duration, easing} = event; + if (duration != null && duration !== 0) { + LayoutAnimation.configureNext({ duration: duration, - type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard', - }, - }); + update: { + duration: duration, + type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard', + }, + }); + } } -}; +} -module.exports = KeyboardEventEmitter; +module.exports = (new Keyboard(): Keyboard); diff --git a/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/Libraries/Components/Keyboard/KeyboardAvoidingView.js index 4e87a3f16c8d76..26897f1632da1e 100644 --- a/Libraries/Components/Keyboard/KeyboardAvoidingView.js +++ b/Libraries/Components/Keyboard/KeyboardAvoidingView.js @@ -5,17 +5,15 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ -'use strict'; - -const Keyboard = require('./Keyboard'); -const LayoutAnimation = require('../../LayoutAnimation/LayoutAnimation'); -const Platform = require('../../Utilities/Platform'); -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const View = require('../View/View'); +import Keyboard from './Keyboard'; +import LayoutAnimation from '../../LayoutAnimation/LayoutAnimation'; +import Platform from '../../Utilities/Platform'; +import * as React from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; import {type EventSubscription} from '../../vendor/emitter/EventEmitter'; @@ -43,13 +41,13 @@ type Props = $ReadOnly<{| * Controls whether this `KeyboardAvoidingView` instance should take effect. * This is useful when more than one is on the screen. Defaults to true. */ - enabled: ?boolean, + enabled?: ?boolean, /** * Distance between the top of the user screen and the React Native view. This * may be non-zero in some cases. Defaults to 0. */ - keyboardVerticalOffset: number, + keyboardVerticalOffset?: number, |}>; type State = {| @@ -61,15 +59,10 @@ type State = {| * adjusting its height, position, or bottom padding. */ class KeyboardAvoidingView extends React.Component { - static defaultProps: {|enabled: boolean, keyboardVerticalOffset: number|} = { - enabled: true, - keyboardVerticalOffset: 0, - }; - _frame: ?ViewLayout = null; _keyboardEvent: ?KeyboardEvent = null; _subscriptions: Array = []; - viewRef: {current: React.ElementRef | null, ...}; + viewRef: {current: React.ElementRef | null, ...}; _initialFrameHeight: number = 0; constructor(props: Props) { @@ -84,7 +77,8 @@ class KeyboardAvoidingView extends React.Component { return 0; } - const keyboardY = keyboardFrame.screenY - this.props.keyboardVerticalOffset; + const keyboardY = + keyboardFrame.screenY - (this.props.keyboardVerticalOffset ?? 0); // Calculate the displacement needed for the view such that it // no longer overlaps with the keyboard @@ -97,13 +91,16 @@ class KeyboardAvoidingView extends React.Component { }; _onLayout = (event: ViewLayoutEvent) => { + const wasFrameNull = this._frame == null; this._frame = event.nativeEvent.layout; if (!this._initialFrameHeight) { // save the initial frame height, before the keyboard is visible this._initialFrameHeight = this._frame.height; } - this._updateBottomIfNecesarry(); + if (wasFrameNull) { + this._updateBottomIfNecesarry(); + } }; _updateBottomIfNecesarry = () => { @@ -156,12 +153,13 @@ class KeyboardAvoidingView extends React.Component { behavior, children, contentContainerStyle, - enabled, - keyboardVerticalOffset, + enabled = true, + // eslint-disable-next-line no-unused-vars + keyboardVerticalOffset = 0, style, ...props } = this.props; - const bottomHeight = enabled ? this.state.bottom : 0; + const bottomHeight = enabled === true ? this.state.bottom : 0; switch (behavior) { case 'height': let heightStyle; @@ -226,4 +224,4 @@ class KeyboardAvoidingView extends React.Component { } } -module.exports = KeyboardAvoidingView; +export default KeyboardAvoidingView; diff --git a/Libraries/Components/Keyboard/NativeKeyboardObserver.js b/Libraries/Components/Keyboard/NativeKeyboardObserver.js index 7f077c3c88baa8..7868dd9fb0941a 100644 --- a/Libraries/Components/Keyboard/NativeKeyboardObserver.js +++ b/Libraries/Components/Keyboard/NativeKeyboardObserver.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {TurboModule} from '../../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry'; diff --git a/Libraries/Components/Keyboard/__tests__/Keyboard-test.js b/Libraries/Components/Keyboard/__tests__/Keyboard-test.js index 639cdd0db5f4f0..2c7befec418355 100644 --- a/Libraries/Components/Keyboard/__tests__/Keyboard-test.js +++ b/Libraries/Components/Keyboard/__tests__/Keyboard-test.js @@ -9,41 +9,27 @@ * @emails oncall+react_native */ -'use strict'; - -const NativeModules = require('../../../BatchedBridge/NativeModules'); const LayoutAnimation = require('../../../LayoutAnimation/LayoutAnimation'); const dismissKeyboard = require('../../../Utilities/dismissKeyboard'); const Keyboard = require('../Keyboard'); -import NativeEventEmitter from '../../../EventEmitter/NativeEventEmitter'; - jest.mock('../../../LayoutAnimation/LayoutAnimation'); +jest.mock('../../../Utilities/dismissKeyboard'); describe('Keyboard', () => { beforeEach(() => { jest.resetAllMocks(); }); - it('exposes KeyboardEventEmitter methods', () => { - const KeyboardObserver = NativeModules.KeyboardObserver; - const KeyboardEventEmitter = new NativeEventEmitter(KeyboardObserver); - - // $FlowFixMe - expect(Keyboard._subscriber).toBe(KeyboardEventEmitter._subscriber); - // $FlowFixMe Cannot access private property - expect(Keyboard._nativeModule).toBe(KeyboardEventEmitter._nativeModule); - }); - it('uses dismissKeyboard utility', () => { - expect(Keyboard.dismiss).toBe(dismissKeyboard); + Keyboard.dismiss(); + expect(dismissKeyboard).toHaveBeenCalled(); }); describe('scheduling layout animation', () => { - const scheduleLayoutAnimation = ( - duration: number | null, - easing: string | null, - ): void => Keyboard.scheduleLayoutAnimation({duration, easing}); + const scheduleLayoutAnimation = (duration, easing): void => + // $FlowFixMe[incompatible-call] + Keyboard.scheduleLayoutAnimation({duration, easing}); it('triggers layout animation', () => { scheduleLayoutAnimation(12, 'spring'); diff --git a/Libraries/Components/MaskedView/MaskedViewIOS.ios.js b/Libraries/Components/MaskedView/MaskedViewIOS.ios.js index 4a32d29836f8d0..eb69fc4233affc 100644 --- a/Libraries/Components/MaskedView/MaskedViewIOS.ios.js +++ b/Libraries/Components/MaskedView/MaskedViewIOS.ios.js @@ -8,9 +8,9 @@ * @flow */ -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const View = require('../View/View'); +import * as React from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; import type {ViewProps} from '../View/ViewPropTypes'; import RCTMaskedViewNativeComponent from './RCTMaskedViewNativeComponent'; diff --git a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js b/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js deleted file mode 100644 index d01757865909fc..00000000000000 --- a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -'use strict'; - -import * as React from 'react'; - -import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import AndroidDialogPickerViewConfig from './AndroidDialogPickerViewConfig'; - -import type { - DirectEventHandler, - Int32, - WithDefault, -} from '../../Types/CodegenTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import type {ViewProps} from '../../Components/View/ViewPropTypes'; - -type PickerItem = $ReadOnly<{| - label: string, - color?: ?ProcessedColorValue, -|}>; - -type PickerItemSelectEvent = $ReadOnly<{| - position: Int32, -|}>; - -type NativeProps = $ReadOnly<{| - ...ViewProps, - style?: ?TextStyleProp, - - // Props - color?: ?ColorValue, - backgroundColor?: ?ColorValue, - enabled?: WithDefault, - items: $ReadOnlyArray, - prompt?: WithDefault, - selected: Int32, - - // Events - onSelect?: DirectEventHandler, -|}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +setNativeSelectedPosition: ( - viewRef: React.ElementRef, - index: number, - ) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['setNativeSelectedPosition'], -}); - -let AndroidDialogPickerNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'AndroidDialogPicker', - AndroidDialogPickerViewConfig, - ); - AndroidDialogPickerNativeComponent = 'AndroidDialogPicker'; -} else { - AndroidDialogPickerNativeComponent = requireNativeComponent( - 'AndroidDialogPicker', - ); -} - -export default ((AndroidDialogPickerNativeComponent: any): NativeType); diff --git a/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js b/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js deleted file mode 100644 index 1108b8105e37e1..00000000000000 --- a/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type {GeneratedViewConfig} from '../../Utilities/registerGeneratedViewConfig'; - -const AndroidDialogPickerViewConfig = { - uiViewClassName: 'AndroidDialogPicker', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: { - color: {process: require('../../StyleSheet/processColor')}, - backgroundColor: {process: require('../../StyleSheet/processColor')}, - enabled: true, - items: true, - prompt: true, - selected: true, - onSelect: true, - }, -}; - -module.exports = (AndroidDialogPickerViewConfig: GeneratedViewConfig); diff --git a/Libraries/Components/Picker/AndroidDropdownPickerNativeComponent.js b/Libraries/Components/Picker/AndroidDropdownPickerNativeComponent.js deleted file mode 100644 index f6ddb741888247..00000000000000 --- a/Libraries/Components/Picker/AndroidDropdownPickerNativeComponent.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import * as React from 'react'; - -import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; - -import type { - DirectEventHandler, - Int32, - WithDefault, -} from '../../Types/CodegenTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import type {ViewProps} from '../../Components/View/ViewPropTypes'; - -type PickerItem = $ReadOnly<{| - label: string, - color?: ?ProcessedColorValue, -|}>; - -type PickerItemSelectEvent = $ReadOnly<{| - position: Int32, -|}>; - -type NativeProps = $ReadOnly<{| - ...ViewProps, - style?: ?TextStyleProp, - - // Props - color?: ?ColorValue, - backgroundColor?: ?ColorValue, - enabled?: WithDefault, - items: $ReadOnlyArray, - prompt?: WithDefault, - selected: Int32, - - // Events - onSelect?: DirectEventHandler, -|}>; - -type NativeType = HostComponent; - -interface NativeCommands { - +setNativeSelectedPosition: ( - viewRef: React.ElementRef, - index: number, - ) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['setNativeSelectedPosition'], -}); - -export default (requireNativeComponent( - 'AndroidDropdownPicker', -): NativeType); diff --git a/Libraries/Components/Picker/Picker.js b/Libraries/Components/Picker/Picker.js deleted file mode 100644 index 01e5ae3664862d..00000000000000 --- a/Libraries/Components/Picker/Picker.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -'use strict'; - -const PickerAndroid = require('./PickerAndroid'); -const PickerIOS = require('./PickerIOS'); -const Platform = require('../../Utilities/Platform'); -const React = require('react'); -const UnimplementedView = require('../UnimplementedViews/UnimplementedView'); - -import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; - -const MODE_DIALOG = 'dialog'; -const MODE_DROPDOWN = 'dropdown'; - -type PickerItemProps = $ReadOnly<{| - /** - * Text to display for this item. - */ - label: string, - - /** - * The value to be passed to picker's `onValueChange` callback when - * this item is selected. - */ - value?: ?string, - - /** - * Color of this item's text. - * @platform android - */ - color?: ColorValue, - - /** - * Used to locate the item in end-to-end tests. - */ - testID?: string, -|}>; - -/** - * Individual selectable item in a Picker. - */ -export type {PickerItem}; -class PickerItem extends React.Component { - render() { - // The items are not rendered directly - throw null; - } -} - -type PickerProps = $ReadOnly<{| - children?: React.Node, - style?: ?TextStyleProp, - - /** - * Value matching value of one of the items. - */ - selectedValue?: ?string, - - /** - * Callback for when an item is selected. This is called with the following parameters: - * - `itemValue`: the `value` prop of the item that was selected - * - `itemIndex`: the index of the selected item in this picker - */ - onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed, - - /** - * If set to false, the picker will be disabled, i.e. the user will not be able to make a - * selection. - * @platform android - */ - enabled?: ?boolean, - - /** - * On Android, specifies how to display the selection items when the user taps on the picker: - * - * - 'dialog': Show a modal dialog. This is the default. - * - 'dropdown': Shows a dropdown anchored to the picker view - * - * @platform android - */ - mode?: ?('dialog' | 'dropdown'), - - /** - * Style to apply to each of the item labels. - * @platform ios - */ - itemStyle?: ?TextStyleProp, - - /** - * Color of the item background. - * @platform android - */ - backgroundColor?: ColorValue, - - /** - * Prompt string for this picker, used on Android in dialog mode as the title of the dialog. - * @platform android - */ - prompt?: ?string, - - /** - * Used to locate this view in end-to-end tests. - */ - testID?: ?string, - /** - * The string used for the accessibility label. Will be read once focused on the picker but not on change. - */ - accessibilityLabel?: ?string, -|}>; - -/** - * Renders the native picker component on iOS and Android. Example: - * - * this.setState({language: itemValue})}> - * - * - * - */ -class Picker extends React.Component { - /** - * On Android, display the options in a dialog. - */ - static MODE_DIALOG: $TEMPORARY$string<'dialog'> = MODE_DIALOG; - - /** - * On Android, display the options in a dropdown (this is the default). - */ - static MODE_DROPDOWN: $TEMPORARY$string<'dropdown'> = MODE_DROPDOWN; - - static Item: typeof PickerItem = PickerItem; - - static defaultProps: {|mode: $TEMPORARY$string<'dialog'>|} = { - mode: MODE_DIALOG, - }; - - render(): React.Node { - if ( - Platform.OS === 'ios' || - Platform.OS === 'macos' /* TODO(macOS GH#774) */ - ) { - /* $FlowFixMe(>=0.81.0 site=react_native_ios_fb) This suppression was - * added when renaming suppression sites. */ - return {this.props.children}; - } else if (Platform.OS === 'android') { - return ( - /* $FlowFixMe(>=0.81.0 site=react_native_android_fb) This suppression - * was added when renaming suppression sites. */ - {this.props.children} - ); - } else { - return ; - } - } -} - -module.exports = Picker; diff --git a/Libraries/Components/Picker/PickerAndroid.android.js b/Libraries/Components/Picker/PickerAndroid.android.js deleted file mode 100644 index ccefd18833d214..00000000000000 --- a/Libraries/Components/Picker/PickerAndroid.android.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import AndroidDropdownPickerNativeComponent, { - Commands as AndroidDropdownPickerCommands, -} from './AndroidDropdownPickerNativeComponent'; -import AndroidDialogPickerNativeComponent, { - Commands as AndroidDialogPickerCommands, -} from './AndroidDialogPickerNativeComponent'; -import * as React from 'react'; -import StyleSheet from '../../StyleSheet/StyleSheet'; -import invariant from 'invariant'; -import processColor from '../../StyleSheet/processColor'; - -import type {SyntheticEvent} from '../../Types/CoreEventTypes'; -import type {ColorValue, TextStyleProp} from '../../StyleSheet/StyleSheet'; - -type PickerItemSelectSyntheticEvent = SyntheticEvent< - $ReadOnly<{| - position: number, - |}>, ->; - -type PickerItemValue = number | string; - -type Props = $ReadOnly<{| - accessibilityLabel?: ?Stringish, - children?: React.Node, - style?: ?TextStyleProp, - backgroundColor?: ?ColorValue, - selectedValue?: ?PickerItemValue, - enabled?: ?boolean, - mode?: ?('dialog' | 'dropdown'), - onValueChange?: ?(itemValue: ?PickerItemValue, itemIndex: number) => mixed, - prompt?: ?string, - testID?: string, -|}>; - -/** - * Not exposed as a public API - use instead. - */ -function PickerAndroid(props: Props): React.Node { - const pickerRef = React.useRef(null); - - const [items, selected] = React.useMemo(() => { - // eslint-disable-next-line no-shadow - let selected = 0; - // eslint-disable-next-line no-shadow - const items = React.Children.map(props.children, (child, index) => { - if (child === null) { - return null; - } - if (child.props.value === props.selectedValue) { - selected = index; - } - const {color, label} = child.props; - const processedColor = processColor(color); - invariant( - processedColor == null || typeof processedColor === 'number', - 'Unexpected color given for PickerAndroid color prop', - ); - return { - color: color == null ? null : processedColor, - label, - }; - }); - return [items, selected]; - }, [props.children, props.selectedValue]); - - const onSelect = React.useCallback( - ({nativeEvent}: PickerItemSelectSyntheticEvent) => { - const {position} = nativeEvent; - const onValueChange = props.onValueChange; - - if (onValueChange != null) { - if (position >= 0) { - const children = React.Children.toArray(props.children).filter( - item => item != null, - ); - const value = children[position].props.value; - if (props.selectedValue !== value) { - onValueChange(value, position); - } - } else { - onValueChange(null, position); - } - } - const {current} = pickerRef; - if (current != null && position !== selected) { - const Commands = - props.mode === 'dropdown' - ? AndroidDropdownPickerCommands - : AndroidDialogPickerCommands; - Commands.setNativeSelectedPosition(current, position); - } - }, - [ - props.children, - props.onValueChange, - props.selectedValue, - props.mode, - selected, - ], - ); - - const rootProps = { - accessibilityLabel: props.accessibilityLabel, - enabled: props.enabled, - items, - onSelect, - prompt: props.prompt, - ref: pickerRef, - selected, - style: StyleSheet.compose(styles.pickerAndroid, props.style), - backgroundColor: props.backgroundColor, - testID: props.testID, - }; - return props.mode === 'dropdown' ? ( - - ) : ( - - ); -} - -const styles = StyleSheet.create({ - pickerAndroid: { - // The picker will conform to whatever width is given, but we do - // have to set the component's height explicitly on the - // surrounding view to ensure it gets rendered. - // TODO would be better to export a native constant for this, - // like in iOS the RCTDatePickerManager.m - height: 50, - }, -}); - -module.exports = PickerAndroid; diff --git a/Libraries/Components/Picker/PickerIOS.ios.js b/Libraries/Components/Picker/PickerIOS.ios.js deleted file mode 100644 index 4b4c50d00b1d2a..00000000000000 --- a/Libraries/Components/Picker/PickerIOS.ios.js +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -// This is a controlled component version of RCTPickerIOS. - -'use strict'; - -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const View = require('../View/View'); -const Platform = require('../../Utilities/Platform'); // TODO(macOS GH#774) - -const invariant = require('invariant'); -const processColor = require('../../StyleSheet/processColor'); - -import RCTPickerNativeComponent, { - Commands as PickerCommands, -} from './RCTPickerNativeComponent'; -import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import type {SyntheticEvent} from '../../Types/CoreEventTypes'; -import type {ViewProps} from '../View/ViewPropTypes'; - -type PickerIOSChangeEvent = SyntheticEvent< - $ReadOnly<{| - newValue: number | string, - newIndex: number, - |}>, ->; - -type RCTPickerIOSItemType = $ReadOnly<{| - label: ?Label, - value: ?string, - textColor: ?ProcessedColorValue, -|}>; - -type Label = Stringish | number; - -type Props = $ReadOnly<{| - ...ViewProps, - children: React.ChildrenArray>, - itemStyle?: ?TextStyleProp, - onChange?: ?(event: PickerIOSChangeEvent) => mixed, - onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed, - selectedValue: ?string, - accessibilityLabel?: ?string, -|}>; - -type State = {| - selectedIndex: number, - items: $ReadOnlyArray, -|}; - -type ItemProps = $ReadOnly<{| - label: ?Label, - value?: ?string, - color?: ?ColorValue, -|}>; - -const PickerIOSItem = (props: ItemProps): null => { - return null; -}; - -class PickerIOS extends React.Component { - _picker: ?React.ElementRef = null; - _lastNativeValue: ?number; - - state: State = { - selectedIndex: 0, - items: [], - }; - - static Item: (props: ItemProps) => null = PickerIOSItem; - - static getDerivedStateFromProps(props: Props): State { - let selectedIndex = 0; - const items = []; - React.Children.toArray(props.children) - .filter(child => child !== null) - .forEach(function(child, index) { - if (child.props.value === props.selectedValue) { - selectedIndex = index; - } - const processedTextColor = processColor(child.props.color); - invariant( - processedTextColor == null || typeof processedTextColor === 'number', - 'Unexpected color given for PickerIOSItem color', - ); - items.push({ - value: child.props.value, - label: child.props.label, - textColor: processedTextColor, - }); - }); - return {selectedIndex, items}; - } - - render(): React.Node { - return ( - - { - this._picker = picker; - }} - testID={this.props.testID} - style={[styles.pickerIOS, this.props.itemStyle]} - items={this.state.items} - selectedIndex={this.state.selectedIndex} - onChange={this._onChange} - accessibilityLabel={this.props.accessibilityLabel} - /> - - ); - } - - componentDidUpdate() { - // This is necessary in case native updates the picker and JS decides - // that the update should be ignored and we should stick with the value - // that we have in JS. - if ( - this._picker && - this._lastNativeValue !== undefined && - this._lastNativeValue !== this.state.selectedIndex - ) { - PickerCommands.setNativeSelectedIndex( - this._picker, - this.state.selectedIndex, - ); - } - } - - _onChange = event => { - if (this.props.onChange) { - this.props.onChange(event); - } - if (this.props.onValueChange) { - this.props.onValueChange( - event.nativeEvent.newValue, - event.nativeEvent.newIndex, - ); - } - - this._lastNativeValue = event.nativeEvent.newIndex; - this.forceUpdate(); - }; -} - -const styles = StyleSheet.create({ - pickerIOS: { - // The picker will conform to whatever width is given, but we do - // have to set the component's height explicitly on the - // surrounding view to ensure it gets rendered. - height: Platform.OS === 'ios' ? 216 : 25, // TODO(macOS GH#774): NSComboBox in Storyboards is 25 points. - }, -}); - -module.exports = PickerIOS; diff --git a/Libraries/Components/Picker/RCTPickerNativeComponent.js b/Libraries/Components/Picker/RCTPickerNativeComponent.js deleted file mode 100644 index 7fdbe9c76c80fd..00000000000000 --- a/Libraries/Components/Picker/RCTPickerNativeComponent.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); -const ReactNativeViewConfigRegistry = require('../../Renderer/shims/ReactNativeViewConfigRegistry'); - -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {SyntheticEvent} from '../../Types/CoreEventTypes'; -import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import RCTPickerViewConfig from './RCTPickerViewConfig'; -import * as React from 'react'; - -type PickerIOSChangeEvent = SyntheticEvent< - $ReadOnly<{| - newValue: number | string, - newIndex: number, - |}>, ->; - -type RCTPickerIOSItemType = $ReadOnly<{| - label: ?Label, - value: ?string, - textColor: ?ProcessedColorValue, -|}>; - -type Label = Stringish | number; - -type NativeProps = $ReadOnly<{| - items: $ReadOnlyArray, - onChange: (event: PickerIOSChangeEvent) => void, - selectedIndex: number, - style?: ?TextStyleProp, - testID?: ?string, - accessibilityLabel?: ?string, -|}>; - -type ComponentType = HostComponent; - -interface NativeCommands { - +setNativeSelectedIndex: ( - viewRef: React.ElementRef, - index: number, - ) => void; -} - -export const Commands: NativeCommands = codegenNativeCommands({ - supportedCommands: ['setNativeSelectedIndex'], -}); - -let RCTPickerNativeComponent; -if (global.RN$Bridgeless) { - ReactNativeViewConfigRegistry.register('RCTPicker', () => { - return RCTPickerViewConfig; - }); - RCTPickerNativeComponent = 'RCTPicker'; -} else { - RCTPickerNativeComponent = requireNativeComponent('RCTPicker'); -} - -// flowlint-next-line unclear-type:off -export default ((RCTPickerNativeComponent: any): HostComponent); diff --git a/Libraries/Components/Picker/RCTPickerViewConfig.js b/Libraries/Components/Picker/RCTPickerViewConfig.js deleted file mode 100644 index 448bc2a2b8e5cf..00000000000000 --- a/Libraries/Components/Picker/RCTPickerViewConfig.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import ReactNativeViewViewConfig from '../../Components/View/ReactNativeViewViewConfig'; -import type {ReactNativeBaseComponentViewConfig} from '../../Renderer/shims/ReactNativeTypes'; - -const RCTPickerViewConfig = { - uiViewClassName: 'RCTPicker', - bubblingEventTypes: { - topChange: { - phasedRegistrationNames: { - bubbled: 'onChange', - captured: 'onChangeCapture', - }, - }, - }, - directEventTypes: {}, - validAttributes: { - ...ReactNativeViewViewConfig.validAttributes, - color: {process: require('../../StyleSheet/processColor')}, - fontFamily: true, - fontSize: true, - fontStyle: true, - fontWeight: true, - items: true, - onChange: true, - selectedIndex: true, - textAlign: true, - }, -}; - -module.exports = (RCTPickerViewConfig: ReactNativeBaseComponentViewConfig<>); diff --git a/Libraries/Components/Picker/__tests__/Picker-test.js b/Libraries/Components/Picker/__tests__/Picker-test.js deleted file mode 100644 index 1a22421c5686c0..00000000000000 --- a/Libraries/Components/Picker/__tests__/Picker-test.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @emails oncall+react_native - * @flow strict-local - */ - -'use strict'; - -const React = require('react'); -const Picker = require('../Picker'); - -const ReactNativeTestTools = require('../../../Utilities/ReactNativeTestTools'); - -describe('', () => { - it('should render as expected', () => { - ReactNativeTestTools.expectRendersMatchingSnapshot( - 'Picker', - () => ( - - - - - ), - () => { - jest.dontMock('../Picker'); - }, - ); - }); -}); diff --git a/Libraries/Components/Picker/__tests__/__snapshots__/Picker-test.js.snap b/Libraries/Components/Picker/__tests__/__snapshots__/Picker-test.js.snap deleted file mode 100644 index 32c40aa992d57a..00000000000000 --- a/Libraries/Components/Picker/__tests__/__snapshots__/Picker-test.js.snap +++ /dev/null @@ -1,97 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` - - - -`; - -exports[` should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` - - - -`; - -exports[` should render as expected: should shallow render as when mocked 1`] = ` - - - - -`; - -exports[` should render as expected: should shallow render as when not mocked 1`] = ` - - - - -`; diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index ec0e2343dfb3ee..59760863a020ee 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import * as React from 'react'; import {useMemo, useState, useRef, useImperativeHandle} from 'react'; import useAndroidRippleForView, { @@ -58,6 +56,12 @@ type Props = $ReadOnly<{| importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, + /** + * Whether a press gesture can be interrupted by a parent gesture such as a + * scroll event. Defaults to true. + */ + cancelable?: ?boolean, + /** * Either children or a render prop that receives a boolean reflecting whether * the component is currently pressed. @@ -98,7 +102,7 @@ type Props = $ReadOnly<{| /** * Called when this view's layout changes. */ - onLayout?: ?(event: LayoutEvent) => void, + onLayout?: ?(event: LayoutEvent) => mixed, /** * Called when the hover is activated to provide visual feedback. @@ -113,22 +117,22 @@ type Props = $ReadOnly<{| /** * Called when a long-tap gesture is detected. */ - onLongPress?: ?(event: PressEvent) => void, + onLongPress?: ?(event: PressEvent) => mixed, /** * Called when a single tap gesture is detected. */ - onPress?: ?(event: PressEvent) => void, + onPress?: ?(event: PressEvent) => mixed, /** * Called when a touch is engaged before `onPress`. */ - onPressIn?: ?(event: PressEvent) => void, + onPressIn?: ?(event: PressEvent) => mixed, /** * Called when a touch is released before `onPress`. */ - onPressOut?: ?(event: PressEvent) => void, + onPressOut?: ?(event: PressEvent) => mixed, /** * Either view styles or a function that receives a boolean reflecting whether @@ -183,6 +187,7 @@ function Pressable(props: Props, forwardedRef): React.Node { accessible, android_disableSound, android_ripple, + cancelable, children, delayHoverIn, delayHoverOut, @@ -211,6 +216,11 @@ function Pressable(props: Props, forwardedRef): React.Node { const hitSlop = normalizeRect(props.hitSlop); + const accessibilityState = + disabled != null + ? {...props.accessibilityState, disabled} + : props.accessibilityState; + const restPropsWithDefaults: React.ElementConfig = { ...restProps, ...android_rippleConfig?.viewProps, @@ -218,11 +228,13 @@ function Pressable(props: Props, forwardedRef): React.Node { enableFocusRing: enableFocusRing !== false && !disabled, accessible: accessible !== false, focusable: focusable !== false && !disabled, // ]TODO(macOS GH#774) + accessibilityState, hitSlop, }; const config = useMemo( () => ({ + cancelable, disabled, hitSlop, pressRectOffset: pressRetentionOffset, @@ -258,6 +270,7 @@ function Pressable(props: Props, forwardedRef): React.Node { [ android_disableSound, android_rippleConfig, + cancelable, delayHoverIn, delayHoverOut, delayLongPress, diff --git a/Libraries/Components/Pressable/__tests__/Pressable-test.js b/Libraries/Components/Pressable/__tests__/Pressable-test.js index a8c5af535e8518..46909623347aa1 100644 --- a/Libraries/Components/Pressable/__tests__/Pressable-test.js +++ b/Libraries/Components/Pressable/__tests__/Pressable-test.js @@ -9,8 +9,6 @@ * @flow strict-local */ -'use strict'; - import * as React from 'react'; import Pressable from '../Pressable'; @@ -32,3 +30,67 @@ describe('', () => { ); }); }); + +describe('', () => { + it('should be disabled when disabled is true', () => { + expectRendersMatchingSnapshot( + 'Pressable', + () => ( + + + + ), + () => { + jest.dontMock('../Pressable'); + }, + ); + }); +}); + +describe('', () => { + it('should be disabled when disabled is true and accessibilityState is empty', () => { + expectRendersMatchingSnapshot( + 'Pressable', + () => ( + + + + ), + () => { + jest.dontMock('../Pressable'); + }, + ); + }); +}); + +describe('', () => { + it('should keep accessibilityState when disabled is true', () => { + expectRendersMatchingSnapshot( + 'Pressable', + () => ( + + + + ), + () => { + jest.dontMock('../Pressable'); + }, + ); + }); +}); + +describe('', () => { + it('should overwrite accessibilityState with value of disabled prop', () => { + expectRendersMatchingSnapshot( + 'Pressable', + () => ( + + + + ), + () => { + jest.dontMock('../Pressable'); + }, + ); + }); +}); diff --git a/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap b/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap index 6f244c492b92fb..c4add53c23e111 100644 --- a/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap +++ b/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap @@ -57,3 +57,315 @@ exports[` should render as expected: should shallow render as `; + +exports[` should be disabled when disabled is true: should deep render when mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true: should deep render when not mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true: should shallow render as when mocked 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true: should shallow render as when not mocked 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true and accessibilityState is empty: should deep render when mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true and accessibilityState is empty: should deep render when not mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true and accessibilityState is empty: should shallow render as when mocked 1`] = ` + + + +`; + +exports[` should be disabled when disabled is true and accessibilityState is empty: should shallow render as when not mocked 1`] = ` + + + +`; + +exports[` should keep accessibilityState when disabled is true: should deep render when mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should keep accessibilityState when disabled is true: should deep render when not mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should keep accessibilityState when disabled is true: should shallow render as when mocked 1`] = ` + + + +`; + +exports[` should keep accessibilityState when disabled is true: should shallow render as when not mocked 1`] = ` + + + +`; + +exports[` should overwrite accessibilityState with value of disabled prop: should deep render when mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should overwrite accessibilityState with value of disabled prop: should deep render when not mocked (please verify output manually) 1`] = ` + + + +`; + +exports[` should overwrite accessibilityState with value of disabled prop: should shallow render as when mocked 1`] = ` + + + +`; + +exports[` should overwrite accessibilityState with value of disabled prop: should shallow render as when not mocked 1`] = ` + + + +`; diff --git a/Libraries/Components/Pressable/useAndroidRippleForView.js b/Libraries/Components/Pressable/useAndroidRippleForView.js index 1e33f2a144c762..18ee3d5c6a4623 100644 --- a/Libraries/Components/Pressable/useAndroidRippleForView.js +++ b/Libraries/Components/Pressable/useAndroidRippleForView.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import invariant from 'invariant'; import {Commands} from '../View/ViewNativeComponent'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; @@ -29,6 +27,7 @@ export type RippleConfig = {| color?: ColorValue, borderless?: boolean, radius?: number, + foreground?: boolean, |}; /** @@ -42,11 +41,11 @@ export default function useAndroidRippleForView( onPressIn: (event: PressEvent) => void, onPressMove: (event: PressEvent) => void, onPressOut: (event: PressEvent) => void, - viewProps: $ReadOnly<{| - nativeBackgroundAndroid: NativeBackgroundProp, - |}>, + viewProps: + | $ReadOnly<{|nativeBackgroundAndroid: NativeBackgroundProp|}> + | $ReadOnly<{|nativeForegroundAndroid: NativeBackgroundProp|}>, |}> { - const {color, borderless, radius} = rippleConfig ?? {}; + const {color, borderless, radius, foreground} = rippleConfig ?? {}; return useMemo(() => { if ( @@ -60,25 +59,27 @@ export default function useAndroidRippleForView( 'Unexpected color given for Ripple color', ); + const nativeRippleValue = { + type: 'RippleAndroid', + color: processedColor, + borderless: borderless === true, + rippleRadius: radius, + }; + return { - viewProps: { - // Consider supporting `nativeForegroundAndroid` - nativeBackgroundAndroid: { - type: 'RippleAndroid', - color: processedColor, - borderless: borderless === true, - rippleRadius: radius, - }, - }, + viewProps: + foreground === true + ? {nativeForegroundAndroid: nativeRippleValue} + : {nativeBackgroundAndroid: nativeRippleValue}, onPressIn(event: PressEvent): void { const view = viewRef.current; if (view != null) { - Commands.setPressed(view, true); Commands.hotspotUpdate( view, event.nativeEvent.locationX ?? 0, event.nativeEvent.locationY ?? 0, ); + Commands.setPressed(view, true); } }, onPressMove(event: PressEvent): void { @@ -100,5 +101,5 @@ export default function useAndroidRippleForView( }; } return null; - }, [color, borderless, radius, viewRef]); + }, [borderless, color, foreground, radius, viewRef]); } diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js index 61663d6ad50b30..51803f1df2e8a6 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - const React = require('react'); import ProgressBarAndroidNativeComponent from './ProgressBarAndroidNativeComponent'; @@ -81,23 +79,27 @@ export type ProgressBarAndroidProps = $ReadOnly<{| * ``` */ const ProgressBarAndroid = ( - props: ProgressBarAndroidProps, + { + styleAttr = 'Normal', + indeterminate = true, + animating = true, + ...restProps + }: ProgressBarAndroidProps, forwardedRef: ?React.Ref, ) => { - return ; + return ( + + ); }; const ProgressBarAndroidToExport = React.forwardRef(ProgressBarAndroid); -/* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an - * error found when Flow v0.89 was deployed. To see the error, delete this - * comment and run Flow. */ -ProgressBarAndroidToExport.defaultProps = { - styleAttr: 'Normal', - indeterminate: true, - animating: true, -}; - /* $FlowFixMe(>=0.89.0 site=react_native_android_fb) This comment suppresses an * error found when Flow v0.89 was deployed. To see the error, delete this * comment and run Flow. */ diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.js index 0274e5866792e0..5b2fb1a222f99f 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidNativeComponent.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {ViewProps} from '../View/ViewPropTypes'; import type {Double, WithDefault} from '../../Types/CodegenTypes'; diff --git a/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap b/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap index 87b8c16da4f277..f1985dfedb660a 100644 --- a/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap +++ b/Libraries/Components/ProgressBarAndroid/__tests__/__snapshots__/ProgressBarAndroid-test.js.snap @@ -18,7 +18,6 @@ exports[` should render as expected: should deep render wh exports[` should render as expected: should shallow render as when mocked 1`] = ` @@ -26,7 +25,6 @@ exports[` should render as expected: should shallow render exports[` should render as expected: should shallow render as when not mocked 1`] = ` diff --git a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.android.js b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.android.js index 8396ac4e87981e..d642a6545ab5bb 100644 --- a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.android.js +++ b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.android.js @@ -8,11 +8,10 @@ */ 'use strict'; - -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); -const Text = require('../../Text/Text'); -const View = require('../View/View'); +import * as React from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import Text from '../../Text/Text'; +import View from '../View/View'; class DummyProgressViewIOS extends React.Component { render() { diff --git a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js index 189f7be3872ee0..d465440d174872 100644 --- a/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js +++ b/Libraries/Components/ProgressViewIOS/ProgressViewIOS.ios.js @@ -8,14 +8,11 @@ * @flow strict-local */ -'use strict'; - -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); +import * as React from 'react'; +import StyleSheet, {type ColorValue} from '../../StyleSheet/StyleSheet'; import RCTProgressViewNativeComponent from './RCTProgressViewNativeComponent'; import type {ImageSource} from '../../Image/ImageSource'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {ViewProps} from '../View/ViewPropTypes'; type Props = $ReadOnly<{| diff --git a/Libraries/Components/ProgressViewIOS/RCTProgressViewNativeComponent.js b/Libraries/Components/ProgressViewIOS/RCTProgressViewNativeComponent.js index ccdd15e5100489..c0c0b56bfef280 100644 --- a/Libraries/Components/ProgressViewIOS/RCTProgressViewNativeComponent.js +++ b/Libraries/Components/ProgressViewIOS/RCTProgressViewNativeComponent.js @@ -8,8 +8,6 @@ * @format */ -'use strict'; - import type {Float, WithDefault} from '../../Types/CodegenTypes'; import type {ImageSource} from '../../Image/ImageSource'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; diff --git a/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js index 9bd3600eb31571..de1b8d9a2a52f1 100644 --- a/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js +++ b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import * as React from 'react'; import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; @@ -41,17 +39,9 @@ type NativeProps = $ReadOnly<{| */ progressBackgroundColor?: ?ColorValue, /** - * Size of the refresh indicator, see RefreshControl.SIZE. - * - * This type isn't currently accurate. It really is specific numbers - * hard coded in the Android platform. - * - * Also, 1 isn't actually a safe default. We are able to set this here - * because native code isn't currently consuming the generated artifact. - * This will end up being - * size?: WithDefault<'default' | 'large', 'default'>, + * Size of the refresh indicator. */ - size?: WithDefault, + size?: WithDefault<'default' | 'large', 'default'>, /** * Progress view top offset */ diff --git a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js index 7f97db35b6120f..fa4791f2ab620c 100644 --- a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js +++ b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js @@ -8,9 +8,11 @@ * @flow strict-local */ -'use strict'; - -import type {DirectEventHandler, WithDefault} from '../../Types/CodegenTypes'; +import type { + DirectEventHandler, + Float, + WithDefault, +} from '../../Types/CodegenTypes'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {ViewProps} from '../View/ViewPropTypes'; import * as React from 'react'; @@ -34,6 +36,10 @@ type NativeProps = $ReadOnly<{| * The title displayed under the refresh indicator. */ title?: WithDefault, + /** + * Progress view top offset + */ + progressViewOffset?: WithDefault, /** * Called when the view starts refreshing. diff --git a/Libraries/Components/RefreshControl/RefreshControl.js b/Libraries/Components/RefreshControl/RefreshControl.js index a85c820791d1e1..0f0a16dbbccfc5 100644 --- a/Libraries/Components/RefreshControl/RefreshControl.js +++ b/Libraries/Components/RefreshControl/RefreshControl.js @@ -8,8 +8,6 @@ * @flow */ -'use strict'; - const Platform = require('../../Utilities/Platform'); const React = require('react'); @@ -22,18 +20,6 @@ import PullToRefreshViewNativeComponent, { Commands as PullToRefreshCommands, } from './PullToRefreshViewNativeComponent'; -let RefreshLayoutConsts: any; -if (Platform.OS === 'android') { - const AndroidSwipeRefreshLayout = require('../../ReactNative/UIManager').getViewManagerConfig( - 'AndroidSwipeRefreshLayout', - ); - RefreshLayoutConsts = AndroidSwipeRefreshLayout - ? AndroidSwipeRefreshLayout.Constants - : {SIZE: {}}; -} else { - RefreshLayoutConsts = {SIZE: {}}; -} - type IOSProps = $ReadOnly<{| /** * The color of the refresh indicator. @@ -63,16 +49,9 @@ type AndroidProps = $ReadOnly<{| */ progressBackgroundColor?: ?ColorValue, /** - * Size of the refresh indicator, see RefreshControl.SIZE. + * Size of the refresh indicator. */ - size?: ?( - | typeof RefreshLayoutConsts.SIZE.DEFAULT - | typeof RefreshLayoutConsts.SIZE.LARGE - ), - /** - * Progress view top offset - */ - progressViewOffset?: ?number, + size?: ?('default' | 'large'), |}>; export type RefreshControlProps = $ReadOnly<{| @@ -89,6 +68,11 @@ export type RefreshControlProps = $ReadOnly<{| * Whether the view should be indicating an active refresh. */ refreshing: boolean, + + /** + * Progress view top offset + */ + progressViewOffset?: ?number, |}>; /** @@ -137,8 +121,6 @@ export type RefreshControlProps = $ReadOnly<{| * in the `onRefresh` function otherwise the refresh indicator will stop immediately. */ class RefreshControl extends React.Component { - static SIZE: any = RefreshLayoutConsts.SIZE; - _nativeRef: ?React.ElementRef< | typeof PullToRefreshViewNativeComponent | typeof AndroidSwipeRefreshLayoutNativeComponent, @@ -181,7 +163,6 @@ class RefreshControl extends React.Component { colors, progressBackgroundColor, size, - progressViewOffset, ...props } = this.props; return ( diff --git a/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js b/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js index 40d41abbdc68ec..696eaa37ae7d2d 100644 --- a/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +++ b/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js @@ -9,10 +9,9 @@ */ 'use strict'; +import * as React from 'react'; -const React = require('react'); - -const requireNativeComponent = require('../../../ReactNative/requireNativeComponent'); +import requireNativeComponent from '../../../ReactNative/requireNativeComponent'; import type {HostComponent} from '../../../Renderer/shims/ReactNativeTypes'; diff --git a/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js b/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js index 9025f1a88195d5..5365e35f8fce53 100644 --- a/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js +++ b/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {ViewProps} from '../View/ViewPropTypes'; import type {WithDefault} from '../../Types/CodegenTypes'; diff --git a/Libraries/Components/SafeAreaView/SafeAreaView.js b/Libraries/Components/SafeAreaView/SafeAreaView.js index 8fc76bed849dc8..827965958439b5 100644 --- a/Libraries/Components/SafeAreaView/SafeAreaView.js +++ b/Libraries/Components/SafeAreaView/SafeAreaView.js @@ -59,4 +59,4 @@ if (Platform.OS !== 'ios') { ); } -module.exports = exported; +export default exported; diff --git a/Libraries/Components/SafeAreaView/__tests__/SafeAreaView-test.js b/Libraries/Components/SafeAreaView/__tests__/SafeAreaView-test.js index 133fd1da8a9f85..4b7edf60fee47e 100644 --- a/Libraries/Components/SafeAreaView/__tests__/SafeAreaView-test.js +++ b/Libraries/Components/SafeAreaView/__tests__/SafeAreaView-test.js @@ -12,7 +12,7 @@ 'use strict'; const React = require('react'); -const SafeAreaView = require('../SafeAreaView'); +import SafeAreaView from '../SafeAreaView'; const ReactNativeTestTools = require('../../../Utilities/ReactNativeTestTools'); const View = require('../../View/View'); const Text = require('../../../Text/Text'); diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js deleted file mode 100644 index 7aef247b62c869..00000000000000 --- a/Libraries/Components/ScrollResponder.js +++ /dev/null @@ -1,772 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -'use strict'; - -const Dimensions = require('../Utilities/Dimensions'); -const FrameRateLogger = require('../Interaction/FrameRateLogger'); -const Keyboard = require('./Keyboard/Keyboard'); -const Platform = require('../Utilities/Platform'); -const React = require('react'); -const ReactNative = require('../Renderer/shims/ReactNative'); -const TextInputState = require('./TextInput/TextInputState'); -const UIManager = require('../ReactNative/UIManager'); - -const invariant = require('invariant'); - -import type {HostComponent} from '../Renderer/shims/ReactNativeTypes'; -import type {PressEvent, ScrollEvent} from '../Types/CoreEventTypes'; -import {type EventSubscription} from '../vendor/emitter/EventEmitter'; -import type {KeyboardEvent} from './Keyboard/Keyboard'; -import typeof ScrollView from './ScrollView/ScrollView'; -import type {Props as ScrollViewProps} from './ScrollView/ScrollView'; -import Commands from './ScrollView/ScrollViewCommands'; - -/** - * Mixin that can be integrated in order to handle scrolling that plays well - * with `ResponderEventPlugin`. Integrate with your platform specific scroll - * views, or even your custom built (every-frame animating) scroll views so that - * all of these systems play well with the `ResponderEventPlugin`. - * - * iOS scroll event timing nuances: - * =============================== - * - * - * Scrolling without bouncing, if you touch down: - * ------------------------------- - * - * 1. `onMomentumScrollBegin` (when animation begins after letting up) - * ... physical touch starts ... - * 2. `onTouchStartCapture` (when you press down to stop the scroll) - * 3. `onTouchStart` (same, but bubble phase) - * 4. `onResponderRelease` (when lifting up - you could pause forever before * lifting) - * 5. `onMomentumScrollEnd` - * - * - * Scrolling with bouncing, if you touch down: - * ------------------------------- - * - * 1. `onMomentumScrollBegin` (when animation begins after letting up) - * ... bounce begins ... - * ... some time elapses ... - * ... physical touch during bounce ... - * 2. `onMomentumScrollEnd` (Makes no sense why this occurs first during bounce) - * 3. `onTouchStartCapture` (immediately after `onMomentumScrollEnd`) - * 4. `onTouchStart` (same, but bubble phase) - * 5. `onTouchEnd` (You could hold the touch start for a long time) - * 6. `onMomentumScrollBegin` (When releasing the view starts bouncing back) - * - * So when we receive an `onTouchStart`, how can we tell if we are touching - * *during* an animation (which then causes the animation to stop)? The only way - * to tell is if the `touchStart` occurred immediately after the - * `onMomentumScrollEnd`. - * - * This is abstracted out for you, so you can just call this.scrollResponderIsAnimating() if - * necessary - * - * `ScrollResponder` also includes logic for blurring a currently focused input - * if one is focused while scrolling. The `ScrollResponder` is a natural place - * to put this logic since it can support not dismissing the keyboard while - * scrolling, unless a recognized "tap"-like gesture has occurred. - * - * The public lifecycle API includes events for keyboard interaction, responder - * interaction, and scrolling (among others). The keyboard callbacks - * `onKeyboardWill/Did/*` are *global* events, but are invoked on scroll - * responder's props so that you can guarantee that the scroll responder's - * internal state has been updated accordingly (and deterministically) by - * the time the props callbacks are invoke. Otherwise, you would always wonder - * if the scroll responder is currently in a state where it recognizes new - * keyboard positions etc. If coordinating scrolling with keyboard movement, - * *always* use these hooks instead of listening to your own global keyboard - * events. - * - * Public keyboard lifecycle API: (props callbacks) - * - * Standard Keyboard Appearance Sequence: - * - * this.props.onKeyboardWillShow - * this.props.onKeyboardDidShow - * - * `onScrollResponderKeyboardDismissed` will be invoked if an appropriate - * tap inside the scroll responder's scrollable region was responsible - * for the dismissal of the keyboard. There are other reasons why the - * keyboard could be dismissed. - * - * this.props.onScrollResponderKeyboardDismissed - * - * Standard Keyboard Hide Sequence: - * - * this.props.onKeyboardWillHide - * this.props.onKeyboardDidHide - */ - -const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16; - -export type State = {| - isTouching: boolean, - lastMomentumScrollBeginTime: number, - lastMomentumScrollEndTime: number, - observedScrollSinceBecomingResponder: boolean, - becameResponderWhileAnimating: boolean, -|}; - -const ScrollResponderMixin = { - _subscriptionKeyboardWillShow: (null: ?EventSubscription), - _subscriptionKeyboardWillHide: (null: ?EventSubscription), - _subscriptionKeyboardDidShow: (null: ?EventSubscription), - _subscriptionKeyboardDidHide: (null: ?EventSubscription), - scrollResponderMixinGetInitialState: function(): State { - return { - isTouching: false, - lastMomentumScrollBeginTime: 0, - lastMomentumScrollEndTime: 0, - - // Reset to false every time becomes responder. This is used to: - // - Determine if the scroll view has been scrolled and therefore should - // refuse to give up its responder lock. - // - Determine if releasing should dismiss the keyboard when we are in - // tap-to-dismiss mode (this.props.keyboardShouldPersistTaps !== 'always'). - observedScrollSinceBecomingResponder: false, - becameResponderWhileAnimating: false, - }; - }, - - /** - * Invoke this from an `onScroll` event. - */ - scrollResponderHandleScrollShouldSetResponder: function(): boolean { - // Allow any event touch pass through if the default pan responder is disabled - if (this.props.disableScrollViewPanResponder === true) { - return false; - } - return this.state.isTouching; - }, - - /** - * Merely touch starting is not sufficient for a scroll view to become the - * responder. Being the "responder" means that the very next touch move/end - * event will result in an action/movement. - * - * Invoke this from an `onStartShouldSetResponder` event. - * - * `onStartShouldSetResponder` is used when the next move/end will trigger - * some UI movement/action, but when you want to yield priority to views - * nested inside of the view. - * - * There may be some cases where scroll views actually should return `true` - * from `onStartShouldSetResponder`: Any time we are detecting a standard tap - * that gives priority to nested views. - * - * - If a single tap on the scroll view triggers an action such as - * recentering a map style view yet wants to give priority to interaction - * views inside (such as dropped pins or labels), then we would return true - * from this method when there is a single touch. - * - * - Similar to the previous case, if a two finger "tap" should trigger a - * zoom, we would check the `touches` count, and if `>= 2`, we would return - * true. - * - */ - scrollResponderHandleStartShouldSetResponder: function( - e: PressEvent, - ): boolean { - // Allow any event touch pass through if the default pan responder is disabled - if (this.props.disableScrollViewPanResponder === true) { - return false; - } - - const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); - - if ( - this.props.keyboardShouldPersistTaps === 'handled' && - currentlyFocusedInput != null && - e.target !== currentlyFocusedInput - ) { - return true; - } - return false; - }, - - /** - * There are times when the scroll view wants to become the responder - * (meaning respond to the next immediate `touchStart/touchEnd`), in a way - * that *doesn't* give priority to nested views (hence the capture phase): - * - * - Currently animating. - * - Tapping anywhere that is not a text input, while the keyboard is - * up (which should dismiss the keyboard). - * - * Invoke this from an `onStartShouldSetResponderCapture` event. - */ - scrollResponderHandleStartShouldSetResponderCapture: function( - e: PressEvent, - ): boolean { - // The scroll view should receive taps instead of its descendants if: - // * it is already animating/decelerating - if (this.scrollResponderIsAnimating()) { - return true; - } - - // Allow any event touch pass through if the default pan responder is disabled - if (this.props.disableScrollViewPanResponder === true) { - return false; - } - - // * the keyboard is up, keyboardShouldPersistTaps is 'never' (the default), - // and a new touch starts with a non-textinput target (in which case the - // first tap should be sent to the scroll view and dismiss the keyboard, - // then the second tap goes to the actual interior view) - const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); - const {keyboardShouldPersistTaps} = this.props; - const keyboardNeverPersistTaps = - !keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never'; - - if (typeof e.target === 'number') { - if (__DEV__) { - console.error( - 'Did not expect event target to be a number. Should have been a native component', - ); - } - - return false; - } - - if ( - keyboardNeverPersistTaps && - currentlyFocusedTextInput != null && - e.target != null && - !TextInputState.isTextInput(e.target) - ) { - return true; - } - - return false; - }, - - /** - * Invoke this from an `onResponderReject` event. - * - * Some other element is not yielding its role as responder. Normally, we'd - * just disable the `UIScrollView`, but a touch has already began on it, the - * `UIScrollView` will not accept being disabled after that. The easiest - * solution for now is to accept the limitation of disallowing this - * altogether. To improve this, find a way to disable the `UIScrollView` after - * a touch has already started. - */ - scrollResponderHandleResponderReject: function() {}, - - /** - * We will allow the scroll view to give up its lock iff it acquired the lock - * during an animation. This is a very useful default that happens to satisfy - * many common user experiences. - * - * - Stop a scroll on the left edge, then turn that into an outer view's - * backswipe. - * - Stop a scroll mid-bounce at the top, continue pulling to have the outer - * view dismiss. - * - However, without catching the scroll view mid-bounce (while it is - * motionless), if you drag far enough for the scroll view to become - * responder (and therefore drag the scroll view a bit), any backswipe - * navigation of a swipe gesture higher in the view hierarchy, should be - * rejected. - */ - scrollResponderHandleTerminationRequest: function(): boolean { - return !this.state.observedScrollSinceBecomingResponder; - }, - - /** - * Invoke this from an `onTouchEnd` event. - * - * @param {PressEvent} e Event. - */ - scrollResponderHandleTouchEnd: function(e: PressEvent) { - const nativeEvent = e.nativeEvent; - this.state.isTouching = nativeEvent.touches.length !== 0; - this.props.onTouchEnd && this.props.onTouchEnd(e); - }, - - /** - * Invoke this from an `onTouchCancel` event. - * - * @param {PressEvent} e Event. - */ - scrollResponderHandleTouchCancel: function(e: PressEvent) { - this.state.isTouching = false; - this.props.onTouchCancel && this.props.onTouchCancel(e); - }, - - /** - * Invoke this from an `onResponderRelease` event. - */ - scrollResponderHandleResponderRelease: function(e: PressEvent) { - this.props.onResponderRelease && this.props.onResponderRelease(e); - - if (typeof e.target === 'number') { - if (__DEV__) { - console.error( - 'Did not expect event target to be a number. Should have been a native component', - ); - } - - return; - } - - // By default scroll views will unfocus a textField - // if another touch occurs outside of it - const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); - if ( - this.props.keyboardShouldPersistTaps !== true && - this.props.keyboardShouldPersistTaps !== 'always' && - currentlyFocusedTextInput != null && - e.target !== currentlyFocusedTextInput && - !this.state.observedScrollSinceBecomingResponder && - !this.state.becameResponderWhileAnimating - ) { - this.props.onScrollResponderKeyboardDismissed && - this.props.onScrollResponderKeyboardDismissed(e); - TextInputState.blurTextInput(currentlyFocusedTextInput); - } - }, - - scrollResponderHandleScroll: function(e: ScrollEvent) { - (this: any).state.observedScrollSinceBecomingResponder = true; - (this: any).props.onScroll && (this: any).props.onScroll(e); - }, - - /** - * Invoke this from an `onResponderGrant` event. - */ - scrollResponderHandleResponderGrant: function(e: ScrollEvent) { - this.state.observedScrollSinceBecomingResponder = false; - this.props.onResponderGrant && this.props.onResponderGrant(e); - this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating(); - }, - - /** - * Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll - * animation, and there's not an easy way to distinguish a drag vs. stopping - * momentum. - * - * Invoke this from an `onScrollBeginDrag` event. - */ - scrollResponderHandleScrollBeginDrag: function(e: ScrollEvent) { - FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation - this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); - }, - - /** - * Invoke this from an `onScrollEndDrag` event. - */ - scrollResponderHandleScrollEndDrag: function(e: ScrollEvent) { - const {velocity} = e.nativeEvent; - // - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end - // will fire. - // - If velocity is non-zero, then the interaction will stop when momentum scroll ends or - // another drag starts and ends. - // - If we don't get velocity, better to stop the interaction twice than not stop it. - if ( - !this.scrollResponderIsAnimating() && - (!velocity || (velocity.x === 0 && velocity.y === 0)) - ) { - FrameRateLogger.endScroll(); - } - this.props.onScrollEndDrag && this.props.onScrollEndDrag(e); - }, - - /** - * Invoke this from an `onMomentumScrollBegin` event. - */ - scrollResponderHandleMomentumScrollBegin: function(e: ScrollEvent) { - this.state.lastMomentumScrollBeginTime = global.performance.now(); - this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); - }, - - /** - * Invoke this from an `onMomentumScrollEnd` event. - */ - scrollResponderHandleMomentumScrollEnd: function(e: ScrollEvent) { - FrameRateLogger.endScroll(); - this.state.lastMomentumScrollEndTime = global.performance.now(); - this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); - }, - - /** - * Invoke this from an `onTouchStart` event. - * - * Since we know that the `SimpleEventPlugin` occurs later in the plugin - * order, after `ResponderEventPlugin`, we can detect that we were *not* - * permitted to be the responder (presumably because a contained view became - * responder). The `onResponderReject` won't fire in that case - it only - * fires when a *current* responder rejects our request. - * - * @param {PressEvent} e Touch Start event. - */ - scrollResponderHandleTouchStart: function(e: PressEvent) { - this.state.isTouching = true; - this.props.onTouchStart && this.props.onTouchStart(e); - }, - - /** - * Invoke this from an `onTouchMove` event. - * - * Since we know that the `SimpleEventPlugin` occurs later in the plugin - * order, after `ResponderEventPlugin`, we can detect that we were *not* - * permitted to be the responder (presumably because a contained view became - * responder). The `onResponderReject` won't fire in that case - it only - * fires when a *current* responder rejects our request. - * - * @param {PressEvent} e Touch Start event. - */ - scrollResponderHandleTouchMove: function(e: PressEvent) { - this.props.onTouchMove && this.props.onTouchMove(e); - }, - - /** - * A helper function for this class that lets us quickly determine if the - * view is currently animating. This is particularly useful to know when - * a touch has just started or ended. - */ - scrollResponderIsAnimating: function(): boolean { - const now = global.performance.now(); - const timeSinceLastMomentumScrollEnd = - now - this.state.lastMomentumScrollEndTime; - const isAnimating = - timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS || - this.state.lastMomentumScrollEndTime < - this.state.lastMomentumScrollBeginTime; - return isAnimating; - }, - - /** - * Returns the node that represents native view that can be scrolled. - * Components can pass what node to use by defining a `getScrollableNode` - * function otherwise `this` is used. - */ - scrollResponderGetScrollableNode: function(): ?number { - return this.getScrollableNode - ? this.getScrollableNode() - : ReactNative.findNodeHandle(this); - }, - - /** - * A helper function to scroll to a specific point in the ScrollView. - * This is currently used to help focus child TextViews, but can also - * be used to quickly scroll to any element we want to focus. Syntax: - * - * `scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})` - * - * Note: The weird argument signature is due to the fact that, for historical reasons, - * the function also accepts separate arguments as as alternative to the options object. - * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED. - */ - scrollResponderScrollTo: function( - x?: - | number - | { - x?: number, - y?: number, - animated?: boolean, - ... - }, - y?: number, - animated?: boolean, - ) { - if (typeof x === 'number') { - console.warn( - '`scrollResponderScrollTo(x, y, animated)` is deprecated. Use `scrollResponderScrollTo({x: 5, y: 5, animated: true})` instead.', - ); - } else { - ({x, y, animated} = x || {}); - } - - const that: React.ElementRef = (this: any); - invariant( - that.getNativeScrollRef != null, - 'Expected scrollTo to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native', - ); - const nativeScrollRef = that.getNativeScrollRef(); - if (nativeScrollRef == null) { - return; - } - Commands.scrollTo(nativeScrollRef, x || 0, y || 0, animated !== false); - }, - - /** - * Scrolls to the end of the ScrollView, either immediately or with a smooth - * animation. - * - * Example: - * - * `scrollResponderScrollToEnd({animated: true})` - */ - scrollResponderScrollToEnd: function(options?: {animated?: boolean, ...}) { - // Default to true - const animated = (options && options.animated) !== false; - - const that: React.ElementRef = (this: any); - invariant( - that.getNativeScrollRef != null, - 'Expected scrollToEnd to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native', - ); - const nativeScrollRef = that.getNativeScrollRef(); - if (nativeScrollRef == null) { - return; - } - - Commands.scrollToEnd(nativeScrollRef, animated); - }, - - /** - * A helper function to zoom to a specific rect in the scrollview. The argument has the shape - * {x: number; y: number; width: number; height: number; animated: boolean = true} - * - * @platform ios - */ - scrollResponderZoomTo: function( - rect: {| - x: number, - y: number, - width: number, - height: number, - animated?: boolean, - |}, - animated?: boolean, // deprecated, put this inside the rect argument instead - ) { - invariant(Platform.OS === 'ios', 'zoomToRect is not implemented'); - if ('animated' in rect) { - animated = rect.animated; - delete rect.animated; - } else if (typeof animated !== 'undefined') { - console.warn( - '`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead', - ); - } - - const that: React.ElementRef = this; - invariant( - that.getNativeScrollRef != null, - 'Expected zoomToRect to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native', - ); - const nativeScrollRef = that.getNativeScrollRef(); - if (nativeScrollRef == null) { - return; - } - Commands.zoomToRect(nativeScrollRef, rect, animated !== false); - }, - - /** - * Displays the scroll indicators momentarily. - */ - scrollResponderFlashScrollIndicators: function() { - const that: React.ElementRef = (this: any); - invariant( - that.getNativeScrollRef != null, - 'Expected flashScrollIndicators to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native', - ); - const nativeScrollRef = that.getNativeScrollRef(); - if (nativeScrollRef == null) { - return; - } - Commands.flashScrollIndicators(nativeScrollRef); - }, - - /** - * This method should be used as the callback to onFocus in a TextInputs' - * parent view. Note that any module using this mixin needs to return - * the parent view's ref in getScrollViewRef() in order to use this method. - * @param {number} nodeHandle The TextInput node handle - * @param {number} additionalOffset The scroll view's bottom "contentInset". - * Default is 0. - * @param {bool} preventNegativeScrolling Whether to allow pulling the content - * down to make it meet the keyboard's top. Default is false. - */ - scrollResponderScrollNativeHandleToKeyboard: function( - nodeHandle: number | React.ElementRef>, - additionalOffset?: number, - preventNegativeScrollOffset?: boolean, - ) { - this.additionalScrollOffset = additionalOffset || 0; - this.preventNegativeScrollOffset = !!preventNegativeScrollOffset; - - if (typeof nodeHandle === 'number') { - UIManager.measureLayout( - nodeHandle, - ReactNative.findNodeHandle(this.getInnerViewNode()), - this.scrollResponderTextInputFocusError, - this.scrollResponderInputMeasureAndScrollToKeyboard, - ); - } else { - const innerRef = this.getInnerViewRef(); - - if (innerRef == null) { - return; - } - - nodeHandle.measureLayout( - innerRef, - this.scrollResponderInputMeasureAndScrollToKeyboard, - this.scrollResponderTextInputFocusError, - ); - } - }, - - /** - * The calculations performed here assume the scroll view takes up the entire - * screen - even if has some content inset. We then measure the offsets of the - * keyboard, and compensate both for the scroll view's "contentInset". - * - * @param {number} left Position of input w.r.t. table view. - * @param {number} top Position of input w.r.t. table view. - * @param {number} width Width of the text input. - * @param {number} height Height of the text input. - */ - scrollResponderInputMeasureAndScrollToKeyboard: function( - left: number, - top: number, - width: number, - height: number, - ) { - let keyboardScreenY = Dimensions.get('window').height; - if (this.keyboardWillOpenTo) { - keyboardScreenY = this.keyboardWillOpenTo.endCoordinates.screenY; - } - let scrollOffsetY = - top - keyboardScreenY + height + this.additionalScrollOffset; - - // By default, this can scroll with negative offset, pulling the content - // down so that the target component's bottom meets the keyboard's top. - // If requested otherwise, cap the offset at 0 minimum to avoid content - // shifting down. - if (this.preventNegativeScrollOffset) { - scrollOffsetY = Math.max(0, scrollOffsetY); - } - this.scrollResponderScrollTo({x: 0, y: scrollOffsetY, animated: true}); - - this.additionalOffset = 0; - this.preventNegativeScrollOffset = false; - }, - - scrollResponderTextInputFocusError: function(msg: string) { - console.error('Error measuring text field: ', msg); - }, - - /** - * `componentWillMount` is the closest thing to a standard "constructor" for - * React components. - * - * The `keyboardWillShow` is called before input focus. - */ - UNSAFE_componentWillMount: function() { - const {keyboardShouldPersistTaps} = ((this: any).props: ScrollViewProps); - if (typeof keyboardShouldPersistTaps === 'boolean') { - console.warn( - `'keyboardShouldPersistTaps={${ - keyboardShouldPersistTaps === true ? 'true' : 'false' - }}' is deprecated. ` + - `Use 'keyboardShouldPersistTaps="${ - keyboardShouldPersistTaps ? 'always' : 'never' - }"' instead`, - ); - } - - (this: any).keyboardWillOpenTo = null; - (this: any).additionalScrollOffset = 0; - this._subscriptionKeyboardWillShow = Keyboard.addListener( - 'keyboardWillShow', - this.scrollResponderKeyboardWillShow, - ); - - this._subscriptionKeyboardWillHide = Keyboard.addListener( - 'keyboardWillHide', - this.scrollResponderKeyboardWillHide, - ); - this._subscriptionKeyboardDidShow = Keyboard.addListener( - 'keyboardDidShow', - this.scrollResponderKeyboardDidShow, - ); - this._subscriptionKeyboardDidHide = Keyboard.addListener( - 'keyboardDidHide', - this.scrollResponderKeyboardDidHide, - ); - }, - - componentWillUnmount: function() { - if (this._subscriptionKeyboardWillShow != null) { - this._subscriptionKeyboardWillShow.remove(); - } - if (this._subscriptionKeyboardWillHide != null) { - this._subscriptionKeyboardWillHide.remove(); - } - if (this._subscriptionKeyboardDidShow != null) { - this._subscriptionKeyboardDidShow.remove(); - } - if (this._subscriptionKeyboardDidHide != null) { - this._subscriptionKeyboardDidHide.remove(); - } - }, - - /** - * Warning, this may be called several times for a single keyboard opening. - * It's best to store the information in this method and then take any action - * at a later point (either in `keyboardDidShow` or other). - * - * Here's the order that events occur in: - * - focus - * - willShow {startCoordinates, endCoordinates} several times - * - didShow several times - * - blur - * - willHide {startCoordinates, endCoordinates} several times - * - didHide several times - * - * The `ScrollResponder` module callbacks for each of these events. - * Even though any user could have easily listened to keyboard events - * themselves, using these `props` callbacks ensures that ordering of events - * is consistent - and not dependent on the order that the keyboard events are - * subscribed to. This matters when telling the scroll view to scroll to where - * the keyboard is headed - the scroll responder better have been notified of - * the keyboard destination before being instructed to scroll to where the - * keyboard will be. Stick to the `ScrollResponder` callbacks, and everything - * will work. - * - * WARNING: These callbacks will fire even if a keyboard is displayed in a - * different navigation pane. Filter out the events to determine if they are - * relevant to you. (For example, only if you receive these callbacks after - * you had explicitly focused a node etc). - */ - scrollResponderKeyboardWillShow: function(e: KeyboardEvent) { - this.keyboardWillOpenTo = e; - this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e); - }, - - scrollResponderKeyboardWillHide: function(e: KeyboardEvent) { - this.keyboardWillOpenTo = null; - this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e); - }, - - scrollResponderKeyboardDidShow: function(e: KeyboardEvent) { - // TODO(7693961): The event for DidShow is not available on iOS yet. - // Use the one from WillShow and do not assign. - if (e) { - this.keyboardWillOpenTo = e; - } - this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e); - }, - - scrollResponderKeyboardDidHide: function(e: KeyboardEvent) { - this.keyboardWillOpenTo = null; - this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e); - }, -}; - -const ScrollResponder = { - Mixin: ScrollResponderMixin, -}; - -module.exports = ScrollResponder; diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js index fa0a173a4fdcc5..71210f989d7e20 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollContentViewNativeComponent.js @@ -5,36 +5,19 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow + * @flow strict-local */ -'use strict'; - -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; - +import codegenNativeComponent from '../../Utilities/codegenNativeComponent'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {ViewProps} from '../View/ViewPropTypes'; -const AndroidHorizontalScrollContentViewViewConfig = { - uiViewClassName: 'AndroidHorizontalScrollContentView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: {}, -}; +type NativeProps = $ReadOnly<{| + ...ViewProps, +|}>; -let AndroidHorizontalScrollContentViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'AndroidHorizontalScrollContentView', - AndroidHorizontalScrollContentViewViewConfig, - ); - AndroidHorizontalScrollContentViewNativeComponent = - 'AndroidHorizontalScrollContentView'; -} else { - AndroidHorizontalScrollContentViewNativeComponent = requireNativeComponent( - 'AndroidHorizontalScrollContentView', - ); -} +type NativeType = HostComponent; -export default ((AndroidHorizontalScrollContentViewNativeComponent: any): HostComponent); +export default (codegenNativeComponent( + 'AndroidHorizontalScrollContentView', +): NativeType); diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js index a4a0d4e6bb8dba..05f629e01a1d1e 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js @@ -4,54 +4,40 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ -'use strict'; - -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; - +import type {ScrollViewNativeProps as Props} from './ScrollViewNativeComponentType'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ScrollViewNativeProps} from './ScrollViewNativeComponentType'; - -const AndroidHorizontalScrollViewViewConfig = { - uiViewClassName: 'AndroidHorizontalScrollView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: { - decelerationRate: true, - disableIntervalMomentum: true, - endFillColor: {process: require('../../StyleSheet/processColor')}, - fadingEdgeLength: true, - nestedScrollEnabled: true, - overScrollMode: true, - pagingEnabled: true, - persistentScrollbar: true, - scrollEnabled: true, - scrollPerfTag: true, - sendMomentumEvents: true, - showsHorizontalScrollIndicator: true, - snapToEnd: true, - snapToInterval: true, - snapToStart: true, - snapToOffsets: true, - contentOffset: true, - }, -}; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; -let AndroidHorizontalScrollViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'AndroidHorizontalScrollView', - AndroidHorizontalScrollViewViewConfig, - ); - AndroidHorizontalScrollViewNativeComponent = 'AndroidHorizontalScrollView'; -} else { - AndroidHorizontalScrollViewNativeComponent = requireNativeComponent( - 'AndroidHorizontalScrollView', - ); -} +const AndroidHorizontalScrollViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'AndroidHorizontalScrollView', + () => ({ + uiViewClassName: 'AndroidHorizontalScrollView', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: { + decelerationRate: true, + disableIntervalMomentum: true, + endFillColor: {process: require('../../StyleSheet/processColor')}, + fadingEdgeLength: true, + nestedScrollEnabled: true, + overScrollMode: true, + pagingEnabled: true, + persistentScrollbar: true, + scrollEnabled: true, + scrollPerfTag: true, + sendMomentumEvents: true, + showsHorizontalScrollIndicator: true, + snapToEnd: true, + snapToInterval: true, + snapToStart: true, + snapToOffsets: true, + contentOffset: true, + }, + }), +); -export default ((AndroidHorizontalScrollViewNativeComponent: any): HostComponent); +export default AndroidHorizontalScrollViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js b/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js index 6a94a30a72dae7..4e3174044dfc8b 100644 --- a/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js +++ b/Libraries/Components/ScrollView/ScrollContentViewNativeComponent.js @@ -8,32 +8,18 @@ * @flow */ -'use strict'; - -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; - import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {ViewProps} from '../View/ViewPropTypes'; - -const ScrollContentViewViewConfig = { - uiViewClassName: 'RCTScrollContentView', - bubblingEventTypes: {}, - directEventTypes: {}, - validAttributes: {}, -}; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import type {ViewProps as Props} from '../View/ViewPropTypes'; -let ScrollContentViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig( - 'RCTScrollContentView', - ScrollContentViewViewConfig, - ); - ScrollContentViewNativeComponent = 'RCTScrollContentView'; -} else { - ScrollContentViewNativeComponent = requireNativeComponent( - 'RCTScrollContentView', - ); -} +const ScrollContentViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTScrollContentView', + () => ({ + uiViewClassName: 'RCTScrollContentView', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: {}, + }), +); -export default ((ScrollContentViewNativeComponent: any): HostComponent); +export default ScrollContentViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index cdaafbe4a6b2af..541245effac1c2 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -8,23 +8,24 @@ * @flow strict-local */ -'use strict'; - import AnimatedImplementation from '../../Animated/AnimatedImplementation'; +import Dimensions from '../../Utilities/Dimensions'; import Platform from '../../Utilities/Platform'; import * as React from 'react'; import ReactNative from '../../Renderer/shims/ReactNative'; require('../../Renderer/shims/ReactNative'); // Force side effects to prevent T55744311 -import ScrollResponder from '../ScrollResponder'; import ScrollViewStickyHeader from './ScrollViewStickyHeader'; import StyleSheet from '../../StyleSheet/StyleSheet'; import View from '../View/View'; +import UIManager from '../../ReactNative/UIManager'; +import Keyboard from '../Keyboard/Keyboard'; +import FrameRateLogger from '../../Interaction/FrameRateLogger'; +import TextInputState from '../TextInput/TextInputState'; import dismissKeyboard from '../../Utilities/dismissKeyboard'; import flattenStyle from '../../StyleSheet/flattenStyle'; import invariant from 'invariant'; import processDecelerationRate from './processDecelerationRate'; -import resolveAssetSource from '../../Image/resolveAssetSource'; import splitLayoutProps from '../../StyleSheet/splitLayoutProps'; import setAndForwardRef from '../../Utilities/setAndForwardRef'; @@ -38,33 +39,110 @@ import type { LayoutEvent, } from '../../Types/CoreEventTypes'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; -import type {State as ScrollResponderState} from '../ScrollResponder'; import type {ViewProps} from '../View/ViewPropTypes'; +import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeader'; +import type {KeyboardEvent} from '../Keyboard/Keyboard'; +import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; -import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; -import ScrollViewNativeComponent from './ScrollViewNativeComponent'; -import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent'; -import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent'; +import Commands from './ScrollViewCommands'; import AndroidHorizontalScrollContentViewNativeComponent from './AndroidHorizontalScrollContentViewNativeComponent'; +import AndroidHorizontalScrollViewNativeComponent from './AndroidHorizontalScrollViewNativeComponent'; +import ScrollContentViewNativeComponent from './ScrollContentViewNativeComponent'; +import ScrollViewNativeComponent from './ScrollViewNativeComponent'; -let AndroidScrollView; -let AndroidHorizontalScrollContentView; -let AndroidHorizontalScrollView; -let RCTScrollView; -let RCTScrollContentView; - -if (Platform.OS === 'android') { - AndroidScrollView = ScrollViewNativeComponent; - AndroidHorizontalScrollView = AndroidHorizontalScrollViewNativeComponent; - AndroidHorizontalScrollContentView = AndroidHorizontalScrollContentViewNativeComponent; -} else if ( - Platform.OS === 'ios' || - Platform.OS === 'macos' /*TODO(macOS GH#774)*/ -) { - RCTScrollView = ScrollViewNativeComponent; - RCTScrollContentView = ScrollContentViewNativeComponent; -} +const {NativeHorizontalScrollViewTuple, NativeVerticalScrollViewTuple} = + Platform.OS === 'android' + ? { + NativeHorizontalScrollViewTuple: [ + AndroidHorizontalScrollViewNativeComponent, + AndroidHorizontalScrollContentViewNativeComponent, + ], + NativeVerticalScrollViewTuple: [ScrollViewNativeComponent, View], + } + : { + NativeHorizontalScrollViewTuple: [ + ScrollViewNativeComponent, + ScrollContentViewNativeComponent, + ], + NativeVerticalScrollViewTuple: [ + ScrollViewNativeComponent, + ScrollContentViewNativeComponent, + ], + }; + +/* + * iOS scroll event timing nuances: + * =============================== + * + * + * Scrolling without bouncing, if you touch down: + * ------------------------------- + * + * 1. `onMomentumScrollBegin` (when animation begins after letting up) + * ... physical touch starts ... + * 2. `onTouchStartCapture` (when you press down to stop the scroll) + * 3. `onTouchStart` (same, but bubble phase) + * 4. `onResponderRelease` (when lifting up - you could pause forever before * lifting) + * 5. `onMomentumScrollEnd` + * + * + * Scrolling with bouncing, if you touch down: + * ------------------------------- + * + * 1. `onMomentumScrollBegin` (when animation begins after letting up) + * ... bounce begins ... + * ... some time elapses ... + * ... physical touch during bounce ... + * 2. `onMomentumScrollEnd` (Makes no sense why this occurs first during bounce) + * 3. `onTouchStartCapture` (immediately after `onMomentumScrollEnd`) + * 4. `onTouchStart` (same, but bubble phase) + * 5. `onTouchEnd` (You could hold the touch start for a long time) + * 6. `onMomentumScrollBegin` (When releasing the view starts bouncing back) + * + * So when we receive an `onTouchStart`, how can we tell if we are touching + * *during* an animation (which then causes the animation to stop)? The only way + * to tell is if the `touchStart` occurred immediately after the + * `onMomentumScrollEnd`. + * + * This is abstracted out for you, so you can just call this.scrollResponderIsAnimating() if + * necessary + * + * `ScrollView` also includes logic for blurring a currently focused input + * if one is focused while scrolling. This is a natural place + * to put this logic since it can support not dismissing the keyboard while + * scrolling, unless a recognized "tap"-like gesture has occurred. + * + * The public lifecycle API includes events for keyboard interaction, responder + * interaction, and scrolling (among others). The keyboard callbacks + * `onKeyboardWill/Did/*` are *global* events, but are invoked on scroll + * responder's props so that you can guarantee that the scroll responder's + * internal state has been updated accordingly (and deterministically) by + * the time the props callbacks are invoke. Otherwise, you would always wonder + * if the scroll responder is currently in a state where it recognizes new + * keyboard positions etc. If coordinating scrolling with keyboard movement, + * *always* use these hooks instead of listening to your own global keyboard + * events. + * + * Public keyboard lifecycle API: (props callbacks) + * + * Standard Keyboard Appearance Sequence: + * + * this.props.onKeyboardWillShow + * this.props.onKeyboardDidShow + * + * `onScrollResponderKeyboardDismissed` will be invoked if an appropriate + * tap inside the scroll responder's scrollable region was responsible + * for the dismissal of the keyboard. There are other reasons why the + * keyboard could be dismissed. + * + * this.props.onScrollResponderKeyboardDismissed + * + * Standard Keyboard Hide Sequence: + * + * this.props.onKeyboardWillHide + * this.props.onKeyboardDidHide + */ // Public methods for ScrollView export type ScrollViewImperativeMethods = $ReadOnly<{| @@ -76,14 +154,9 @@ export type ScrollViewImperativeMethods = $ReadOnly<{| scrollTo: $PropertyType, scrollToEnd: $PropertyType, flashScrollIndicators: $PropertyType, - - // ScrollResponder.Mixin public methods - scrollResponderZoomTo: $PropertyType< - typeof ScrollResponder.Mixin, - 'scrollResponderZoomTo', - >, + scrollResponderZoomTo: $PropertyType, scrollResponderScrollNativeHandleToKeyboard: $PropertyType< - typeof ScrollResponder.Mixin, + ScrollView, 'scrollResponderScrollNativeHandleToKeyboard', >, |}>; @@ -98,6 +171,12 @@ type IOSProps = $ReadOnly<{| * @platform ios */ automaticallyAdjustContentInsets?: ?boolean, + /** + * Controls whether iOS should automatically adjust the scroll indicator + * insets. The default value is true. Available on iOS 13 and later. + * @platform ios + */ + automaticallyAdjustsScrollIndicatorInsets?: ?boolean, /** * The amount by which the scroll view content is inset from the edges * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`. @@ -368,32 +447,15 @@ type AndroidProps = $ReadOnly<{| fadingEdgeLength?: ?number, |}>; -type VRProps = $ReadOnly<{| - /** - * Optionally an image can be used for the scroll bar thumb. This will - * override the color. While the image is loading or the image fails to - * load the color will be used instead. Use an alpha of 0 in the color - * to avoid seeing it while the image is loading. - * - * - `uri` - a string representing the resource identifier for the image, which - * should be either a local file path or the name of a static image resource - * - `number` - Opaque type returned by something like - * `import IMAGE from './image.jpg'`. - * @platform vr - */ - scrollBarThumbImage?: ?($ReadOnly<{||}> | number), // Opaque type returned by import IMAGE from './image.jpg' -|}>; - type StickyHeaderComponentType = React.AbstractComponent< ScrollViewStickyHeaderProps, - $ReadOnly<{setNextHeaderY: number => void, ...}>, + $ReadOnly void}>, >; export type Props = $ReadOnly<{| ...ViewProps, ...IOSProps, ...AndroidProps, - ...VRProps, /** * These styles will be applied to the scroll view content container which @@ -456,10 +518,8 @@ export type Props = $ReadOnly<{| * On android this is not supported and it will have the same behavior as 'none'. */ keyboardDismissMode?: ?// default - (| 'none' // cross-platform - | 'on-drag' - | 'interactive' - ), // ios only + // cross-platform + ('none' | 'on-drag' | 'interactive'), // ios only /** * Determines when the keyboard should stay visible after a tap. * @@ -506,7 +566,10 @@ export type Props = $ReadOnly<{| * which this ScrollView renders. */ onContentSizeChange?: (contentWidth: number, contentHeight: number) => void, - onKeyboardDidShow?: (event: PressEvent) => void, + onKeyboardDidShow?: (event: KeyboardEvent) => void, + onKeyboardDidHide?: (event: KeyboardEvent) => void, + onKeyboardWillShow?: (event: KeyboardEvent) => void, + onKeyboardWillHide?: (event: KeyboardEvent) => void, /** * When true, the scroll view stops on multiples of the scroll view's size * when scrolling. This can be used for horizontal pagination. The default @@ -528,6 +591,11 @@ export type Props = $ReadOnly<{| * The default value is true. */ showsVerticalScrollIndicator?: ?boolean, + /** + * When true, Sticky header is hidden when scrolling down, and dock at the top + * when scrolling up + */ + stickyHeaderHiddenOnScroll?: ?boolean, /** * An array of child indices determining which children get docked to the * top of the screen when scrolling. For example, passing @@ -591,7 +659,8 @@ export type Props = $ReadOnly<{| * * See [RefreshControl](docs/refreshcontrol.html). */ - // $FlowFixMe - how to handle generic type without existential operator? + /* $FlowFixMe[unclear-type] - how to handle generic type without existential + * operator? */ refreshControl?: ?React.Element, children?: React.Node, /** @@ -612,22 +681,9 @@ export type Props = $ReadOnly<{| type State = {| contentKey: number, // TODO(macOS GH#774) layoutHeight: ?number, - ...ScrollResponderState, |}; -function createScrollResponder( - node: React.ElementRef, -): typeof ScrollResponder.Mixin { - const scrollResponder = {...ScrollResponder.Mixin}; - - for (const key in scrollResponder) { - if (typeof scrollResponder[key] === 'function') { - scrollResponder[key] = scrollResponder[key].bind(node); - } - } - - return scrollResponder; -} +const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16; type ScrollViewComponentStatics = $ReadOnly<{| Context: typeof ScrollViewContext, @@ -670,61 +726,17 @@ type ScrollViewComponentStatics = $ReadOnly<{| */ class ScrollView extends React.Component { static Context: typeof ScrollViewContext = ScrollViewContext; - /** - * Part 1: Removing ScrollResponder.Mixin: - * - * 1. Mixin methods should be flow typed. That's why we create a - * copy of ScrollResponder.Mixin and attach it to this._scrollResponder. - * Otherwise, we'd have to manually declare each method on the component - * class and assign it a flow type. - * 2. Mixin methods can call component methods, and access the component's - * props and state. So, we need to bind all mixin methods to the - * component instance. - * 3. Continued... - */ - _scrollResponder: typeof ScrollResponder.Mixin = createScrollResponder(this); constructor(props: Props) { super(props); - /** - * Part 2: Removing ScrollResponder.Mixin - * - * 3. Mixin methods access other mixin methods via dynamic dispatch using - * this. Since mixin methods are bound to the component instance, we need - * to copy all mixin methods to the component instance. This is also - * necessary because getScrollResponder() is a public method that returns - * an object that can be used to execute all scrollResponder methods. - * Since the object returned from that method is the ScrollView instance, - * we need to bind all mixin methods to the ScrollView instance. - */ - for (const key in ScrollResponder.Mixin) { - if ( - typeof ScrollResponder.Mixin[key] === 'function' && - key.startsWith('scrollResponder') - ) { - // $FlowFixMe - dynamically adding properties to a class - (this: any)[key] = ScrollResponder.Mixin[key].bind(this); - } - } - - /** - * Part 3: Removing ScrollResponder.Mixin - * - * 4. Mixins can initialize properties and use properties on the component - * instance. - */ - Object.keys(ScrollResponder.Mixin) - .filter(key => typeof ScrollResponder.Mixin[key] !== 'function') - .forEach(key => { - // $FlowFixMe - dynamically adding properties to a class - (this: any)[key] = ScrollResponder.Mixin[key]; - }); + this._scrollAnimatedValue = new AnimatedImplementation.Value( + this.props.contentOffset?.y ?? 0, + ); + this._scrollAnimatedValue.setOffset(this.props.contentInset?.top ?? 0); } - _scrollAnimatedValue: AnimatedImplementation.Value = new AnimatedImplementation.Value( - 0, - ); + _scrollAnimatedValue: AnimatedImplementation.Value; _scrollAnimatedValueAttachment: ?{detach: () => void, ...} = null; _stickyHeaderRefs: Map< string, @@ -732,44 +744,96 @@ class ScrollView extends React.Component { > = new Map(); _headerLayoutYs: Map = new Map(); + _keyboardWillOpenTo: ?KeyboardEvent = null; + _additionalScrollOffset: number = 0; + _isTouching: boolean = false; + _lastMomentumScrollBeginTime: number = 0; + _lastMomentumScrollEndTime: number = 0; + + // Reset to false every time becomes responder. This is used to: + // - Determine if the scroll view has been scrolled and therefore should + // refuse to give up its responder lock. + // - Determine if releasing should dismiss the keyboard when we are in + // tap-to-dismiss mode (this.props.keyboardShouldPersistTaps !== 'always'). + _observedScrollSinceBecomingResponder: boolean = false; + _becameResponderWhileAnimating: boolean = false; + _preventNegativeScrollOffset: ?boolean = null; + + _animated = null; + + _subscriptionKeyboardWillShow: ?EventSubscription = null; + _subscriptionKeyboardWillHide: ?EventSubscription = null; + _subscriptionKeyboardDidShow: ?EventSubscription = null; + _subscriptionKeyboardDidHide: ?EventSubscription = null; + state: State = { contentKey: 1, // TODO(macOS GH#774) layoutHeight: null, - ...ScrollResponder.Mixin.scrollResponderMixinGetInitialState(), }; - UNSAFE_componentWillMount() { - this._scrollResponder.UNSAFE_componentWillMount(); - this._scrollAnimatedValue = new AnimatedImplementation.Value( - this.props.contentOffset?.y ?? 0, + componentDidMount() { + if (typeof this.props.keyboardShouldPersistTaps === 'boolean') { + console.warn( + `'keyboardShouldPersistTaps={${ + this.props.keyboardShouldPersistTaps === true ? 'true' : 'false' + }}' is deprecated. ` + + `Use 'keyboardShouldPersistTaps="${ + this.props.keyboardShouldPersistTaps ? 'always' : 'never' + }"' instead`, + ); + } + + this._keyboardWillOpenTo = null; + this._additionalScrollOffset = 0; + + this._subscriptionKeyboardWillShow = Keyboard.addListener( + 'keyboardWillShow', + this.scrollResponderKeyboardWillShow, ); - this._scrollAnimatedValue.setOffset(this.props.contentInset?.top ?? 0); - this._stickyHeaderRefs = new Map(); - this._headerLayoutYs = new Map(); + this._subscriptionKeyboardWillHide = Keyboard.addListener( + 'keyboardWillHide', + this.scrollResponderKeyboardWillHide, + ); + this._subscriptionKeyboardDidShow = Keyboard.addListener( + 'keyboardDidShow', + this.scrollResponderKeyboardDidShow, + ); + this._subscriptionKeyboardDidHide = Keyboard.addListener( + 'keyboardDidHide', + this.scrollResponderKeyboardDidHide, + ); + + this._updateAnimatedNodeAttachment(); } - UNSAFE_componentWillReceiveProps(nextProps: Props) { - const currentContentInsetTop = this.props.contentInset - ? this.props.contentInset.top + componentDidUpdate(prevProps: Props) { + const prevContentInsetTop = prevProps.contentInset + ? prevProps.contentInset.top : 0; - const nextContentInsetTop = nextProps.contentInset - ? nextProps.contentInset.top + const newContentInsetTop = this.props.contentInset + ? this.props.contentInset.top : 0; - if (currentContentInsetTop !== nextContentInsetTop) { - this._scrollAnimatedValue.setOffset(nextContentInsetTop || 0); + if (prevContentInsetTop !== newContentInsetTop) { + this._scrollAnimatedValue.setOffset(newContentInsetTop || 0); } - } - componentDidMount() { - this._updateAnimatedNodeAttachment(); - } - - componentDidUpdate() { this._updateAnimatedNodeAttachment(); } componentWillUnmount() { - this._scrollResponder.componentWillUnmount(); + if (this._subscriptionKeyboardWillShow != null) { + this._subscriptionKeyboardWillShow.remove(); + } + if (this._subscriptionKeyboardWillHide != null) { + this._subscriptionKeyboardWillHide.remove(); + } + if (this._subscriptionKeyboardDidShow != null) { + this._subscriptionKeyboardDidShow.remove(); + } + if (this._subscriptionKeyboardDidHide != null) { + this._subscriptionKeyboardDidHide.remove(); + } + if (this._scrollAnimatedValueAttachment) { this._scrollAnimatedValueAttachment.detach(); } @@ -798,10 +862,7 @@ class ScrollView extends React.Component { ref.scrollTo = this.scrollTo; ref.scrollToEnd = this.scrollToEnd; ref.flashScrollIndicators = this.flashScrollIndicators; - - // $FlowFixMe - This method was manually bound from ScrollResponder.mixin ref.scrollResponderZoomTo = this.scrollResponderZoomTo; - // $FlowFixMe - This method was manually bound from ScrollResponder.mixin ref.scrollResponderScrollNativeHandleToKeyboard = this.scrollResponderScrollNativeHandleToKeyboard; } }, @@ -814,7 +875,7 @@ class ScrollView extends React.Component { * to the underlying scroll responder's methods. */ getScrollResponder: () => ScrollResponderType = () => { - // $FlowFixMe - overriding type to include ScrollResponder.Mixin + // $FlowFixMe[unclear-type] return ((this: any): ScrollResponderType); }; @@ -822,13 +883,13 @@ class ScrollView extends React.Component { return ReactNative.findNodeHandle(this._scrollViewRef); }; - getInnerViewNode(): ?number { + getInnerViewNode: () => ?number = () => { return ReactNative.findNodeHandle(this._innerViewRef); - } + }; - getInnerViewRef(): ?React.ElementRef { + getInnerViewRef: () => ?React.ElementRef = () => { return this._innerViewRef; - } + }; getNativeScrollRef: () => ?React.ElementRef> = () => { return this._scrollViewRef; @@ -882,11 +943,10 @@ class ScrollView extends React.Component { x = options.x; animated = options.animated; } - this._scrollResponder.scrollResponderScrollTo({ - x: x || 0, - y: y || 0, - animated: animated !== false, - }); + if (this._scrollViewRef == null) { + return; + } + Commands.scrollTo(this._scrollViewRef, x || 0, y || 0, animated !== false); }; /** @@ -902,9 +962,10 @@ class ScrollView extends React.Component { ) => { // Default to true const animated = (options && options.animated) !== false; - this._scrollResponder.scrollResponderScrollToEnd({ - animated: animated, - }); + if (this._scrollViewRef == null) { + return; + } + Commands.scrollToEnd(this._scrollViewRef, animated); }; /** @@ -913,7 +974,150 @@ class ScrollView extends React.Component { * @platform ios */ flashScrollIndicators: () => void = () => { - this._scrollResponder.scrollResponderFlashScrollIndicators(); + if (this._scrollViewRef == null) { + return; + } + Commands.flashScrollIndicators(this._scrollViewRef); + }; + + /** + * This method should be used as the callback to onFocus in a TextInputs' + * parent view. Note that any module using this mixin needs to return + * the parent view's ref in getScrollViewRef() in order to use this method. + * @param {number} nodeHandle The TextInput node handle + * @param {number} additionalOffset The scroll view's bottom "contentInset". + * Default is 0. + * @param {bool} preventNegativeScrolling Whether to allow pulling the content + * down to make it meet the keyboard's top. Default is false. + */ + scrollResponderScrollNativeHandleToKeyboard: ( + nodeHandle: number | React.ElementRef>, + additionalOffset?: number, + preventNegativeScrollOffset?: boolean, + ) => void = ( + nodeHandle: number | React.ElementRef>, + additionalOffset?: number, + preventNegativeScrollOffset?: boolean, + ) => { + this._additionalScrollOffset = additionalOffset || 0; + this._preventNegativeScrollOffset = !!preventNegativeScrollOffset; + + if (this._innerViewRef == null) { + return; + } + + if (typeof nodeHandle === 'number') { + UIManager.measureLayout( + nodeHandle, + ReactNative.findNodeHandle(this), + // $FlowFixMe[method-unbinding] added when improving typing for this parameters + this._textInputFocusError, + this._inputMeasureAndScrollToKeyboard, + ); + } else { + nodeHandle.measureLayout( + this._innerViewRef, + this._inputMeasureAndScrollToKeyboard, + // $FlowFixMe[method-unbinding] added when improving typing for this parameters + this._textInputFocusError, + ); + } + }; + + /** + * A helper function to zoom to a specific rect in the scrollview. The argument has the shape + * {x: number; y: number; width: number; height: number; animated: boolean = true} + * + * @platform ios + */ + scrollResponderZoomTo: ( + rect: {| + x: number, + y: number, + width: number, + height: number, + animated?: boolean, + |}, + animated?: boolean, // deprecated, put this inside the rect argument instead + ) => void = ( + rect: {| + x: number, + y: number, + width: number, + height: number, + animated?: boolean, + |}, + animated?: boolean, // deprecated, put this inside the rect argument instead + ) => { + invariant(Platform.OS === 'ios', 'zoomToRect is not implemented'); + if ('animated' in rect) { + this._animated = rect.animated; + delete rect.animated; + } else if (typeof animated !== 'undefined') { + console.warn( + '`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead', + ); + } + + if (this._scrollViewRef == null) { + return; + } + Commands.zoomToRect(this._scrollViewRef, rect, animated !== false); + }; + + _textInputFocusError() { + console.warn('Error measuring text field.'); + } + + /** + * The calculations performed here assume the scroll view takes up the entire + * screen - even if has some content inset. We then measure the offsets of the + * keyboard, and compensate both for the scroll view's "contentInset". + * + * @param {number} left Position of input w.r.t. table view. + * @param {number} top Position of input w.r.t. table view. + * @param {number} width Width of the text input. + * @param {number} height Height of the text input. + */ + _inputMeasureAndScrollToKeyboard: ( + left: number, + top: number, + width: number, + height: number, + ) => void = (left: number, top: number, width: number, height: number) => { + let keyboardScreenY = Dimensions.get('window').height; + + const scrollTextInputIntoVisibleRect = () => { + if (this._keyboardWillOpenTo != null) { + keyboardScreenY = this._keyboardWillOpenTo.endCoordinates.screenY; + } + let scrollOffsetY = + top - keyboardScreenY + height + this._additionalScrollOffset; + + // By default, this can scroll with negative offset, pulling the content + // down so that the target component's bottom meets the keyboard's top. + // If requested otherwise, cap the offset at 0 minimum to avoid content + // shifting down. + if (this._preventNegativeScrollOffset === true) { + scrollOffsetY = Math.max(0, scrollOffsetY); + } + this.scrollTo({x: 0, y: scrollOffsetY, animated: true}); + + this._additionalScrollOffset = 0; + this._preventNegativeScrollOffset = false; + }; + + if (this._keyboardWillOpenTo == null) { + // `_keyboardWillOpenTo` is set inside `scrollResponderKeyboardWillShow` which + // is not guaranteed to be called before `_inputMeasureAndScrollToKeyboard` but native has already scheduled it. + // In case it was not called before `_inputMeasureAndScrollToKeyboard`, we postpone scrolling to + // text input. + setTimeout(() => { + scrollTextInputIntoVisibleRect(); + }, 0); + } else { + scrollTextInputIntoVisibleRect(); + } }; _getKeyForIndex(index, childArray) { @@ -1072,14 +1276,12 @@ class ScrollView extends React.Component { } } if (Platform.OS === 'android') { - if ( - this.props.keyboardDismissMode === 'on-drag' && - this.state.isTouching - ) { + if (this.props.keyboardDismissMode === 'on-drag' && this._isTouching) { dismissKeyboard(); } } - this._scrollResponder.scrollResponderHandleScroll(e); + this._observedScrollSinceBecomingResponder = true; + this.props.onScroll && this.props.onScroll(e); }; _handleLayout = (e: LayoutEvent) => { @@ -1107,31 +1309,395 @@ class ScrollView extends React.Component { }, }); - render(): React.Node | React.Element { - let ScrollViewClass; - let ScrollContentContainerViewClass; - if (Platform.OS === 'android') { - if (this.props.horizontal === true) { - ScrollViewClass = AndroidHorizontalScrollView; - ScrollContentContainerViewClass = AndroidHorizontalScrollContentView; - } else { - ScrollViewClass = AndroidScrollView; - ScrollContentContainerViewClass = View; + /** + * Warning, this may be called several times for a single keyboard opening. + * It's best to store the information in this method and then take any action + * at a later point (either in `keyboardDidShow` or other). + * + * Here's the order that events occur in: + * - focus + * - willShow {startCoordinates, endCoordinates} several times + * - didShow several times + * - blur + * - willHide {startCoordinates, endCoordinates} several times + * - didHide several times + * + * The `ScrollResponder` module callbacks for each of these events. + * Even though any user could have easily listened to keyboard events + * themselves, using these `props` callbacks ensures that ordering of events + * is consistent - and not dependent on the order that the keyboard events are + * subscribed to. This matters when telling the scroll view to scroll to where + * the keyboard is headed - the scroll responder better have been notified of + * the keyboard destination before being instructed to scroll to where the + * keyboard will be. Stick to the `ScrollResponder` callbacks, and everything + * will work. + * + * WARNING: These callbacks will fire even if a keyboard is displayed in a + * different navigation pane. Filter out the events to determine if they are + * relevant to you. (For example, only if you receive these callbacks after + * you had explicitly focused a node etc). + */ + + scrollResponderKeyboardWillShow: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardWillOpenTo = e; + this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e); + }; + + scrollResponderKeyboardWillHide: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardWillOpenTo = null; + this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e); + }; + + scrollResponderKeyboardDidShow: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + // TODO(7693961): The event for DidShow is not available on iOS yet. + // Use the one from WillShow and do not assign. + if (e) { + this._keyboardWillOpenTo = e; + } + this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e); + }; + + scrollResponderKeyboardDidHide: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardWillOpenTo = null; + this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e); + }; + + /** + * Invoke this from an `onMomentumScrollBegin` event. + */ + _handleMomentumScrollBegin: (e: ScrollEvent) => void = (e: ScrollEvent) => { + this._lastMomentumScrollBeginTime = global.performance.now(); + this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); + }; + + /** + * Invoke this from an `onMomentumScrollEnd` event. + */ + _handleMomentumScrollEnd: (e: ScrollEvent) => void = (e: ScrollEvent) => { + FrameRateLogger.endScroll(); + this._lastMomentumScrollEndTime = global.performance.now(); + this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); + }; + + /** + * Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll + * animation, and there's not an easy way to distinguish a drag vs. stopping + * momentum. + * + * Invoke this from an `onScrollBeginDrag` event. + */ + _handleScrollBeginDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { + FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation + this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); + }; + + /** + * Invoke this from an `onScrollEndDrag` event. + */ + _handleScrollEndDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { + const {velocity} = e.nativeEvent; + // - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end + // will fire. + // - If velocity is non-zero, then the interaction will stop when momentum scroll ends or + // another drag starts and ends. + // - If we don't get velocity, better to stop the interaction twice than not stop it. + if ( + !this._isAnimating() && + (!velocity || (velocity.x === 0 && velocity.y === 0)) + ) { + FrameRateLogger.endScroll(); + } + this.props.onScrollEndDrag && this.props.onScrollEndDrag(e); + }; + + /** + * A helper function for this class that lets us quickly determine if the + * view is currently animating. This is particularly useful to know when + * a touch has just started or ended. + */ + _isAnimating: () => boolean = () => { + const now = global.performance.now(); + const timeSinceLastMomentumScrollEnd = + now - this._lastMomentumScrollEndTime; + const isAnimating = + timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS || + this._lastMomentumScrollEndTime < this._lastMomentumScrollBeginTime; + return isAnimating; + }; + + /** + * Invoke this from an `onResponderGrant` event. + */ + _handleResponderGrant: (e: PressEvent) => void = (e: PressEvent) => { + this._observedScrollSinceBecomingResponder = false; + this.props.onResponderGrant && this.props.onResponderGrant(e); + this._becameResponderWhileAnimating = this._isAnimating(); + }; + + /** + * Invoke this from an `onResponderReject` event. + * + * Some other element is not yielding its role as responder. Normally, we'd + * just disable the `UIScrollView`, but a touch has already began on it, the + * `UIScrollView` will not accept being disabled after that. The easiest + * solution for now is to accept the limitation of disallowing this + * altogether. To improve this, find a way to disable the `UIScrollView` after + * a touch has already started. + */ + _handleResponderReject: () => void = () => {}; + + /** + * Invoke this from an `onResponderRelease` event. + */ + _handleResponderRelease: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = e.nativeEvent.touches.length !== 0; + this.props.onResponderRelease && this.props.onResponderRelease(e); + + if (typeof e.target === 'number') { + if (__DEV__) { + console.error( + 'Did not expect event target to be a number. Should have been a native component', + ); } - } else { - ScrollViewClass = RCTScrollView; - ScrollContentContainerViewClass = RCTScrollContentView; + + return; } - invariant( - ScrollViewClass !== undefined, - 'ScrollViewClass must not be undefined', - ); + // By default scroll views will unfocus a textField + // if another touch occurs outside of it + const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); + if ( + this.props.keyboardShouldPersistTaps !== true && + this.props.keyboardShouldPersistTaps !== 'always' && + this._keyboardIsDismissible() && + e.target !== currentlyFocusedTextInput && + !this._observedScrollSinceBecomingResponder && + !this._becameResponderWhileAnimating + ) { + TextInputState.blurTextInput(currentlyFocusedTextInput); + } + }; - invariant( - ScrollContentContainerViewClass !== undefined, - 'ScrollContentContainerViewClass must not be undefined', - ); + /** + * We will allow the scroll view to give up its lock iff it acquired the lock + * during an animation. This is a very useful default that happens to satisfy + * many common user experiences. + * + * - Stop a scroll on the left edge, then turn that into an outer view's + * backswipe. + * - Stop a scroll mid-bounce at the top, continue pulling to have the outer + * view dismiss. + * - However, without catching the scroll view mid-bounce (while it is + * motionless), if you drag far enough for the scroll view to become + * responder (and therefore drag the scroll view a bit), any backswipe + * navigation of a swipe gesture higher in the view hierarchy, should be + * rejected. + */ + _handleResponderTerminationRequest: () => boolean = () => { + return !this._observedScrollSinceBecomingResponder; + }; + + /** + * Invoke this from an `onScroll` event. + */ + _handleScrollShouldSetResponder: () => boolean = () => { + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + return this._isTouching; + }; + + /** + * Merely touch starting is not sufficient for a scroll view to become the + * responder. Being the "responder" means that the very next touch move/end + * event will result in an action/movement. + * + * Invoke this from an `onStartShouldSetResponder` event. + * + * `onStartShouldSetResponder` is used when the next move/end will trigger + * some UI movement/action, but when you want to yield priority to views + * nested inside of the view. + * + * There may be some cases where scroll views actually should return `true` + * from `onStartShouldSetResponder`: Any time we are detecting a standard tap + * that gives priority to nested views. + * + * - If a single tap on the scroll view triggers an action such as + * recentering a map style view yet wants to give priority to interaction + * views inside (such as dropped pins or labels), then we would return true + * from this method when there is a single touch. + * + * - Similar to the previous case, if a two finger "tap" should trigger a + * zoom, we would check the `touches` count, and if `>= 2`, we would return + * true. + * + */ + _handleStartShouldSetResponder: (e: PressEvent) => boolean = ( + e: PressEvent, + ) => { + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + + const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); + + if ( + this.props.keyboardShouldPersistTaps === 'handled' && + this._keyboardIsDismissible() && + e.target !== currentlyFocusedInput + ) { + return true; + } + return false; + }; + + /** + * There are times when the scroll view wants to become the responder + * (meaning respond to the next immediate `touchStart/touchEnd`), in a way + * that *doesn't* give priority to nested views (hence the capture phase): + * + * - Currently animating. + * - Tapping anywhere that is not a text input, while the keyboard is + * up (which should dismiss the keyboard). + * + * Invoke this from an `onStartShouldSetResponderCapture` event. + */ + _handleStartShouldSetResponderCapture: (e: PressEvent) => boolean = ( + e: PressEvent, + ) => { + // The scroll view should receive taps instead of its descendants if: + // * it is already animating/decelerating + if (this._isAnimating()) { + return true; + } + + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + + // * the keyboard is up, keyboardShouldPersistTaps is 'never' (the default), + // and a new touch starts with a non-textinput target (in which case the + // first tap should be sent to the scroll view and dismiss the keyboard, + // then the second tap goes to the actual interior view) + const {keyboardShouldPersistTaps} = this.props; + const keyboardNeverPersistTaps = + !keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never'; + + if (typeof e.target === 'number') { + if (__DEV__) { + console.error( + 'Did not expect event target to be a number. Should have been a native component', + ); + } + + return false; + } + + if ( + keyboardNeverPersistTaps && + this._keyboardIsDismissible() && + e.target != null && + !TextInputState.isTextInput(e.target) + ) { + return true; + } + + return false; + }; + + /** + * Do we consider there to be a dismissible soft-keyboard open? + */ + _keyboardIsDismissible: () => boolean = () => { + const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); + + // We cannot dismiss the keyboard without an input to blur, even if a soft + // keyboard is open (e.g. when keyboard is open due to a native component + // not participating in TextInputState). It's also possible that the + // currently focused input isn't a TextInput (such as by calling ref.focus + // on a non-TextInput). + const hasFocusedTextInput = + currentlyFocusedInput != null && + TextInputState.isTextInput(currentlyFocusedInput); + + // Even if an input is focused, we may not have a keyboard to dismiss. E.g + // when using a physical keyboard. Ensure we have an event for an opened + // keyboard, except on Android where setting windowSoftInputMode to + // adjustNone leads to missing keyboard events. + const softKeyboardMayBeOpen = + this._keyboardWillOpenTo != null || Platform.OS === 'android'; + + return hasFocusedTextInput && softKeyboardMayBeOpen; + }; + + /** + * Invoke this from an `onTouchEnd` event. + * + * @param {PressEvent} e Event. + */ + _handleTouchEnd: (e: PressEvent) => void = (e: PressEvent) => { + const nativeEvent = e.nativeEvent; + this._isTouching = nativeEvent.touches.length !== 0; + this.props.onTouchEnd && this.props.onTouchEnd(e); + }; + + /** + * Invoke this from an `onTouchCancel` event. + * + * @param {PressEvent} e Event. + */ + _handleTouchCancel: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = false; + this.props.onTouchCancel && this.props.onTouchCancel(e); + }; + + /** + * Invoke this from an `onTouchStart` event. + * + * Since we know that the `SimpleEventPlugin` occurs later in the plugin + * order, after `ResponderEventPlugin`, we can detect that we were *not* + * permitted to be the responder (presumably because a contained view became + * responder). The `onResponderReject` won't fire in that case - it only + * fires when a *current* responder rejects our request. + * + * @param {PressEvent} e Touch Start event. + */ + _handleTouchStart: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = true; + this.props.onTouchStart && this.props.onTouchStart(e); + }; + + /** + * Invoke this from an `onTouchMove` event. + * + * Since we know that the `SimpleEventPlugin` occurs later in the plugin + * order, after `ResponderEventPlugin`, we can detect that we were *not* + * permitted to be the responder (presumably because a contained view became + * responder). The `onResponderReject` won't fire in that case - it only + * fires when a *current* responder rejects our request. + * + * @param {PressEvent} e Touch Start event. + */ + _handleTouchMove: (e: PressEvent) => void = (e: PressEvent) => { + this.props.onTouchMove && this.props.onTouchMove(e); + }; + + render(): React.Node | React.Element { + const [NativeDirectionalScrollView, NativeDirectionalScrollContentView] = + this.props.horizontal === true + ? NativeHorizontalScrollViewTuple + : NativeVerticalScrollViewTuple; const contentContainerStyle = [ this.props.horizontal === true && styles.contentContainerHorizontal, @@ -1150,12 +1716,12 @@ class ScrollView extends React.Component { ); } - let contentSizeChangeProps = {}; - if (this.props.onContentSizeChange) { - contentSizeChangeProps = { - onLayout: this._handleContentOnLayout, - }; - } + const contentSizeChangeProps = + this.props.onContentSizeChange == null + ? null + : { + onLayout: this._handleContentOnLayout, + }; const {stickyHeaderIndices} = this.props; let children = this.props.children; @@ -1181,6 +1747,7 @@ class ScrollView extends React.Component { onLayout={event => this._onStickyHeaderLayout(index, event, key)} scrollAnimatedValue={this._scrollAnimatedValue} inverted={this.props.invertStickyHeaders} + hiddenOnScroll={this.props.stickyHeaderHiddenOnScroll} scrollViewHeight={this.state.layoutHeight}> {child} @@ -1201,10 +1768,7 @@ class ScrollView extends React.Component { Array.isArray(stickyHeaderIndices) && stickyHeaderIndices.length > 0; const contentContainer = ( - /* $FlowFixMe(>=0.112.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.112 was deployed. To see the error, delete - * this comment and run Flow. */ - { key={this.state.contentKey} // TODO(macOS GH#774) collapsable={false}> {children} - + ); const alwaysBounceHorizontal = @@ -1239,7 +1803,7 @@ class ScrollView extends React.Component { ...this.props, alwaysBounceHorizontal, alwaysBounceVertical, - style: [baseStyle, this.props.style], + style: StyleSheet.compose(baseStyle, this.props.style), // Override the onContentSizeChange from props, since this event can // bubble up from TextInputs onContentSizeChange: null, @@ -1247,33 +1811,23 @@ class ScrollView extends React.Component { onPreferredScrollerStyleDidChange: this ._handlePreferredScrollerStyleDidChange, // TODO(macOS GH#774) onLayout: this._handleLayout, - onMomentumScrollBegin: this._scrollResponder - .scrollResponderHandleMomentumScrollBegin, - onMomentumScrollEnd: this._scrollResponder - .scrollResponderHandleMomentumScrollEnd, - onResponderGrant: this._scrollResponder - .scrollResponderHandleResponderGrant, - onResponderReject: this._scrollResponder - .scrollResponderHandleResponderReject, - onResponderRelease: this._scrollResponder - .scrollResponderHandleResponderRelease, - onResponderTerminationRequest: this._scrollResponder - .scrollResponderHandleTerminationRequest, - onScrollBeginDrag: this._scrollResponder - .scrollResponderHandleScrollBeginDrag, - onScrollEndDrag: this._scrollResponder.scrollResponderHandleScrollEndDrag, - onScrollShouldSetResponder: this._scrollResponder - .scrollResponderHandleScrollShouldSetResponder, - onStartShouldSetResponder: this._scrollResponder - .scrollResponderHandleStartShouldSetResponder, - onStartShouldSetResponderCapture: this._scrollResponder - .scrollResponderHandleStartShouldSetResponderCapture, - onTouchEnd: this._scrollResponder.scrollResponderHandleTouchEnd, - onTouchMove: this._scrollResponder.scrollResponderHandleTouchMove, - onTouchStart: this._scrollResponder.scrollResponderHandleTouchStart, - onTouchCancel: this._scrollResponder.scrollResponderHandleTouchCancel, + onMomentumScrollBegin: this._handleMomentumScrollBegin, + onMomentumScrollEnd: this._handleMomentumScrollEnd, + onResponderGrant: this._handleResponderGrant, + onResponderReject: this._handleResponderReject, + onResponderRelease: this._handleResponderRelease, + onResponderTerminationRequest: this._handleResponderTerminationRequest, + onScrollBeginDrag: this._handleScrollBeginDrag, + onScrollEndDrag: this._handleScrollEndDrag, + onScrollShouldSetResponder: this._handleScrollShouldSetResponder, + onStartShouldSetResponder: this._handleStartShouldSetResponder, + onStartShouldSetResponderCapture: this + ._handleStartShouldSetResponderCapture, + onTouchEnd: this._handleTouchEnd, + onTouchMove: this._handleTouchMove, + onTouchStart: this._handleTouchStart, + onTouchCancel: this._handleTouchCancel, onScroll: this._handleScroll, - scrollBarThumbImage: resolveAssetSource(this.props.scrollBarThumbImage), scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle, @@ -1316,13 +1870,10 @@ class ScrollView extends React.Component { if (Platform.OS === 'ios') { // On iOS the RefreshControl is a child of the ScrollView. return ( - /* $FlowFixMe(>=0.117.0 site=react_native_fb) This comment suppresses - * an error found when Flow v0.117 was deployed. To see the error, - * delete this comment and run Flow. */ - + {refreshControl} {contentContainer} - + ); } else if (Platform.OS === 'android') { // On Android wrap the ScrollView with a AndroidSwipeRefreshLayout. @@ -1333,20 +1884,20 @@ class ScrollView extends React.Component { const {outer, inner} = splitLayoutProps(flattenStyle(props.style)); return React.cloneElement( refreshControl, - {style: [baseStyle, outer]}, - {contentContainer} - , + , ); } } return ( - + {contentContainer} - + ); } } @@ -1375,7 +1926,7 @@ function Wrapper(props, ref) { Wrapper.displayName = 'ScrollView'; const ForwardedScrollView = React.forwardRef(Wrapper); -// $FlowFixMe Add static context to ForwardedScrollView +// $FlowFixMe[prop-missing] Add static context to ForwardedScrollView ForwardedScrollView.Context = ScrollViewContext; ForwardedScrollView.displayName = 'ScrollView'; diff --git a/Libraries/Components/ScrollView/ScrollViewContext.js b/Libraries/Components/ScrollView/ScrollViewContext.js index f774483912d928..0b5e9ac40de003 100644 --- a/Libraries/Components/ScrollView/ScrollViewContext.js +++ b/Libraries/Components/ScrollView/ScrollViewContext.js @@ -8,14 +8,14 @@ * @format */ -'use strict'; - import * as React from 'react'; type Value = {horizontal: boolean} | null; const ScrollViewContext: React.Context = React.createContext(null); - +if (__DEV__) { + ScrollViewContext.displayName = 'ScrollViewContext'; +} export default ScrollViewContext; export const HORIZONTAL: Value = Object.freeze({horizontal: true}); diff --git a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 1e1100f0cc3165..cdfc8ff450f3c3 100644 --- a/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -4,29 +4,83 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ -'use strict'; +import type {ScrollViewNativeProps as Props} from './ScrollViewNativeComponentType'; +import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; -import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; -import requireNativeComponent from '../../ReactNative/requireNativeComponent'; -import ScrollViewViewConfig from './ScrollViewViewConfig'; +const ScrollViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTScrollView', + () => ({ + uiViewClassName: 'RCTScrollView', + bubblingEventTypes: {}, + directEventTypes: { + topScrollToTop: { + registrationName: 'onScrollToTop', + }, + }, + validAttributes: { + alwaysBounceHorizontal: true, + alwaysBounceVertical: true, + automaticallyAdjustContentInsets: true, + automaticallyAdjustsScrollIndicatorInsets: true, + bounces: true, + bouncesZoom: true, + canCancelContentTouches: true, + centerContent: true, + contentInset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentOffset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentInsetAdjustmentBehavior: true, + decelerationRate: true, + directionalLockEnabled: true, + disableIntervalMomentum: true, + endFillColor: { + process: require('../../StyleSheet/processColor'), + }, + fadingEdgeLength: true, + indicatorStyle: true, + inverted: true, + keyboardDismissMode: true, + maintainVisibleContentPosition: true, + maximumZoomScale: true, + minimumZoomScale: true, + nestedScrollEnabled: true, + onMomentumScrollBegin: true, + onMomentumScrollEnd: true, + onScroll: true, + onScrollBeginDrag: true, + onScrollEndDrag: true, + onScrollToTop: true, + overScrollMode: true, + pagingEnabled: true, + persistentScrollbar: true, + pinchGestureEnabled: true, + scrollEnabled: true, + scrollEventThrottle: true, + scrollIndicatorInsets: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + scrollPerfTag: true, + scrollToOverflowEnabled: true, + scrollsToTop: true, + sendMomentumEvents: true, + showsHorizontalScrollIndicator: true, + showsVerticalScrollIndicator: true, + snapToAlignment: true, + snapToEnd: true, + snapToInterval: true, + snapToOffsets: true, + snapToStart: true, + zoomScale: true, + }, + }), +); -import type { - ScrollViewNativeProps, - ScrollViewNativeComponentType, -} from './ScrollViewNativeComponentType'; - -let ScrollViewNativeComponent; -if (global.RN$Bridgeless) { - registerGeneratedViewConfig('RCTScrollView', ScrollViewViewConfig); - ScrollViewNativeComponent = 'RCTScrollView'; -} else { - ScrollViewNativeComponent = requireNativeComponent( - 'RCTScrollView', - ); -} - -export default ((ScrollViewNativeComponent: any): ScrollViewNativeComponentType); +export default ScrollViewNativeComponent; diff --git a/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js b/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js index a6366e8b62b347..24e0c70f442787 100644 --- a/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +++ b/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js @@ -4,18 +4,13 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ 'use strict'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; import type {ViewProps} from '../View/ViewPropTypes'; -import type { - ViewStyleProp, - DangerouslyImpreciseStyle, -} from '../../StyleSheet/StyleSheet'; import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; import type {ScrollEvent} from '../../Types/CoreEventTypes'; @@ -26,6 +21,7 @@ export type ScrollViewNativeProps = $ReadOnly<{ alwaysBounceHorizontal?: ?boolean, alwaysBounceVertical?: ?boolean, automaticallyAdjustContentInsets?: ?boolean, + automaticallyAdjustsScrollIndicatorInsets?: ?boolean, bounces?: ?boolean, bouncesZoom?: ?boolean, canCancelContentTouches?: ?boolean, @@ -45,10 +41,10 @@ export type ScrollViewNativeProps = $ReadOnly<{ fadingEdgeLength?: ?number, indicatorStyle?: ?('default' | 'black' | 'white'), keyboardDismissMode?: ?('none' | 'on-drag' | 'interactive'), - maintainVisibleContentPosition?: ?$ReadOnly<{| + maintainVisibleContentPosition?: ?$ReadOnly<{ minIndexForVisible: number, autoscrollToTopThreshold?: ?number, - |}>, + }>, maximumZoomScale?: ?number, minimumZoomScale?: ?number, nestedScrollEnabled?: ?boolean, @@ -78,9 +74,6 @@ export type ScrollViewNativeProps = $ReadOnly<{ snapToStart?: ?boolean, zoomScale?: ?number, // Overrides - style?: {...ViewStyleProp, ...} | DangerouslyImpreciseStyle, - onResponderGrant?: ?(e: any) => void | boolean, + onResponderGrant?: ?(e: $FlowFixMe) => void | boolean, ... }>; - -export type ScrollViewNativeComponentType = HostComponent; diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index a71b9d56020386..f530be611602e1 100644 --- a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -4,289 +4,303 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict-local * @format */ -'use strict'; - -import AnimatedImplementation from '../../Animated/AnimatedImplementation'; -import * as React from 'react'; -import StyleSheet from '../../StyleSheet/StyleSheet'; -import View from '../View/View'; -import Platform from '../../Utilities/Platform'; - import type {LayoutEvent} from '../../Types/CoreEventTypes'; +import setAndForwardRef from 'react-native/Libraries/Utilities/setAndForwardRef'; +import Platform from '../../Utilities/Platform'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import Animated from '../../Animated/Animated'; +import * as React from 'react'; +import {useEffect, useMemo, useRef, useCallback} from 'react'; -const AnimatedView = AnimatedImplementation.createAnimatedComponent(View); +const AnimatedView = Animated.View; -export type Props = { - children?: React.Element, +export type Props = $ReadOnly<{ + children?: React.Element<$FlowFixMe>, nextHeaderLayoutY: ?number, onLayout: (event: LayoutEvent) => void, - scrollAnimatedValue: AnimatedImplementation.Value, + scrollAnimatedValue: Animated.Value, // Will cause sticky headers to stick at the bottom of the ScrollView instead // of the top. inverted: ?boolean, // The height of the parent ScrollView. Currently only set when inverted. scrollViewHeight: ?number, nativeID?: ?string, - ... -}; - -type State = { - measured: boolean, - layoutY: number, - layoutHeight: number, - nextHeaderLayoutY: ?number, - translateY: ?number, - ... -}; + hiddenOnScroll?: ?boolean, +}>; -class ScrollViewStickyHeader extends React.Component { - state: State = { - measured: false, - layoutY: 0, - layoutHeight: 0, - nextHeaderLayoutY: this.props.nextHeaderLayoutY, - translateY: null, - }; +const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent< + Props, + $ReadOnly<{ + setNextHeaderY: number => void, + ...$Exact>, + }>, +> = React.forwardRef(function ScrollViewStickyHeader(props, forwardedRef) { + const { + inverted, + scrollViewHeight, + hiddenOnScroll, + scrollAnimatedValue, + nextHeaderLayoutY: _nextHeaderLayoutY, + } = props; - _translateY: ?AnimatedImplementation.Interpolation = null; - _shouldRecreateTranslateY: boolean = true; - _haveReceivedInitialZeroTranslateY: boolean = true; - _ref: any; // TODO T53738161: flow type this, and the whole file + const [measured, setMeasured] = React.useState(false); + const [layoutY, setLayoutY] = React.useState(0); + const [layoutHeight, setLayoutHeight] = React.useState(0); + const [translateY, setTranslateY] = React.useState(null); + const [nextHeaderLayoutY, setNextHeaderLayoutY] = React.useState( + _nextHeaderLayoutY, + ); + const [isFabric, setIsFabric] = React.useState(false); - // Fabric-only: - _timer: ?TimeoutID; - _animatedValueListenerId: string; - _animatedValueListener: (valueObject: $ReadOnly<{|value: number|}>) => void; - _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; + const componentRef = React.useRef>(); + const _setNativeRef = setAndForwardRef({ + getForwardedRef: () => forwardedRef, + setLocalRef: ref => { + componentRef.current = ref; + if (ref) { + ref.setNextHeaderY = value => { + setNextHeaderLayoutY(value); + }; + setIsFabric( + !!( + // An internal transform mangles variables with leading "_" as private. + // eslint-disable-next-line dot-notation + ref['_internalInstanceHandle']?.stateNode?.canonical + ), + ); + } + }, + }); - setNextHeaderY(y: number) { - this.setState({nextHeaderLayoutY: y}); - } + const offset = useMemo( + () => + hiddenOnScroll === true + ? Animated.diffClamp( + scrollAnimatedValue + .interpolate({ + extrapolateLeft: 'clamp', + inputRange: [layoutY, layoutY + 1], + outputRange: ([0, 1]: Array), + }) + .interpolate({ + inputRange: [0, 1], + outputRange: ([0, -1]: Array), + }), + -layoutHeight, + 0, + ) + : null, + [scrollAnimatedValue, layoutHeight, layoutY, hiddenOnScroll], + ); - UNSAFE_componentWillReceiveProps(nextProps: Props) { - if ( - nextProps.scrollViewHeight !== this.props.scrollViewHeight || - nextProps.scrollAnimatedValue !== this.props.scrollAnimatedValue || - nextProps.inverted !== this.props.inverted - ) { - this._shouldRecreateTranslateY = true; - } - } + const [ + animatedTranslateY, + setAnimatedTranslateY, + ] = React.useState(() => { + const inputRange: Array = [-1, 0]; + const outputRange: Array = [0, 0]; + const initialTranslateY: Animated.Interpolation = scrollAnimatedValue.interpolate( + { + inputRange, + outputRange, + }, + ); - updateTranslateListener( - translateY: AnimatedImplementation.Interpolation, - isFabric: boolean, - ) { - if (this._translateY != null && this._animatedValueListenerId != null) { - this._translateY.removeListener(this._animatedValueListenerId); + if (offset != null) { + return Animated.add(initialTranslateY, offset); } + return initialTranslateY; + }); - this._translateY = translateY; - this._shouldRecreateTranslateY = false; + const _haveReceivedInitialZeroTranslateY = useRef(true); + const _timer = useRef(null); - if (!isFabric) { - return; + useEffect(() => { + if (translateY !== 0 && translateY != null) { + _haveReceivedInitialZeroTranslateY.current = false; } + }, [translateY]); - if (!this._animatedValueListener) { - // This is called whenever the (Interpolated) Animated Value - // updates, which is several times per frame during scrolling. - // To ensure that the Fabric ShadowTree has the most recent - // translate style of this node, we debounce the value and then - // pass it through to the underlying node during render. - // This is: - // 1. Only an issue in Fabric. - // 2. Worse in Android than iOS. In Android, but not iOS, you - // can touch and move your finger slightly and still trigger - // a "tap" event. In iOS, moving will cancel the tap in - // both Fabric and non-Fabric. On Android when you move - // your finger, the hit-detection moves from the Android - // platform to JS, so we need the ShadowTree to have knowledge - // of the current position. - this._animatedValueListener = ({value}) => { - // When the AnimatedInterpolation is recreated, it always initializes - // to a value of zero and emits a value change of 0 to its listeners. - if (value === 0 && !this._haveReceivedInitialZeroTranslateY) { - this._haveReceivedInitialZeroTranslateY = true; - return; - } - if (this._timer) { - clearTimeout(this._timer); + // This is called whenever the (Interpolated) Animated Value + // updates, which is several times per frame during scrolling. + // To ensure that the Fabric ShadowTree has the most recent + // translate style of this node, we debounce the value and then + // pass it through to the underlying node during render. + // This is: + // 1. Only an issue in Fabric. + // 2. Worse in Android than iOS. In Android, but not iOS, you + // can touch and move your finger slightly and still trigger + // a "tap" event. In iOS, moving will cancel the tap in + // both Fabric and non-Fabric. On Android when you move + // your finger, the hit-detection moves from the Android + // platform to JS, so we need the ShadowTree to have knowledge + // of the current position. + const animatedValueListener = useCallback( + ({value}) => { + const _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; + // When the AnimatedInterpolation is recreated, it always initializes + // to a value of zero and emits a value change of 0 to its listeners. + if (value === 0 && !_haveReceivedInitialZeroTranslateY.current) { + _haveReceivedInitialZeroTranslateY.current = true; + return; + } + if (_timer.current != null) { + clearTimeout(_timer.current); + } + _timer.current = setTimeout(() => { + if (value !== translateY) { + setTranslateY(value); } - this._timer = setTimeout(() => { - if (value !== this.state.translateY) { - this.setState({ - translateY: value, - }); - } - }, this._debounceTimeout); - }; - } - if (this.state.translateY !== 0 && this.state.translateY != null) { - this._haveReceivedInitialZeroTranslateY = false; - } - this._animatedValueListenerId = translateY.addListener( - this._animatedValueListener, - ); - } + }, _debounceTimeout); + }, + [translateY], + ); - _onLayout = event => { - const layoutY = event.nativeEvent.layout.y; - const layoutHeight = event.nativeEvent.layout.height; - const measured = true; + useEffect(() => { + const inputRange: Array = [-1, 0]; + const outputRange: Array = [0, 0]; - if ( - layoutY !== this.state.layoutY || - layoutHeight !== this.state.layoutHeight || - measured !== this.state.measured - ) { - this._shouldRecreateTranslateY = true; + if (measured) { + if (inverted === true) { + // The interpolation looks like: + // - Negative scroll: no translation + // - `stickStartPoint` is the point at which the header will start sticking. + // It is calculated using the ScrollView viewport height so it is a the bottom. + // - Headers that are in the initial viewport will never stick, `stickStartPoint` + // will be negative. + // - From 0 to `stickStartPoint` no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + if (scrollViewHeight != null) { + const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; + if (stickStartPoint > 0) { + inputRange.push(stickStartPoint); + outputRange.push(0); + inputRange.push(stickStartPoint + 1); + outputRange.push(1); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = + (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; + if (collisionPoint > stickStartPoint) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push( + collisionPoint - stickStartPoint, + collisionPoint - stickStartPoint, + ); + } + } + } + } else { + // The interpolation looks like: + // - Negative scroll: no translation + // - From 0 to the y of the header: no translation. This will cause the header + // to scroll normally until it reaches the top of the scroll view. + // - From header y to when the next header y hits the bottom edge of the header: translate + // equally to scroll. This will cause the header to stay at the top of the scroll view. + // - Past the collision with the next header y: no more translation. This will cause the + // header to continue scrolling up and make room for the next sticky header. + // In the case that there is no next header just translate equally to + // scroll indefinitely. + inputRange.push(layoutY); + outputRange.push(0); + // If the next sticky header has not loaded yet (probably windowing) or is the last + // we can just keep it sticked forever. + const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; + if (collisionPoint >= layoutY) { + inputRange.push(collisionPoint, collisionPoint + 1); + outputRange.push(collisionPoint - layoutY, collisionPoint - layoutY); + } else { + inputRange.push(layoutY + 1); + outputRange.push(1); + } + } } - this.setState({ - measured, - layoutY, - layoutHeight, + let newAnimatedTranslateY: Animated.Node = scrollAnimatedValue.interpolate({ + inputRange, + outputRange, }); - this.props.onLayout(event); - const child = React.Children.only(this.props.children); - if (child.props.onLayout) { - child.props.onLayout(event); + if (offset != null) { + newAnimatedTranslateY = Animated.add(newAnimatedTranslateY, offset); } - }; - - _setComponentRef = ref => { - this._ref = ref; - }; - render(): React.Node { - // Fabric Detection - const isFabric = !!( - // An internal transform mangles variables with leading "_" as private. - // eslint-disable-next-line dot-notation - (this._ref && this._ref['_internalInstanceHandle']?.stateNode?.canonical) - ); + // add the event listener + let animatedListenerId; + if (isFabric) { + animatedListenerId = newAnimatedTranslateY.addListener( + animatedValueListener, + ); + } - // Initially and in the case of updated props or layout, we - // recreate this interpolated value. Otherwise, we do not recreate - // when there are state changes. - if (this._shouldRecreateTranslateY) { - const {inverted, scrollViewHeight} = this.props; - const {measured, layoutHeight, layoutY, nextHeaderLayoutY} = this.state; - const inputRange: Array = [-1, 0]; - const outputRange: Array = [0, 0]; + setAnimatedTranslateY(newAnimatedTranslateY); - if (measured) { - if (inverted) { - // The interpolation looks like: - // - Negative scroll: no translation - // - `stickStartPoint` is the point at which the header will start sticking. - // It is calculated using the ScrollView viewport height so it is a the bottom. - // - Headers that are in the initial viewport will never stick, `stickStartPoint` - // will be negative. - // - From 0 to `stickStartPoint` no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From `stickStartPoint` to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - if (scrollViewHeight != null) { - const stickStartPoint = layoutY + layoutHeight - scrollViewHeight; - if (stickStartPoint > 0) { - inputRange.push(stickStartPoint); - outputRange.push(0); - inputRange.push(stickStartPoint + 1); - outputRange.push(1); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = - (nextHeaderLayoutY || 0) - layoutHeight - scrollViewHeight; - if (collisionPoint > stickStartPoint) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push( - collisionPoint - stickStartPoint, - collisionPoint - stickStartPoint, - ); - } - } - } - } else { - // The interpolation looks like: - // - Negative scroll: no translation - // - From 0 to the y of the header: no translation. This will cause the header - // to scroll normally until it reaches the top of the scroll view. - // - From header y to when the next header y hits the bottom edge of the header: translate - // equally to scroll. This will cause the header to stay at the top of the scroll view. - // - Past the collision with the next header y: no more translation. This will cause the - // header to continue scrolling up and make room for the next sticky header. - // In the case that there is no next header just translate equally to - // scroll indefinitely. - inputRange.push(layoutY); - outputRange.push(0); - // If the next sticky header has not loaded yet (probably windowing) or is the last - // we can just keep it sticked forever. - const collisionPoint = (nextHeaderLayoutY || 0) - layoutHeight; - if (collisionPoint >= layoutY) { - inputRange.push(collisionPoint, collisionPoint + 1); - outputRange.push( - collisionPoint - layoutY, - collisionPoint - layoutY, - ); - } else { - inputRange.push(layoutY + 1); - outputRange.push(1); - } - } + // clean up the event listener and timer + return () => { + if (animatedListenerId) { + newAnimatedTranslateY.removeListener(animatedListenerId); + } + if (_timer.current != null) { + clearTimeout(_timer.current); } + }; + }, [nextHeaderLayoutY, measured, layoutHeight, layoutY, scrollViewHeight, scrollAnimatedValue, inverted, offset, animatedValueListener, isFabric]); - this.updateTranslateListener( - this.props.scrollAnimatedValue.interpolate({ - inputRange, - outputRange, - }), - isFabric, - ); + const _onLayout = (event: LayoutEvent) => { + setLayoutY(event.nativeEvent.layout.y); + setLayoutHeight(event.nativeEvent.layout.height); + setMeasured(true); + + props.onLayout(event); + const child = React.Children.only(props.children); + if (child.props.onLayout) { + child.props.onLayout(event); } + }; - const child = React.Children.only(this.props.children); + const child = React.Children.only(props.children); - // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric - const passthroughAnimatedPropExplicitValues = - isFabric && this.state.translateY != null - ? { - style: {transform: [{translateY: this.state.translateY}]}, - } - : null; + // TODO T68319535: remove this if NativeAnimated is rewritten for Fabric + const passthroughAnimatedPropExplicitValues = + isFabric && translateY != null + ? { + style: {transform: [{translateY: translateY}]}, + } + : null; - return ( - - {React.cloneElement(child, { - style: styles.fill, // We transfer the child style to the wrapper. - onLayout: undefined, // we call this manually through our this._onLayout - })} - - ); - } -} + return ( + /* $FlowFixMe[prop-missing] passthroughAnimatedPropExplicitValues isn't properly + included in the Animated.View flow type. */ + + {React.cloneElement(child, { + style: styles.fill, // We transfer the child style to the wrapper. + onLayout: undefined, // we call this manually through our this._onLayout + })} + + ); +}); const styles = StyleSheet.create({ header: { @@ -298,4 +312,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = ScrollViewStickyHeader; +export default ScrollViewStickyHeaderWithForwardedRef; diff --git a/Libraries/Components/ScrollView/ScrollViewViewConfig.js b/Libraries/Components/ScrollView/ScrollViewViewConfig.js index b2a3a9246b343b..5b276d54fa0fe0 100644 --- a/Libraries/Components/ScrollView/ScrollViewViewConfig.js +++ b/Libraries/Components/ScrollView/ScrollViewViewConfig.js @@ -10,7 +10,7 @@ 'use strict'; -import type {GeneratedViewConfig} from '../../Utilities/registerGeneratedViewConfig'; +import type {PartialViewConfig} from '../../Renderer/shims/ReactNativeTypes'; const ScrollViewViewConfig = { uiViewClassName: 'RCTScrollView', @@ -24,19 +24,27 @@ const ScrollViewViewConfig = { alwaysBounceHorizontal: true, alwaysBounceVertical: true, automaticallyAdjustContentInsets: true, + automaticallyAdjustsScrollIndicatorInsets: true, bounces: true, bouncesZoom: true, canCancelContentTouches: true, centerContent: true, - contentInset: {diff: require('../../Utilities/differ/pointsDiffer')}, - contentOffset: {diff: require('../../Utilities/differ/pointsDiffer')}, + contentInset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, + contentOffset: { + diff: require('../../Utilities/differ/pointsDiffer'), + }, contentInsetAdjustmentBehavior: true, decelerationRate: true, directionalLockEnabled: true, disableIntervalMomentum: true, - endFillColor: {process: require('../../StyleSheet/processColor')}, + endFillColor: { + process: require('../../StyleSheet/processColor'), + }, fadingEdgeLength: true, indicatorStyle: true, + inverted: true, keyboardDismissMode: true, maintainVisibleContentPosition: true, maximumZoomScale: true, @@ -72,4 +80,4 @@ const ScrollViewViewConfig = { }, }; -module.exports = (ScrollViewViewConfig: GeneratedViewConfig); +module.exports = (ScrollViewViewConfig: PartialViewConfig); diff --git a/Libraries/Components/ScrollView/__tests__/ScrollView-test.js b/Libraries/Components/ScrollView/__tests__/ScrollView-test.js index fb7aa74a55703e..f2a7abe2c9f852 100644 --- a/Libraries/Components/ScrollView/__tests__/ScrollView-test.js +++ b/Libraries/Components/ScrollView/__tests__/ScrollView-test.js @@ -11,12 +11,12 @@ 'use strict'; -const React = require('react'); -const ScrollView = require('../ScrollView'); -const ReactNativeTestTools = require('../../../Utilities/ReactNativeTestTools'); -const ReactTestRenderer = require('react-test-renderer'); -const View = require('../../View/View'); -const Text = require('../../../Text/Text'); +import * as React from 'react'; +import ScrollView from '../ScrollView'; +import * as ReactNativeTestTools from '../../../Utilities/ReactNativeTestTools'; +import ReactTestRenderer from 'react-test-renderer'; +import View from '../../View/View'; +import Text from '../../../Text/Text'; describe('', () => { it('should render as expected', () => { @@ -48,4 +48,20 @@ describe('', () => { jest.fn().constructor, ); }); + it('getInnerViewRef for case where it returns a native view', () => { + jest.resetModules(); + jest.unmock('../ScrollView'); + + const scrollViewRef = React.createRef(null); + + ReactTestRenderer.create(); + + const innerViewRef = scrollViewRef.current.getInnerViewRef(); + + // This is checking if the ref acts like a host component. If we had an + // `isHostComponent(ref)` method, that would be preferred. + expect(innerViewRef.measure).toBeInstanceOf(jest.fn().constructor); + expect(innerViewRef.measureLayout).toBeInstanceOf(jest.fn().constructor); + expect(innerViewRef.measureInWindow).toBeInstanceOf(jest.fn().constructor); + }); }); diff --git a/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap b/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap index 47a15d64c9348e..6fb8cfb75c3c1b 100644 --- a/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap +++ b/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap @@ -36,21 +36,17 @@ exports[` should render as expected: should deep render when not m onTouchMove={[Function]} onTouchStart={[Function]} pagingEnabled={false} - scrollBarThumbImage={null} scrollViewRef={null} sendMomentumEvents={false} snapToEnd={true} snapToStart={true} style={ - Array [ - Object { - "flexDirection": "column", - "flexGrow": 1, - "flexShrink": 1, - "overflow": "scroll", - }, - undefined, - ] + Object { + "flexDirection": "column", + "flexGrow": 1, + "flexShrink": 1, + "overflow": "scroll", + } } > , /** @@ -29,6 +29,8 @@ type SegmentedControlIOSProps = $ReadOnly<{| selectedIndex?: ?number, /** * If false the user won't be able to interact with the control. + * + * The default value is true. */ enabled?: boolean, /** @@ -78,11 +80,6 @@ type Props = $ReadOnly<{| */ class SegmentedControlIOS extends React.Component { - static defaultProps = { - values: [], - enabled: true, - }; - _onChange = (event: SyntheticEvent) => { this.props.onChange && this.props.onChange(event); this.props.onValueChange && @@ -90,12 +87,21 @@ class SegmentedControlIOS extends React.Component { }; render() { - const {forwardedRef, onValueChange, style, ...props} = this.props; + const { + enabled, + forwardedRef, + onValueChange, + style, + values, + ...props + } = this.props; return ( ); @@ -117,7 +123,7 @@ const SegmentedControlIOSWithRef = React.forwardRef( }, ); -/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an - * error found when Flow v0.89 was deployed. To see the error, delete this - * comment and run Flow. */ +/* $FlowFixMe[cannot-resolve-name] (>=0.89.0 site=react_native_ios_fb) This + * comment suppresses an error found when Flow v0.89 was deployed. To see the + * error, delete this comment and run Flow. */ module.exports = (SegmentedControlIOSWithRef: NativeSegmentedControlIOS); diff --git a/Libraries/Components/SegmentedControlIOS/__tests__/SegmentedContolIOS-test.js b/Libraries/Components/SegmentedControlIOS/__tests__/SegmentedContolIOS-test.js new file mode 100644 index 00000000000000..605864bf697b88 --- /dev/null +++ b/Libraries/Components/SegmentedControlIOS/__tests__/SegmentedContolIOS-test.js @@ -0,0 +1,55 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @emails oncall+react_native + */ + +'use strict'; + +const React = require('react'); +const ReactTestRenderer = require('react-test-renderer'); + +const SegmentedControlIOS = require('../SegmentedControlIOS.ios'); + +describe('SegmentedControlIOS', () => { + it('renders the segmented control', () => { + const component = ReactTestRenderer.create(); + expect(component).not.toBeNull(); + }); + it('renders the segmented control with enabled default value', () => { + const component = ReactTestRenderer.create(); + expect(component.toTree().rendered.props.enabled).toBe(true); + expect(component).toMatchSnapshot(); + }); + it('renders the segmented control with enabled', () => { + const component = ReactTestRenderer.create( + , + ); + expect(component.toTree().rendered.props.enabled).toBe(true); + expect(component).toMatchSnapshot(); + }); + it('renders the segmented control with enabled set to false', () => { + const component = ReactTestRenderer.create( + , + ); + expect(component.toTree().rendered.props.enabled).toBe(false); + expect(component).toMatchSnapshot(); + }); + it('renders the segmented control with values default value', () => { + const component = ReactTestRenderer.create(); + expect(component.toTree().rendered.props.values).toEqual([]); + expect(component).toMatchSnapshot(); + }); + it('renders the segmented control with values', () => { + const values = ['One', 'Two']; + const component = ReactTestRenderer.create( + , + ); + expect(component.toTree().rendered.props.values).toBe(values); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/Libraries/Components/SegmentedControlIOS/__tests__/__snapshots__/SegmentedContolIOS-test.js.snap b/Libraries/Components/SegmentedControlIOS/__tests__/__snapshots__/SegmentedContolIOS-test.js.snap new file mode 100644 index 00000000000000..30195d27c7f857 --- /dev/null +++ b/Libraries/Components/SegmentedControlIOS/__tests__/__snapshots__/SegmentedContolIOS-test.js.snap @@ -0,0 +1,86 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SegmentedControlIOS renders the segmented control with enabled 1`] = ` + +`; + +exports[`SegmentedControlIOS renders the segmented control with enabled default value 1`] = ` + +`; + +exports[`SegmentedControlIOS renders the segmented control with enabled set to false 1`] = ` + +`; + +exports[`SegmentedControlIOS renders the segmented control with values 1`] = ` + +`; + +exports[`SegmentedControlIOS renders the segmented control with values default value 1`] = ` + +`; diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js index 784af7cc272750..1edf184c172ec9 100644 --- a/Libraries/Components/Slider/Slider.js +++ b/Libraries/Components/Slider/Slider.js @@ -8,18 +8,18 @@ * @flow strict-local */ -'use strict'; - -const Platform = require('../../Utilities/Platform'); +import * as React from 'react'; +import Platform from '../../Utilities/Platform'; import SliderNativeComponent from './SliderNativeComponent'; -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); +import StyleSheet, { + type ViewStyleProp, + type ColorValue, +} from '../../StyleSheet/StyleSheet'; import type {ImageSource} from '../../Image/ImageSource'; -import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; import type {ViewProps} from '../View/ViewPropTypes'; import type {SyntheticEvent} from '../../Types/CoreEventTypes'; +import type {AccessibilityState} from '../View/ViewAccessibility'; type Event = SyntheticEvent< $ReadOnly<{| @@ -132,10 +132,18 @@ type Props = $ReadOnly<{| * Used to locate this view in UI automation tests. */ testID?: ?string, + + // [ TODO(macOS GH#774) /** * Specifies the tooltip. */ tooltip?: ?string, + // TODO(macOS GH#774) ] + + /** + Indicates to accessibility services that UI Component is in a specific State. + */ + accessibilityState?: ?AccessibilityState, |}>; /** @@ -205,7 +213,6 @@ const Slider = ( const style = StyleSheet.compose(styles.slider, props.style); const { - disabled = false, value = 0.5, minimumValue = 0, maximumValue = 1, @@ -235,9 +242,16 @@ const Slider = ( } : null; + const disabled = + props.disabled === true || props.accessibilityState?.disabled === true; + const accessibilityState = disabled + ? {...props.accessibilityState, disabled: true} + : props.accessibilityState; + return ( { static _propsStack = []; static _defaultProps = createStackEntry({ - animated: false, - showHideTransition: 'fade', backgroundColor: Platform.OS === 'android' ? NativeStatusBarManagerAndroid.getConstants() @@ -387,14 +384,6 @@ class StatusBar extends React.Component { return newEntry; } - static defaultProps: {| - animated: boolean, - showHideTransition: $TEMPORARY$string<'fade'>, - |} = { - animated: false, - showHideTransition: 'fade', - }; - _stackEntry = null; componentDidMount() { diff --git a/Libraries/Components/StatusBar/StatusBarIOS.js b/Libraries/Components/StatusBar/StatusBarIOS.js deleted file mode 100644 index ccc561103f187c..00000000000000 --- a/Libraries/Components/StatusBar/StatusBarIOS.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -'use strict'; - -import NativeEventEmitter from '../../EventEmitter/NativeEventEmitter'; -import NativeStatusBarManagerIOS from './NativeStatusBarManagerIOS'; - -/** - * Use `StatusBar` for mutating the status bar. - */ -class StatusBarIOS extends NativeEventEmitter {} - -module.exports = (new StatusBarIOS(NativeStatusBarManagerIOS): StatusBarIOS); diff --git a/Libraries/Components/StatusBar/__tests__/StatusBar-test.js b/Libraries/Components/StatusBar/__tests__/StatusBar-test.js new file mode 100644 index 00000000000000..a75d4fc1b0d31c --- /dev/null +++ b/Libraries/Components/StatusBar/__tests__/StatusBar-test.js @@ -0,0 +1,62 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @emails oncall+react_native + */ + +'use strict'; + +const React = require('react'); +const ReactTestRenderer = require('react-test-renderer'); + +const StatusBar = require('../StatusBar'); + +describe('StatusBar', () => { + it('renders the statusbar', () => { + const component = ReactTestRenderer.create(); + expect(component).not.toBeNull(); + }); + it('renders the statusbar animated enabled', () => { + const component = ReactTestRenderer.create(); + expect(component.toTree().props.animated).toBe(true); + }); + it('renders the statusbar with fade transition on hide', () => { + const component = ReactTestRenderer.create( `; + +exports[`TouchableHighlight with disabled state should be disabled when disabled is true 1`] = ` + + + +`; + +exports[`TouchableHighlight with disabled state should be disabled when disabled is true and accessibilityState is empty 1`] = ` + + + +`; + +exports[`TouchableHighlight with disabled state should disable button when accessibilityState is disabled 1`] = ` + + + +`; + +exports[`TouchableHighlight with disabled state should keep accessibilityState when disabled is true 1`] = ` + + + +`; + +exports[`TouchableHighlight with disabled state should overwrite accessibilityState with value of disabled prop 1`] = ` + + + +`; diff --git a/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableNativeFeedback-test.js.snap b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableNativeFeedback-test.js.snap new file mode 100644 index 00000000000000..4c9f7b2c846993 --- /dev/null +++ b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableNativeFeedback-test.js.snap @@ -0,0 +1,141 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should render as expected 1`] = ` + +`; + +exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` + +`; + +exports[` should be disabled when disabled is true and accessibilityState is empty 1`] = ` + +`; + +exports[` should keep accessibilityState when disabled is true 1`] = ` + +`; + +exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` + +`; + +exports[` should be disabled when disabled is true 1`] = ` + +`; + +exports[`TouchableWithoutFeedback renders correctly 1`] = ` + + Touchable + +`; diff --git a/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap new file mode 100644 index 00000000000000..d72c557b33faba --- /dev/null +++ b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TouchableOpacity renders correctly 1`] = ` + + + Touchable + + +`; + +exports[`TouchableOpacity renders in disabled state when a disabled prop is passed 1`] = ` + + + Touchable + + +`; + +exports[`TouchableOpacity renders in disabled state when a key disabled in accessibilityState is passed 1`] = ` + + + Touchable + + +`; diff --git a/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableWithoutFeedback-test.js.snap b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableWithoutFeedback-test.js.snap new file mode 100644 index 00000000000000..9dfeb4e6d44ce5 --- /dev/null +++ b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableWithoutFeedback-test.js.snap @@ -0,0 +1,137 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TouchableWithoutFeedback renders correctly 1`] = ` + + Touchable + +`; + +exports[`TouchableWithoutFeedback with disabled state should be disabled when disabled is true 1`] = ` + +`; + +exports[`TouchableWithoutFeedback with disabled state should be disabled when disabled is true and accessibilityState is empty 1`] = ` + +`; + +exports[`TouchableWithoutFeedback with disabled state should disable button when accessibilityState is disabled 1`] = ` + +`; + +exports[`TouchableWithoutFeedback with disabled state should keep accessibilityState when disabled is true 1`] = ` + +`; + +exports[`TouchableWithoutFeedback with disabled state should overwrite accessibilityState with value of disabled prop 1`] = ` + +`; diff --git a/Libraries/Components/Touchable/ensurePositiveDelayProps.js b/Libraries/Components/Touchable/ensurePositiveDelayProps.js index 69dad5539faf2b..bd9b3028399cd0 100644 --- a/Libraries/Components/Touchable/ensurePositiveDelayProps.js +++ b/Libraries/Components/Touchable/ensurePositiveDelayProps.js @@ -9,8 +9,7 @@ */ 'use strict'; - -const invariant = require('invariant'); +import invariant from 'invariant'; const ensurePositiveDelayProps = function(props: any) { invariant( diff --git a/Libraries/Components/UnimplementedViews/UnimplementedNativeViewNativeComponent.js b/Libraries/Components/UnimplementedViews/UnimplementedNativeViewNativeComponent.js index 796650fefc53e3..2a2969905bc65d 100644 --- a/Libraries/Components/UnimplementedViews/UnimplementedNativeViewNativeComponent.js +++ b/Libraries/Components/UnimplementedViews/UnimplementedNativeViewNativeComponent.js @@ -8,8 +8,6 @@ * @flow strict-local */ -'use strict'; - import type {WithDefault} from '../../Types/CodegenTypes'; import type {ViewProps} from '../View/ViewPropTypes'; diff --git a/Libraries/Components/UnimplementedViews/UnimplementedView.js b/Libraries/Components/UnimplementedViews/UnimplementedView.js index 58804b7a772583..4bbb41060ff32f 100644 --- a/Libraries/Components/UnimplementedViews/UnimplementedView.js +++ b/Libraries/Components/UnimplementedViews/UnimplementedView.js @@ -9,9 +9,8 @@ */ 'use strict'; - -const React = require('react'); -const StyleSheet = require('../../StyleSheet/StyleSheet'); +import * as React from 'react'; +import StyleSheet from '../../StyleSheet/StyleSheet'; /** * Common implementation for a simple stubbed view. Simply applies the view's styles to the inner diff --git a/Libraries/Components/View/ReactNativeStyleAttributes.js b/Libraries/Components/View/ReactNativeStyleAttributes.js index ebd3c63df5614b..9f87352219ef2b 100644 --- a/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -8,80 +8,145 @@ * @flow */ -'use strict'; +import type {AnyAttributeType} from '../../Renderer/shims/ReactNativeTypes'; +import processColor from '../../StyleSheet/processColor'; +import processTransform from '../../StyleSheet/processTransform'; +import sizesDiffer from '../../Utilities/differ/sizesDiffer'; -const DeprecatedImageStylePropTypes = require('../../DeprecatedPropTypes/DeprecatedImageStylePropTypes'); -const DeprecatedTextStylePropTypes = require('../../DeprecatedPropTypes/DeprecatedTextStylePropTypes'); -const DeprecatedViewStylePropTypes = require('../../DeprecatedPropTypes/DeprecatedViewStylePropTypes'); - -const processColor = require('../../StyleSheet/processColor'); -const processTransform = require('../../StyleSheet/processTransform'); -const sizesDiffer = require('../../Utilities/differ/sizesDiffer'); +const colorAttributes = {process: processColor}; -type ReturnBoolType = (V) => true; -type BoolifiedDeprecatedViewStylePropTypes = $ObjMap< - typeof DeprecatedViewStylePropTypes, - ReturnBoolType, ->; -type BoolifiedDeprecatedTextStylePropTypes = $ObjMapi< - typeof DeprecatedTextStylePropTypes, - ReturnBoolType, ->; -type BoolifiedDeprecatedImageStylePropTypes = $ObjMapi< - typeof DeprecatedImageStylePropTypes, - ReturnBoolType, ->; +const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { + /** + * Layout + */ + alignContent: true, + alignItems: true, + alignSelf: true, + aspectRatio: true, + borderBottomWidth: true, + borderEndWidth: true, + borderLeftWidth: true, + borderRightWidth: true, + borderStartWidth: true, + borderTopWidth: true, + borderWidth: true, + bottom: true, + direction: true, + display: true, + end: true, + flex: true, + flexBasis: true, + flexDirection: true, + flexGrow: true, + flexShrink: true, + flexWrap: true, + height: true, + justifyContent: true, + left: true, + margin: true, + marginBottom: true, + marginEnd: true, + marginHorizontal: true, + marginLeft: true, + marginRight: true, + marginStart: true, + marginTop: true, + marginVertical: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + overflow: true, + padding: true, + paddingBottom: true, + paddingEnd: true, + paddingHorizontal: true, + paddingLeft: true, + paddingRight: true, + paddingStart: true, + paddingTop: true, + paddingVertical: true, + position: true, + right: true, + start: true, + top: true, + width: true, + zIndex: true, -type StyleAttributesType = { - ...BoolifiedDeprecatedViewStylePropTypes, - ...BoolifiedDeprecatedTextStylePropTypes, - ...BoolifiedDeprecatedImageStylePropTypes, - transform: $ReadOnly<{|process: typeof processTransform|}> | true, - shadowOffset: $ReadOnly<{|diff: typeof sizesDiffer|}> | true, - backgroundColor: typeof colorAttributes | true, - borderBottomColor: typeof colorAttributes | true, - borderColor: typeof colorAttributes | true, - borderLeftColor: typeof colorAttributes | true, - borderRightColor: typeof colorAttributes | true, - borderTopColor: typeof colorAttributes | true, - borderStartColor: typeof colorAttributes | true, - borderEndColor: typeof colorAttributes | true, - color: typeof colorAttributes | true, - shadowColor: typeof colorAttributes | true, - textDecorationColor: typeof colorAttributes | true, - tintColor: typeof colorAttributes | true, - textShadowColor: typeof colorAttributes | true, - overlayColor: typeof colorAttributes | true, - ... -}; + /** + * Shadow + */ + elevation: true, + shadowColor: colorAttributes, + shadowOffset: {diff: sizesDiffer}, + shadowOpacity: true, + shadowRadius: true, -const ReactNativeStyleAttributes: StyleAttributesType = {}; + /** + * Transform + */ + decomposedMatrix: true, // @deprecated + rotation: true, // @deprecated + scaleX: true, // @deprecated + scaleY: true, // @deprecated + transform: {process: processTransform}, + transformMatrix: true, // @deprecated + translateX: true, // @deprecated + translateY: true, // @deprecated -for (const attributeName of Object.keys({ - ...DeprecatedViewStylePropTypes, - ...DeprecatedTextStylePropTypes, - ...DeprecatedImageStylePropTypes, -})) { - ReactNativeStyleAttributes[attributeName] = true; -} + /** + * View + */ + backfaceVisibility: true, + backgroundColor: colorAttributes, + borderBottomColor: colorAttributes, + borderBottomEndRadius: true, + borderBottomLeftRadius: true, + borderBottomRightRadius: true, + borderBottomStartRadius: true, + borderColor: colorAttributes, + borderEndColor: colorAttributes, + borderLeftColor: colorAttributes, + borderRadius: true, + borderRightColor: colorAttributes, + borderStartColor: colorAttributes, + borderStyle: true, + borderTopColor: colorAttributes, + borderTopEndRadius: true, + borderTopLeftRadius: true, + borderTopRightRadius: true, + borderTopStartRadius: true, + opacity: true, -ReactNativeStyleAttributes.transform = {process: processTransform}; -ReactNativeStyleAttributes.shadowOffset = {diff: sizesDiffer}; + /** + * Text + */ + color: colorAttributes, + fontFamily: true, + fontSize: true, + fontStyle: true, + fontVariant: true, + fontWeight: true, + includeFontPadding: true, + letterSpacing: true, + lineHeight: true, + textAlign: true, + textAlignVertical: true, + textDecorationColor: colorAttributes, + textDecorationLine: true, + textDecorationStyle: true, + textShadowColor: colorAttributes, + textShadowOffset: true, + textShadowRadius: true, + textTransform: true, + writingDirection: true, -const colorAttributes = {process: processColor}; -ReactNativeStyleAttributes.backgroundColor = colorAttributes; -ReactNativeStyleAttributes.borderBottomColor = colorAttributes; -ReactNativeStyleAttributes.borderColor = colorAttributes; -ReactNativeStyleAttributes.borderLeftColor = colorAttributes; -ReactNativeStyleAttributes.borderRightColor = colorAttributes; -ReactNativeStyleAttributes.borderTopColor = colorAttributes; -ReactNativeStyleAttributes.borderStartColor = colorAttributes; -ReactNativeStyleAttributes.borderEndColor = colorAttributes; -ReactNativeStyleAttributes.color = colorAttributes; -ReactNativeStyleAttributes.shadowColor = colorAttributes; -ReactNativeStyleAttributes.textDecorationColor = colorAttributes; -ReactNativeStyleAttributes.tintColor = colorAttributes; -ReactNativeStyleAttributes.textShadowColor = colorAttributes; -ReactNativeStyleAttributes.overlayColor = colorAttributes; + /** + * Image + */ + overlayColor: colorAttributes, + resizeMode: true, + tintColor: colorAttributes, +}; module.exports = ReactNativeStyleAttributes; diff --git a/Libraries/Components/View/ReactNativeViewAttributes.js b/Libraries/Components/View/ReactNativeViewAttributes.js index 7f9452fc9447ec..2e5ffda73f9105 100644 --- a/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/Libraries/Components/View/ReactNativeViewAttributes.js @@ -9,8 +9,7 @@ */ 'use strict'; - -const ReactNativeStyleAttributes = require('./ReactNativeStyleAttributes'); +import ReactNativeStyleAttributes from './ReactNativeStyleAttributes'; const UIView = { pointerEvents: true, diff --git a/Libraries/Components/View/ReactNativeViewViewConfig.js b/Libraries/Components/View/ReactNativeViewViewConfig.js index 4e0c813f71357b..0a3a27ac0370df 100644 --- a/Libraries/Components/View/ReactNativeViewViewConfig.js +++ b/Libraries/Components/View/ReactNativeViewViewConfig.js @@ -8,17 +8,17 @@ * @format */ -'use strict'; +import type {ViewConfig} from '../../Renderer/shims/ReactNativeTypes'; import ReactNativeViewViewConfigAndroid from './ReactNativeViewViewConfigAndroid'; import ReactNativeViewViewConfigMacOS from './ReactNativeViewViewConfigMacOS'; // TODO(macOS GH#774) import {Platform} from 'react-native'; -const ReactNativeViewConfig = { +const ReactNativeViewConfig: ViewConfig = { uiViewClassName: 'RCTView', baseModuleName: null, Manager: 'ViewManager', - Commands: ({}: {...}), - Constants: ({}: {...}), + Commands: {}, + Constants: {}, bubblingEventTypes: { ...ReactNativeViewViewConfigAndroid.bubblingEventTypes, topBlur: { @@ -180,7 +180,7 @@ const ReactNativeViewConfig = { flexShrink: true, flexWrap: true, height: true, - hitSlop: {diff: (require('../../Utilities/differ/insetsDiffer'): any)}, + hitSlop: {diff: require('../../Utilities/differ/insetsDiffer')}, importantForAccessibility: true, justifyContent: true, left: true, @@ -332,9 +332,10 @@ const ReactNativeViewConfig = { textTransform: true, tintColor: {process: require('../../StyleSheet/processColor')}, top: true, - transform: ((Platform.OS === 'ios' || Platform.OS === 'macos' // TODO(macOS GH#774) - ? {diff: require('../../Utilities/differ/matricesDiffer')} - : {process: require('../../StyleSheet/processTransform')}): any), + transform: + Platform.OS === 'ios' || Platform.OS === 'macos' // TODO(macOS GH#774) + ? {diff: require('../../Utilities/differ/matricesDiffer')} + : {process: require('../../StyleSheet/processTransform')}, transformMatrix: true, translateX: true, translateY: true, @@ -344,9 +345,10 @@ const ReactNativeViewConfig = { }, testID: true, top: true, - transform: ((Platform.OS === 'ios' || Platform.OS === 'macos' // TODO(macOS GH#774) - ? {diff: require('../../Utilities/differ/matricesDiffer')} - : {process: require('../../StyleSheet/processTransform')}): any), + transform: + Platform.OS === 'ios' || Platform.OS === 'macos' // TODO(macOS GH#774) + ? {diff: require('../../Utilities/differ/matricesDiffer')} + : {process: require('../../StyleSheet/processTransform')}, translateX: true, translateY: true, validKeysDown: true, diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index c221e4991bc753..a1b7a7abb277ed 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -8,14 +8,12 @@ * @flow strict-local */ -'use strict'; - import type {ViewProps} from './ViewPropTypes'; -const React = require('react'); import ViewNativeComponent from './ViewNativeComponent'; -const TextAncestor = require('../../Text/TextAncestor'); +import TextAncestor from '../../Text/TextAncestor'; import warnOnce from '../../Utilities/warnOnce'; // [macOS #656] +import * as React from 'react'; export type Props = ViewProps; diff --git a/Libraries/Components/View/ViewAccessibility.js b/Libraries/Components/View/ViewAccessibility.js index 485b208b411fb4..9c056b64c9c753 100644 --- a/Libraries/Components/View/ViewAccessibility.js +++ b/Libraries/Components/View/ViewAccessibility.js @@ -21,6 +21,7 @@ export type AccessibilityNodeInfoProp = { export type AccessibilityRole = | 'none' | 'button' + | 'togglebutton' | 'link' | 'search' | 'image' @@ -43,11 +44,13 @@ export type AccessibilityRole = | 'spinbutton' | 'switch' | 'tab' + | 'tabbar' | 'tablist' | 'timer' + | 'list' | 'toolbar' | 'popupbutton' - | 'menubutton'; + | 'menubutton'; // TODO(macOS GH#774) // the info associated with an accessibility action export type AccessibilityActionInfo = $ReadOnly<{ diff --git a/Libraries/Components/View/ViewNativeComponent.js b/Libraries/Components/View/ViewNativeComponent.js index 902414c4eb45e3..4ca5ec9cf3c479 100644 --- a/Libraries/Components/View/ViewNativeComponent.js +++ b/Libraries/Components/View/ViewNativeComponent.js @@ -4,72 +4,25 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict-local * @format - * @flow */ -'use strict'; - -const Platform = require('../../Utilities/Platform'); -const ReactNativeViewViewConfigAndroid = require('./ReactNativeViewViewConfigAndroid'); - -const registerGeneratedViewConfig = require('../../Utilities/registerGeneratedViewConfig'); -const requireNativeComponent = require('../../ReactNative/requireNativeComponent'); - -import * as React from 'react'; - +import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry'; +import {type HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import Platform from '../../Utilities/Platform'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; -import type {ViewProps} from './ViewPropTypes'; -import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; - -export type ViewNativeComponentType = HostComponent; - -let NativeViewComponent; -let viewConfig: - | {...} - | {| - bubblingEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{| - phasedRegistrationNames: $ReadOnly<{| - bubbled: string, - captured: string, - |}>, - |}>, - ..., - }>, - directEventTypes?: $ReadOnly<{ - [eventName: string]: $ReadOnly<{|registrationName: string|}>, - ..., - }>, - uiViewClassName: string, - validAttributes?: { - [propName: string]: - | true - | $ReadOnly<{| - diff?: (arg1: any, arg2: any) => boolean, - process?: (arg1: any) => any, - |}>, - ..., - }, - |}; - -if (__DEV__ || global.RN$Bridgeless) { - // On Android, View extends the base component with additional view-only props - // On iOS, the base component is View - if (Platform.OS === 'android') { - viewConfig = ReactNativeViewViewConfigAndroid; - registerGeneratedViewConfig('RCTView', ReactNativeViewViewConfigAndroid); - } else { - viewConfig = {}; - registerGeneratedViewConfig('RCTView', {uiViewClassName: 'RCTView'}); - } - - NativeViewComponent = 'RCTView'; -} else { - NativeViewComponent = requireNativeComponent('RCTView'); -} +import ReactNativeViewViewConfigAndroid from './ReactNativeViewViewConfigAndroid'; +import {type ViewProps as Props} from './ViewPropTypes'; +import * as React from 'react'; -export const __INTERNAL_VIEW_CONFIG = viewConfig; +const ViewNativeComponent: HostComponent = NativeComponentRegistry.get( + 'RCTView', + () => + Platform.OS === 'android' + ? ReactNativeViewViewConfigAndroid + : {uiViewClassName: 'RCTView'}, +); interface NativeCommands { +hotspotUpdate: ( @@ -87,4 +40,6 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['hotspotUpdate', 'setPressed'], }); -export default ((NativeViewComponent: any): ViewNativeComponentType); +export default ViewNativeComponent; + +export type ViewNativeComponentType = HostComponent; diff --git a/Libraries/Components/__tests__/Button-test.js b/Libraries/Components/__tests__/Button-test.js new file mode 100644 index 00000000000000..f81f9bc63d229e --- /dev/null +++ b/Libraries/Components/__tests__/Button-test.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as React from 'react'; +import ReactTestRenderer from 'react-test-renderer'; +import Button from '../Button'; + +describe('